Download email attachments from outlook using powershell - powershell

I am using following code to download outlook email attachments and images to folder. But it is throwing an error:
Cannot index into a null array.
Any guess why?
$o = New-Object -ComObject outlook.Application
$ns = $o.GetNamespace("MAPI")
$f = $ns.Folders.Item(1)
$di = $f.Folders.item("Deleted Items")
$messagesWithAttachments = $di.items | Where-Object {$_.Attachments.Count -gt 0}
$messagesWithAttachments[0].Attachments.item(1).saveasfile("C:\test")

Provided there are emails with attachments, give a filename instead of folder in the saveasfile() method.
Eg: saveasfile("C:\test\test.txt")

Related

Using Restrict + Filter on ReceivedTime still returns everything in Outlook Inbox

This code returns everything in the Inbox - how to redo the Filter ?
$objOutlook = new-object -comObject Outlook.Application
$namespace = $objOutlook.GetNameSpace("MAPI")
$InboxFolder = $namespace.GetDefaultFolder(6)
$DateYest = (Get-Date).AddDays(-2)
$Filter = "[ReceivedTime] -gt '$DateYest'"
$InboxFolderFiltered = $InboxFolder.Items.Restrict($Filter)
ForEach ($MailItem in $InboxFolderFiltered){
write-host $MailItem.ReceivedTime
}
Firstly, "-gt" is not a valid operator , use ">".
Secondly, the date/time values must be properly formatted, but your code is relying on the default conversion to string.
See https://learn.microsoft.com/en-us/office/vba/api/outlook.items.restrict for examples.

olFolderInbox returns incomplete result

I'm trying to write a PowerShell script that automates the way to retrieve all my emails with sender information in outlook and importing it on a text file.
I monitored this script that I created returns incomplete results.
Below here is my code for:
$namespace = $Outlook.GetNameSpace("MAPI")
$inbox = $namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)
$emails = $inbox.items
ForEach ($email in $emails){
write-host $email.Subject
}
If "incomplete results" means that it's not returning all the emails you're expecting, there are a couple of things that I ran into when working with emails in Powershell:
It won't grab emails that are in folders under the Inbox. You have to call each folder separately. I had to setup a recusive loop to compile a list of them
Not all of your emails are actually stored in Outlook. By default, Outlook only pulls the last year of email form an email server. Sometimes it can show messages that exist on the server but they aren't actually downloaded.
EDIT: Here's the recursive function I built to get all the folders and subfolders within the Inbox.
# Create an ArrayList and immediately add the Inbox as the first folder in the list
[System.Collections.ArrayList] $folderList = #([PSCustomObject]#{
FolderPath = $inbox.FolderPath
EntryID = $inbox.EntryID
})
# Call the function to get all the folders and subfolders in the Inbox folder
Get-MailFolders $inbox.Folders
# Recusive function that will get all the folders and subfolders in the parent folder
function Get-MailFolders ($parent) {
foreach ($child in $parent) {
Write-Host "." -NoNewLine
$folderList.Add([PSCustomObject]#{
FolderPath = $child.FolderPath
EntryID = $child.EntryID
}) | Out-Null
Get-MailFolders ($child.Folders)
}
}
Continuing form my comment
Search for:
'PowerShell read outlook email name and subject'
hit(s)
https://devblogs.microsoft.com/scripting/use-powershell-to-data-mine-your-outlook-inbox
Read most recent e-mail from outlook using PowerShell
http://jon.glass/blog/reads-e-mail-with-powershell
olFolderInbox = 6
$outlook = new-object -com outlook.application;
$mapi = $outlook.GetNameSpace("MAPI");
$inbox = $mapi.GetDefaultFolder($olFolderInbox)
# Grab the specific properties from the messages in the Inbox:
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$mapi = $outlook.GetNameSpace("MAPI");
$inbox = $mapi.GetDefaultFolder($olFolderInbox)
$inbox.items|Select SenderEmailAddress,to,subject|Format-Table -AutoSize
# Results
<#
SenderEmailAddress To Subject
------------------ -- -------
notify#twitter.com Jonathan Glass Thomas Garnier (#mxatone) retweeted one...
mailing-list#rifftrax.com Riff Rediscover Puppets in our latest short!
notify#twitter.com Jonathan Glass [ Gunther ] (#Gunther_AR) retweeted one...
#>

