none
Save Attachments with EWS and PowerShell Exchange 2010 RRS feed

  • Question

  • Hello,



    My problem is:

    if a mail comes from a specific address (or has a specific word in the subject) the attachments should be saved to the file system and then the mail should be moved to a mailfolder.

    With Google  i found the Blog from Glen and this help me a lot.

    this is my current code:

    $MailboxName = "intern@mail.at"
    $Subject = "order"
    $ProcessedFolderPath = "/Posteingang/Bestellung"
    $downloadDirectory = "\\Fileserver\order"
    
    Function FindTargetFolder($FolderPath){
    	$tfTargetidRoot = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
    	$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$tfTargetidRoot)
    	$pfArray = $FolderPath.Split("/")
    	for ($lint = 1; $lint -lt $pfArray.Length; $lint++) {
    		$pfArray[$lint]
    		$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
    		$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$pfArray[$lint])
                    $findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
    		if ($findFolderResults.TotalCount -gt 0){
    			foreach($folder in $findFolderResults.Folders){
    				$tfTargetFolder = $folder				
    			}
    		}
    		else{
    			"Error Folder Not Found"
    			$tfTargetFolder = $null
    			break
    		}	
    	}
    	$Global:findFolder = $tfTargetFolder
    }
    
    $dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
    [void][Reflection.Assembly]::LoadFile($dllpath)
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
    
    $windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
    $aceuser = [ADSI]$sidbind
    
    $service.AutodiscoverUrl($aceuser.mail.ToString())
    
    FindTargetFolder($ProcessedFolderPath)
    
    $folderid = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
    $InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
    $Sfir = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead, $false)
    $Sfsub = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, $Subject)
    $Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::HasAttachments, $true)
    $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
    $sfCollection.add($Sfir)
    $sfCollection.add($Sfsub)
    $sfCollection.add($Sfha)
    $view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000)
    $frFolderResult = $InboxFolder.FindItems($sfCollection,$view)
    
    foreach ($miMailItems in $frFolderResult.Items){
    	$miMailItems.Subject
    	$miMailItems.Load()
    	foreach($attach in $miMailItems.Attachments){
    	$attach.Load()
    		$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + $attach.Name.ToString()), [System.IO.FileMode]::Create)
    		$fiFile.Write($attach.Content, 0, $attach.Content.Length)
    		$fiFile.Close()
    		write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + $attach.Name.ToString()))
    	}
    	$miMailItems.isread = $true
    	$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
    [VOID]$miMailItems.Move($Global:findFolder.Id.UniqueId)
    }

    It makes the Mail unread und save the attachment but it dont move the Mail.

    The Error Code:

    PS C:\Users\> C:\Users\\Desktop\Order.ps1
    Posteingang
    Bestellungen
    Downloaded Attachment :  + \\Fileserver\Order\order.csv
    Das Argument "destinationFolderName" mit dem Wert  
    "AQMkADllZmM0ODBjLWI0YTctNDBmMi05YjcxLTE0MTNmNTdmMDlmNAAuAAADw4U9KEGWoUWmYMBIcUC/mAEAZE0gf4E0qE2I6d4blYYxBgB4TvgAOwAAAA==" für "Move" kann nicht in den Typ 
    "Microsoft.Exchange.WebServices.Data.WellKnownFolderName" konvertiert werden: "Der Wert 
    "AQMkADllZmM0ODBjLWI0YTctNDBmMi05YjcxLTE0MTNmNTdmMDlmNAAuAAADw4U9KEGWoUWmYMBIcUC/mAEAZE0gf4E0qE2I6d4blYYxBgB4TvgAOwAAAA==" kann nicht in den Typ 
    "Microsoft.Exchange.WebServices.Data.WellKnownFolderName" konvertiert werden. Fehler: "Der Bezeichner 
    "AQMkADllZmM0ODBjLWI0YTctNDBmMi05YjcxLTE0MTNmNTdmMDlmNAAuAAADw4U9KEGWoUWmYMBIcUC/mAEAZE0gf4E0qE2I6d4blYYxBgB4TvgAOwAAAA==" kann keinem gültigen Enumeratornamen 
    zugeordnet werden. Geben Sie einen der folgenden Enumeratornamen an, und wiederholen Sie den Vorgang:
    Calendar, Contacts, DeletedItems, Drafts, Inbox, Journal, Notes, Outbox, SentItems, Tasks, MsgFolderRoot, PublicFoldersRoot, Root, JunkEmail, SearchFolders, 
    VoiceMail, RecoverableItemsRoot, RecoverableItemsDeletions, RecoverableItemsVersions, RecoverableItemsPurges, ArchiveRoot, ArchiveMsgFolderRoot, 
    ArchiveDeletedItems, ArchiveRecoverableItemsRoot, ArchiveRecoverableItemsDeletions, ArchiveRecoverableItemsVersions, ArchiveRecoverableItemsPurges, SyncIssues, 
    Conflicts, LocalFailures, ServerFailures, RecipientCache, QuickContacts, ConversationHistory, ToDoSearch""
    In C:\Users\Desktop\Order.ps1:65 Zeichen:1
    + [VOID]$miMailItems.Move($Global:findFolder.Id.UniqueId)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
     
    
    PS C:\Users\> 

    When i change the "$ProcessedFolderPath" to "/Inbox/Bestellungen"

    It´s the same result but with a other error Code:

    PS C:\Users\> C:\Users\\Desktop\Order.ps1
    Inbox
    Error Folder Not Found
    WG: SystemCheck 2017-03-02
    Downloaded Attachment :  + \\Fileserver\Order\order.csv
    
    Ausnahme beim Aufrufen von "Move" mit 1 Argument(en):  "Der Wert darf nicht NULL sein.
    Parametername: destinationFolderId"
    In C:\Users\Desktop\Order.ps1:65 Zeichen:1
    + [VOID]$miMailItems.Move($Global:findFolder.Id.UniqueId)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ArgumentNullException
     
    
    PS C:\Users\> 

    We have a german Exchange 2010 Version 14.3 (Build 123.4) on a german W2008 R2 Service Pack 1.

     

    I hope you can help me.

    Kind regards Thomas

    • Edited by Thomasoe Friday, March 3, 2017 12:34 PM
    Friday, March 3, 2017 12:33 PM

