从 Office 365 中提取附件
Extracting attachments from Office 365
我需要从 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
才能将附件拖到本地?但是文档没有帮助。
所以无论如何,这里有一些经过简化的清理代码。
此代码打印出附件名称,但对于每个附件我都会收到这些错误
Exception calling "Load" with "1" argument(s): "Empty path name is not legal.
这是因为我没有正确调用 Load
Export-OSCEXOEmailAttachment : Exception calling "WriteAllBytes" with "2" argument(s): "Value cannot be null.
这是因为用来保存附件字节的变量是空的。
还有谁能告诉我 - 每次我更改代码时都需要 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
}
这是使用此处 https://msdn.microsoft.com/EN-US/library/office/dn726695(v=exchg.150).aspx
中的 API 在 C# 中保存附件的代码示例
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");
}
}
}
这些都是什么'schemas'?问题就在那里,但我不明白
答案在这里:
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)
我需要从 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
才能将附件拖到本地?但是文档没有帮助。
所以无论如何,这里有一些经过简化的清理代码。
此代码打印出附件名称,但对于每个附件我都会收到这些错误
Exception calling "Load" with "1" argument(s): "Empty path name is not legal.
这是因为我没有正确调用 Load
Export-OSCEXOEmailAttachment : Exception calling "WriteAllBytes" with "2" argument(s): "Value cannot be null.
这是因为用来保存附件字节的变量是空的。
还有谁能告诉我 - 每次我更改代码时都需要 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
}
这是使用此处 https://msdn.microsoft.com/EN-US/library/office/dn726695(v=exchg.150).aspx
中的 API 在 C# 中保存附件的代码示例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");
}
}
}
这些都是什么'schemas'?问题就在那里,但我不明白
答案在这里:
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)