none
PowerShell EWS script move emails to sub-folder error and download attachments error RRS feed

  • Question

  • My code is as following:

    $USERNAME = Get-Content .\init.conf | findstr USERNAME |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $ENCODEDPASSWORD = Get-Content .\init.conf | findstr PASSWORD |  %{ $_.Split(':')[1]; } | foreach{ $_.ToString().Trim() }
    $PASSWORD = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($ENCODEDPASSWORD))
    $DOMAIN = Get-Content .\init.conf | findstr DOMAIN |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $EMAILADDRESS = Get-Content .\init.conf | findstr EMAILADDRESS |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $EXCHANGESRV = Get-Content .\init.conf | findstr EXCHANGESRV |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $DLLPATH = Get-Content .\init.conf | findstr DLLPATH |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $DOWNLOADDIRECTORY =  Get-Content .\init.conf | findstr DOWNLOADDIRECTORY |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $EXTENSIONARRAY = Get-Content .\init.conf | findstr EXTENSIONARRAY |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $SUBFOLDER = Get-Content .\init.conf | findstr SUBFOLDER | %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    $VIRUSTOTAL_API_KEY = Get-Content .\init.conf | findstr VIRUSTOTAL_API_KEY |  %{ $_.Split('=')[1]; } | foreach{ $_.ToString().Trim() }
    
    Import-Module $DLLPATH
    
    $SERVICE = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
    $SERVICE.Credentials = New-Object Net.NetworkCredential($USERNAME, $PASSWORD, $DOMAIN)
    $SERVICE.AutodiscoverUrl($EMAILADDRESS)
    $INBOX = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($SERVICE,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
    $FOLDER = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($SERVICE,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
    $FOLDERID = ($FOLDER.FindFolders([Microsoft.Exchange.WebServices.Data.FolderView]::new(10)) | where { $_.DisplayName -eq $SUBFOLDER }).Id.UniqueID
    write-output $FOLDERID
    $PROPERTYSET = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
    $PROPERTYSET.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text
    
    $ITEMS = $INBOX.FindItems($INBOX.TotalCount)
    
    foreach ( $EMAIL in $ITEMS.Items )
    {
    	$EMAIL.load($PROPERTYSET)
    	
    	foreach($ATTACH in $EMAIL.ATTACHments)
    		{
    		$ATTACH.Load()
    		$EXTENSION = [System.IO.Path]::getExtension($ATTACH.Name.ToString().ToLower())
    		# only save the file that extension is not in the extension list
    		$ATTFILE = new-object System.IO.FileStream(($DOWNLOADDIRECTORY + $ATTACH.Name.ToString()), [System.IO.FileMode]::Create)
    		$ATTFILE.Write($ATTACH.Content, 0, $ATTACH.Content.Length)
    		$ATTFILE.Close()
    		write-host "Downloaded ATTACHment : "  (($DOWNLOADDIRECTORY + $ATTACH.Name.ToString()))
    		Write-host "====================================================================" -foregroundcolor White
    		""
    		write-host $FILEPATH
    		}	
    	$EMAIL.Move($FOLDERID)
    }

    I use it to download the attachments from the emails and move the emails into subfolder "Processed" which is under "Inbox"

    I can get the subfolder's ID, but when I use the "Move" always give me the following error:

    Cannot convert argument "destinationFolderName", with value: "AAMkADlhMmNjNDJhLTAxOGUtNDdmMS05Y2M5LTY3ODY2MzUxMTNjZgAuAAAAAABLzVjG5J5/SYL2OR9YaznTAQBIbT+2dwYRSrsElOIWkgaqAAAAprg6AAA=", for "Move" to
    type "Microsoft.Exchange.WebServices.Data.WellKnownFolderName": "Cannot convert value
    "AAMkADlhMmNjNDJhLTAxOGUtNDdmMS05Y2M5LTY3ODY2MzUxMTNjZgAuAAAAAABLzVjG5J5/SYL2OR9YaznTAQBIbT+2dwYRSrsElOIWkgaqAAAAprg6AAA=" to type "Microsoft.Exchange.WebServices.Data.WellKnownFolderName". Error:
    "Unable to match the identifier name AAMkADlhMmNjNDJhLTAxOGUtNDdmMS05Y2M5LTY3ODY2MzUxMTNjZgAuAAAAAABLzVjG5J5/SYL2OR9YaznTAQBIbT+2dwYRSrsElOIWkgaqAAAAprg6AAA= to a valid enumerator name. Specify one
    of the following enumerator names and try again:
    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""
    At H:\test.ps1:44 char:2
    +     $EMAIL.Move($FOLDERID)
    +     ~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
     

    I can download the attachments, but when an email was attached as a attachment the download will fail. I have no idea what's the difference between a msg file and a PDF file when download it.

    Exception calling "Write" with "3" argument(s): "Buffer cannot be null.
    Parameter name: array"
    At H:\test.ps1:37 char:3
    +         $ATTFILE.Write($ATTACH.Content, 0, $ATTACH.Content.Length)
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ArgumentNullException
    Thank for your helping!


    Tuesday, June 4, 2019 3:02 PM

All replies

  • You cannot use a folder id in a move.  That is what the error is telling you.  Use one of the enumerated types only.


    \_(ツ)_/

    Tuesday, June 4, 2019 3:46 PM
  • Thanks for the help.

    But I saw lots of examples that use $FOLDERID to move the emails.

    And the enumerator names are all predefined, I'd like to move the emails into "Processed" folder which is a sub-folder of the "Inbox".

    The second question I have the answer now. Save an email as attachment should use another class

    foreach($ATTACH in $EMAIL.Attachments)
    		{
    		$EXTENSION = [System.IO.Path]::getExtension($ATTACH.Name.ToString().ToLower())
    		# only save the file that extension is not in the extension list
    		if ( !$EXTENSIONARRAY.contains($EXTENSION) -or ([string]::IsNullOrEmpty($EXTENSION)) ){
    			if ( $ATTACH.ContentType -eq "message/rfc822" ){
    				$MIMEPROPERTYSET = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
    				$ATTACH.Load($MIMEPROPERTYSET)
    				$AttachmentData = $ATTACH.Item.MimeContent.Content
    				Write-host "From:    ",$($AttachmentData.From.Name) 
    				Write-host "Subject: ",$($AttachmentData.Subject)   
    				Write-host "Body:    ",$($AttachmentData.Body.Text) 
    				}else{
    					$ATTACH.Load()
    					$AttachmentData = $ATTACH.Content
    				}	
    			$ATTFILENAME = ($DOWNLOADDIRECTORY + [GUID]::NewGuid().ToString() + "_MSG.eml")
    			$ATTFILE = new-object System.IO.FileStream(($ATTFILENAME), [System.IO.FileMode]::Create)
    			$ATTFILE.Write($AttachmentData, 0, $AttachmentData.Length)
    			$ATTFILE.Close()
    			write-host "Downloaded Attachment : "  ($ATTFILENAME)
    			$ALGORITHM = (Get-FileHash ($ATTFILENAME)).Algorithm
    			$HASH = (Get-FileHash ($ATTFILENAME)).Hash.ToLower()
    			$FILEPATH = (Get-FileHash ($ATTFILENAME)).Path
    			write-host "Attachment Hash : "  $HASH
    			Write-host "====================================================================" -foregroundcolor White
    			""
    			write-host $FILEPATH
    			if ( -not ([string]::IsNullOrEmpty($FILEPATH)) ){ Submit-FILE }	
    			}
    		}
    	}

    Thursday, June 6, 2019 10:20 PM