Quantcast
Channel: TechNet Blogs
Viewing all articles
Browse latest Browse all 36188

的在PowerShell脚本中通过Exchange Web 服务(EWS)接口操作邮箱内邮件

$
0
0

前几天,一个以前的同事突然来找我。他说他们公司的一个新同事在学习邮件记录管理MRM保留策略时,创建了一个测试策略自动将一天前的项目由主邮箱移到存档邮箱,但不小心将该测试策论应用到整个公司。虽然用户访问已移到存档邮箱的邮件没有受到什么影响,但使用Outlook Web AppOWA)客户端的用户却无法访问已移到存档邮箱的日历项目。整个公司上千个邮箱用户受到了影响。他找我就是想问问我在之前的文章里提到New-MailboxRestoreRequest cmdlet 是否可以将那些项目(特别是日历项目)从存档邮箱还原回主邮箱。很遗憾,New-MailboxRestoreRequest cmdlet仅可用于还原软删除邮箱的项目,如果非要用它。则需要将那些受影响的邮箱删除重建,这样做的风险的太大,所以我没有推荐使用该方法。

在和以前的同事的详细讨论后,我们首先确认了当务之急是将存档邮箱内的日历项目移回到主邮箱。目标确定了,方法就容易选择了。之前,我有写过一些通过Exchange Web 服务(EWS)接口对邮箱内邮件操作的PowerShell脚本。所以我知道EWS接口可以实现我们的目的,同时PowerShell脚本又是对多个邮箱进行操作的便捷方法。经和以前的同事讨论,方法就确定了。

用这个方法之前,我们需要做一些准备工作。首先,我们下载并安装Microsoft Exchange Web Services Managed API 2.2http://www.microsoft.com/en-in/download/details.aspx?id=42951)。为了避免遇到一些已经修复的问题,确定.NetPowershell的最新补丁已经安装。其次,我们需要准备一个管理员账号,让他(她)可以通过EWS接口访问Exchange Online 中的邮箱。


参考:https://msdn.microsoft.com/zh-cn/dn722376

另外,我们需要这个管理员对所有需要修复的邮箱有完全管理权限。

Add-MailboxPermission <Name of the mailbox> -User admin -AccessRights FullAccess -InheritanceType all

好了,下面我们可以着手我们的PowerShell脚本了。首先它需要两个参数:目的邮箱和管理员账号。

param (
   [parameter(Mandatory=$true)]
   [string]$MailboxName,
   [parameter(Mandatory=$true)]
   [PSCredential]$AdminCredential
)

第二步,加载EWS模块,并使用管理员账号访问目的邮箱:

###### Load EWS API dll   
Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
Write-Host "Loaded EWS API dll"

###### Create Exchange Service Object   
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013)

###### Credentials for EWS
$service.Credentials = new-object Microsoft.Exchange.WebServices.Data.WebCredentials($AdminCredential)
###### Using static URL $service.AutodiscoverUrl($AdminCredential.UserName.ToString(),{$true})
$service.Url = https://outlook.office365.com/EWS/Exchange.asmx

###### Set the impersonationUser
$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,$MailboxName);
Write-Host "Connected to EWS"

第三步,打开目的邮箱的存档邮箱,并找到日历文件夹。

###### Connect to the Archive Mailbox
$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::ArchiveMsgFolderRoot,$MailboxName)
$folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
Write-Host "Connected to Archive Mailbox"

###### Find the Calendar folder in the Archive Mailbox
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(10)
$FoSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass, "IPF.Appointment")
$ffFolders=$folder.FindFolders($FoSearchFilter,$fvFolderView)

最后就是遍历找到的日历文件夹内的每个项目,并把它们移回到主邮箱的日历文件夹。

$Count = 1
foreach($SourceFolder in $ffFolders)
{
$TotalCount = $SourceFolder.TotalCount
Write-Host "Found the Calendar folder in the Archive Mailbox, and $TotalCount item(s) in it."

  ###### Enumerate all items in the Calendar folder
  $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)   

  do{   
    $fiItems=$SourceFolder.FindItems($ivItemView)
    foreach($Item in $fiItems){

        ###### Move each item back to the default Calendar folder
        $Item.Move([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar)

$Subject = $Item.Subject
Write-Host "Moved the item[$Count]: $Subject"
$Count++
    }
    $ivItemView.Offset+=$fiItems.Items.Count   
  }while($fiItems.MoreAvailable-eq$true)
}

到此,我们把上面的命令保存到一个脚本文件,命名为MoveCalenderItems.ps1。然后用下面的命令调用它,或通过管道符将所有需要修复的邮箱依次传给该脚本。

$AdminCred = Get-Credential
.\MoveCalenderItems.ps1 -MailboxName <Name of the mailbox> -AdminCredential $AdminCred

后来,以前的同事告诉我,经过一个周末,所有的邮箱都被成功修复了。希望这个脚本可以帮助其他有相似需求的朋友。


Viewing all articles
Browse latest Browse all 36188

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>