none
download Email Attachements with Powershell from Exchange Server RRS feed

  • Question

  • I am writing a powershell script that will be run weekly to go to a particular mailbox on our exchange server. Its job is to find the latest email and download its Attachment. I have been all over the internet searching for a good way to do this, but all I have found are ways to access local outlook files or a product to buy that does it for me. I would prefer not to buy anything or use EWS. Could someone please help me out.

    Our servers are win 2008 exchange 2010. Again I want to get an attachment out of the latest email in a mailbox on our exchange server through powershell. Any help would be greatly appreciated. Thank you.

    Thursday, March 8, 2012 4:18 PM

All replies

  • You can do this with the EWS Managed API very easily eg one example http://gsexdev.blogspot.com.au/2010/01/writing-simple-scripted-process-to.html

    If you just want the last received email with an attachment you can do

    ## Load Managed API dll
    Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"
    
    ## Set Exchange Version
    $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1
    
    ## Create Exchange Service Object
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
    
    ## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials
    
    #Credentials Option 1 using UPN for the windows Account
    $creds = New-Object System.Net.NetworkCredential("user@domain.com","pass") 
    $service.Credentials = $creds  
    
    #Credentials Option 2
    #service.UseDefaultCredentials = $true
    
    ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates
    
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    
    ## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use
    
    $MailboxName = "user@domain.com"
    #CAS URL Option 1 Autodiscover
    $service.AutodiscoverUrl($MailboxName,{$true})
    "Using CAS Server : " + $Service.url 
    
    $Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::HasAttachments, $true)
    
    $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)   
    $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
    
    $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1)
    $downloadDirectory = "c:\temp"
    
    $findItemsResults = $Inbox.FindItems($Sfha,$ivItemView)
    foreach($miMailItems in $findItemsResults.Items){
    	$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()))
    	}
    }
    Cheers
    Glen
    • Proposed as answer by Troy Werelius Monday, April 23, 2018 3:58 PM
    Friday, March 9, 2012 2:46 AM
  • Glen, this isn't working for .msg attachments. Do you think I have to tweak something in the code ?

    Can you please let me know. I see this is working perfectly for all other types of attachments except .MSG.


    Monday, April 23, 2018 3:21 PM
  • If you have an attached email then generally the Filename will be null so you need to generate a FileName for these type of attachments and load the Mime content so you can save it as a EML file. eg

    foreach($attach in $miMailItems.Attachments){
        if ($attach.ContentType -eq "message/rfc822") {
            $mimePropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
            $attach.Load($mimePropertySet)
            $attachmentData = $attachment.Item.MimeContent.Content
            $fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + [GUID]::NewGuid().ToString() + ".eml"), [System.IO.FileMode]::Create)
    	    $fiFile.Write($attachmentData, 0, $attachmentData.Length)
            $fiFile.Close()
            write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + $attach.Name.ToString()))
        }else{
    	    $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()))
        }
    }

    Cheers
    Glen

    • Proposed as answer by Raghu.Ram Thursday, April 26, 2018 3:04 PM
    Monday, April 23, 2018 11:52 PM
  • Thank you so much, Glen.

    You made my Day.

    By the way - I find the MS documentation for C#, do you know any easy reference we have for Powershell EWS Managed API 2.1 ?

    I have been trying the code with the below (which I realized was wrong after seeing your code)

    $SchemaType = [Microsoft.Exchange.WebServices.Data.BasePropertySet]

    New-Object -TypeName Microsoft.Exchange.WebServices.Data.PropertySet($SchemaType::MimeContent)

    It did not throw me any error unfortunately..

    Just wondering, if I can get better understanding on using the API with some guidance / articles over Internet.

    Thursday, April 26, 2018 3:07 PM
  • The best suggestion I have is maybe do some basic C# study so you can understand the underlying Class and a little bit of Object Oriented programming. Once you understand the class and object structures putting that into Powershell is relatively easy. Powershell tends to abstract away a lot things (which saves time) but having the underlying understanding of programming methods and structures will always help you along in your career when you go to level up your coding skill or need to automated the vNext etc.

    Cheers
    Glen

       
    Thursday, April 26, 2018 11:45 PM
  • Hello Glen,

    It's really a marvelous code. But I have a question, if the attachments are email message is it the only way to save it as a .eml file? Could it be .msg file? Or can I open/read it directly in memory?

    Because I need to extract the URLs and attachments from the email message. So If the attachment is an email message, currently I save it as a .eml file and open it again to extract the URLs. But I have a barrier to save the attachments that in a .eml file.

    If you have time please view this post. Thanks!

    https://social.technet.microsoft.com/Forums/en-US/44757620-7719-46f5-bf4a-0ad8619aaae0/how-to-extract-an-attachment-from-an-eml-file?forum=ITCG

    Saturday, June 22, 2019 1:59 AM
  • Its not going to be a Msg file because that is Outlook file format and I don't think you need that from what your talking about. An attachment is just an Stream so if you don't want to save it to disk just use the MemorySteam eg 

    $attach.Content

    Is just a Stream object Read the Bytes from it then convert the Byte to Text if you want to parse it

    Cheers
    Glen

    Sunday, June 23, 2019 10:44 PM