从Office 365

时间:2016-03-09 05:21:09

标签: powershell outlook office365api

我需要从Outlook 365邮箱中提取附件。

我在这里关注这个例子(Powershell)

https://gallery.technet.microsoft.com/office/Export-Email-Messages-from-1419bbe9

我运行得很好。此示例提取整个消息并保存到.EML文件。

要获取附件我之后可以在.EML文件上运行一些其他脚本(我真的不想这样做)或者我可以使用Powershell直接提取附件

所以我正在尝试使用powershell,但正在使用的API上的doco比我以前使用的更稀疏

基本上我遇到的问题是示例代码通过调用此代码来保存电子邮件(简化代码)

# not sure if this is relevant. I think so
$itemPropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet(
[Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties,
[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::MimeContent)
$emailMsg.Load($itemPropertySet)



# This actually saves it
$emailContent = $emailMsg.MimeContent.Content      
[System.IO.File]::WriteAllBytes("$Path\$fileName.eml",$emailContent)

但是当我针对附件尝试相同类型的代码时,MimeContent.Content会导致NULL

认为是因为我需要使用正确的参数调用Attachment.Load来在本地拖动附件?但文档没有帮助。

所以无论如何这里有一些简化的消毒代码。

此代码打印出附件名称,但对于每个附件,我都会收到这些错误

  
    

使用“1”参数调用“Load”的异常:“空路径名称不合法。

  

这是因为我没有正确调用Load

  
    

Export-OSCEXOEmailAttachment:使用“2”参数调用“WriteAllBytes”的异常:“值不能为空。

  

这是因为用于保存附件字节的变量是空的。

也可以有人告诉我 - 每次更改代码时,我都需要Remove-ModuleImport-Module进行刷新吗?我怀疑有一种方法可以直接运行脚本而无需导入它

代码低于

Function Export-OSCEXOEmailAttachment
{
    [cmdletbinding()]
    Param
    (
        #Define parameters
        [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true)]
        [Microsoft.Exchange.WebServices.Data.SearchFolder]$SearchFolder,
        [Parameter(Mandatory=$true,Position=2)]
        [string]$Path,
        [Parameter(Mandatory=$false,Position=3)]
        [int]$PageSize=100,
        [Parameter(Mandatory=$false)]
        [switch]$AllowOverwrite,
        [Parameter(Mandatory=$false)]
        [switch]$KeepSearchFolder
    )
    Begin
    {
        #Verify the existence of exchange service object
        #This bit of code (removed) 
        #validates that variable $exService is initialised


        #Load necessary properties for email messages
        #Not certain what this is for. Does this indicate which particular properties are loaded?
        $itemPropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet(`
                           [Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties,
                           [Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::MimeContent)

        #Load properties for attachments. Do we need to do this to get Mime.Content??
        $attachmentPropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet(`
                           [Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties,
                           [Microsoft.Exchange.WebServices.Data.Attachment]::MimeContent)

    }
    Process
    {
        #Define the view settings in a folder search operation.
        $itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($PageSize)

        #Iterate each item in the search folder
        do
        {
            $findResults = $SearchFolder.FindItems($itemView)

            foreach ($findResult in $findResults) {
                #Bind each email with a small set of PropertySet
                $emailMsg = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind(`
                            $exService,$findResult.Id)
                $emailMsg.Load($itemPropertySet)

                # Addition to original function: now iterate through attachments
                foreach ($attachment in $emailMsg.Attachments) {
                    $ext = [System.IO.Path]::GetExtension($attachment.Name)

                    if($ext -eq ".xlsx") {
                     $attachment.Load($attachmentPropertySet)
                     $exportPath=$Path + "\" + $attachment.Name
                     Write-Host $exportPath

                     $attachmentContent = $attachment.MimeContent.Content

                     #Export attachment
                     Try
                     {
                        [System.IO.File]::WriteAllBytes($exportPath,$attachmentContent)
                     }
                     Catch
                     {
                        $PSCmdlet.WriteError($_)
                     }
                   }
                }


            }
        } while ($findResults.MoreAvailable)
    }
    End
}

以下是使用此处使用API​​的C#中代码保存附件的示例https://msdn.microsoft.com/EN-US/library/office/dn726695(v=exchg.150).aspx

public static void SaveEmailAttachment(ExchangeService service, ItemId itemId)
{
    // Bind to an existing message item and retrieve the attachments collection.
    // This method results in an GetItem call to EWS.
    EmailMessage message = EmailMessage.Bind(service, itemId, new PropertySet(ItemSchema.Attachments));

    foreach (Attachment attachment in message.Attachments)
    {
        if (attachment is ItemAttachment)
        {
            ItemAttachment itemAttachment = attachment as ItemAttachment;
            itemAttachment.Load(ItemSchema.MimeContent);
            string fileName = "C:\\Temp\\" + itemAttachment.Item.Subject + ".eml";

            // Write the bytes of the attachment into a file.
            File.WriteAllBytes(fileName, itemAttachment.Item.MimeContent.Content);

            Console.WriteLine("Email attachment name: "+ itemAttachment.Item.Subject + ".eml");
        }
    }
}

所有这些'架构'是什么?问题在那里,但我不明白

1 个答案:

答案 0 :(得分:1)

答案在这里:

http://gsexdev.blogspot.com.au/2009/06/downloading-attachments-and-exporting.html

据我所知,它与模式或属性集无关。我应该用

$attachment.Content

而不是

$attachment.MimeContent.Content

如果Content出现在任何API文档中,那么可能会更明显。为什么C#示例使用MimeContent.Content?对于经验丰富的Powershell / API程序员来说,这可能是显而易见的。

以下是最终代码的摘录,基于https://gallery.technet.microsoft.com/office/Export-Email-Messages-from-1419bbe9的原始代码

#Iterate each item in the search folder
do
{
    $findResults = $SearchFolder.FindItems($itemView)
    foreach ($findResult in $findResults) {
        #Bind each email with a small set of PropertySet
        $emailMsg = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($exService,$findResult.Id)
        $emailMsg.Load()

        # Iterate through attachments inside email
        foreach ($attachment in $emailMsg.Attachments) {
            $ext = [System.IO.Path]::GetExtension($attachment.Name)

            if($ext -eq ".xlsx") {
              $attachment.Load()
              $exportPath=$Path + "\" + $attachment.Name
              Write-Host $exportPath

              #Export attachment
              Try
              {
                 $file = New-Object System.IO.FileStream($exportPath,[System.IO.FileMode]::Create)
                 $file.Write($attachment.Content,0,$attachment.Content.Length)
                 $file.Close()
              }
              Catch
              {
                 $PSCmdlet.WriteError($_)
              }
           }
        }


    }

    # Once we've gone through this page of items, go to the next page
    $itemView.Offset += $PageSize
} while ($findResults.MoreAvailable)