我需要从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-Module
和Import-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");
}
}
}
所有这些'架构'是什么?问题在那里,但我不明白
答案 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)