Copy Items in Outlook Using PowerShell

I am trying to copy some items from "Inbox" to "Sent Items\TEMP" in Outlook. So far I was able to pick up desired messages, based on the subject line, but then I try to copy them with no success. Where am I going wrong? Thanks! Please note, when i do a write-host to retrieve the item I'm looking for, it comes up with no issues, so I am able to retrieve the email with subject line of "Test", but not copy it.
Error message:
Cannot find an overload for "Copy" and the argument count: "1"
Code:
$outlook = New-Object -comobject outlook.application;
$mapi = $outlook.GetNamespace('MAPI').GetDefaultFolder(6);
$mapi2 = $outlook.GetNamespace('MAPI').GetDefaultFolder(5);
$subFolders2 = $mapi.Folders | ? {$_.FolderPath.EndsWith('TEMP')};
$mapi.Items | ForEach-Object {If ($_.Subject -Like '*TEst*'){$_.Copy($subFolders2)}$_.Save()}
MailItem.Copy does not take any parameters. It returns an instance of the MailItem object; you can then call MailItem.Move and pass the pointer to the destination folder.

Outlook Interop Folder.CopyTo Method - Merge Inbox

I'm Trying to copy Mail Items from one mailbox to another, but when i use the Folder.Copy Method to copy the Inbox folder of one mailbox to the other, it's not merge the data but creating Folder Named Inbox1,
Here's my code:
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace("mapi")
$namespace.Logon("Outlook")
$LocalStore = $Namespace.Stores[3]
$RemoteStore = $Namespace.Stores[1]
$LocalFolders = $LocalStore.GetRootFolder().folders
$RemoteFolders = $RemoteStore.GetRootFolder().folders
$RemoteInbox = $RemoteFolders | ? {$_.Name -eq "Inbox"}
$LocalInbox = $LocalFolders | ? {$_.Name -eq "Inbox"}
$RemoteInbox.CopyTo($LocalInbox.Parent)
To workaround i can use the Items Copy :
Foreach ($Item in $RemoteInbox.Items)
{
$Copy = $Item.Copy()
[void]$Copy.Move($TargetFolder)
}
But it's much slower, and if i have subfolders it need special care with extra code,
Search the web with no solution found
Any help is appreciated
This is to be expected - if there is already an existing folder with the same name, MAPI will return MAPI_E_COLLISION - see IMAPIFolder::CopyFolder.
Outlook detects that error and creates a folder with a unique name.
You can copy items in a batch using IMAPIFolder.CopyMessages, but Extended MAPI requires C++ or Delphi. If using Redemption is an option (I am its author), you can use its RDOItems.CopyMultiple method. You can create an array of entry ids from the source folder using RDOItems.MAPITable.ExecSQL and pass it to RDOItems.CopyMultiple.

Moving Emails to subfolder with Powershell

I am trying to write the sender/subject info of all the emails in my outlook inbox to a csv file and then move the emails to a subfolder of my inbox (called "After") using Powershell. The CSV file is created correctly with the email info, but only the first half + 1 emails are actually moved to the subfolder. Here is my code:
$olFolderInbox = 6;
$outlook = new-object -com outlook.application;
$mapi = $outlook.GetNameSpace("MAPI");
$inbox = $mapi.GetDefaultFolder($olFolderInbox);
$inbox.items|Select SenderEmailAddress,subject|Export-Csv C:\Scripts\Testing.csv -NoTypeInformation;
ForEach ($Item in $inbox.items){
try{
$Item.Move($inbox.Folders.Item("After")) | out-null;
}catch{
Write-Host "Failed to move item", $Item.Id.UniqueId;
}
}
This is my first time using Powershell so any help is much appreciated!
Move() changes the collection. Use a down "for" loop (from items.Count down to 1) instead of "foreach".