Answers

All replies

  • Normally, it's getting the attachment saved off that I get questions about, but you seem to have passed this hurdle.  Good, moving the message should be a bit easier to process.

    That being said, it's still not trivial.  I'm not sure what the error you are seeing is saying, but is it possible that it's not able to find the folder?


    Will Martin ...
    -join ('77696c6c406d617274696e2d66616d696c6965732e6f7267' -split '(?<=\G.{2})' | ? { $_ } | % { [char][int]"0x$_" })

    Friday, March 3, 2017 3:10 PM
  • [VOID]$miMailItems.Move($Global:findFolder.Id.UniqueId)

    Move take object of FolderId https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.item.move(v=exchg.80).aspx your just passing in the String which is wrong it should be

    [VOID]$miMailItems.Move($Global:findFolder.Id)
    Cheers
    Glen


    • Edited by Glen ScalesMVP Monday, March 6, 2017 5:09 AM
    • Marked as answer by Thomasoe Wednesday, March 8, 2017 8:36 AM
    Monday, March 6, 2017 5:08 AM
  • Perfect, thank you!

    Now the move works.

    And have you too a idea how i could search still a specify sender?

    Cheers Thomas

    Monday, March 6, 2017 6:11 AM
  • You'd add your From filter after this line in your code:

    foreach ($miMailItems in $frFolderResult.Items){

    I'd suggest using an IF statement in that loop to only have the script run for your specific sender(s).

    If ($miMailItems.Sender -eq "user@company.com") {


    Will Martin ...
    -join ('77696c6c406d617274696e2d66616d696c6965732e6f7267' -split '(?<=\G.{2})' | ? { $_ } | % { [char][int]"0x$_" })

    Monday, March 6, 2017 1:00 PM