使用Invoke-RestMethod或System.Net.WebClient时,Office 365 API超时

时间:2015-01-26 10:03:49

标签: powershell office365

我正在创建一个PowerShell脚本,用于下载包含邮箱附件的所有电子邮件,并在成功下载后从邮箱中删除它们。

我目前使用https://outlook.office365.com/EWS/ODATA/me/messages端点。打开浏览器并登录总是成功且快速(响应时间不到1秒)。

但是,尝试运行以下PowerShell会返回Invoke-RestMethod和WebClient的超时。

$cred = Get-Credential

$url = "https://outlook.office365.com/EWS/ODATA/me/messages"
Invoke-RestMethod $url -Credential $cred -Method GET -TimeoutSec 100

$wc = New-Object System.Net.WebClient
$wc.Credentials = $cred
$wc.DownloadString("https://outlook.office365.com/EWS/ODATA/me/messages")

我在一些测试租户和一些具有相同错误的生产租户中尝试过此操作。我也尝试了https://outlook.office365.com/api/v1.0/me/messages,但成功率更低(在浏览器中无效,而PowerShell无效)。

此外,不仅是消息端点出现此错误,我还尝试了https://outlook.office365.com/ews/odata/Me/Calendar/同样的结果。

  1. 我没有代理服务器
  2. 我尝试过我的客户网络,我的办公室网络,家庭网络
  3. 有时候它运作得很好,其他时候根本不运作
  4. 此API的任何人都取得了成功吗?

2 个答案:

答案 0 :(得分:1)

听起来你可能会遇到一个已知问题。如果增加超时值,它最终会返回吗?如果是这样,并且您重复请求,它会更快地返回吗?

作为旁注,使用此cmdlet调用端点使用基本身份验证,该身份验证当前在REST端点上启用,但将来某个时候将被禁用。

答案 1 :(得分:0)

我决定跳过使用此API,而是使用EWS托管API。以下是感兴趣的人的代码示例:

# Destination folder
$destinationFolder = "C:\Users\username\Downloads\Attachment Downloader"

# replace with your email address
$email    = "email@office365tenant.onmicrosoft.com"
$username = "email@office365tenant.onmicrosoft.com"
$password = "Password123"

# load the assembly
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"

# Create Exchange Service object
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
$s.Credentials = New-Object Net.NetworkCredential($username, $password)
# $s.TraceEnabled = $true
Write-Host "Trying AutoDiscover... "
$s.AutodiscoverUrl($email, {$true})

if(!$s.Url) {
    Write-Error "AutoDiscover failed"
    return;
} else {
    Write-Host -ForegroundColor Green "AutoDiscover succeeded - $($s.Url)"
}

# Create destination folder
$destinationFolder = "{0}\{1}" -f $destinationFolder, (Get-Date -Format "yyyyMMdd HHmmss")
mkdir $destinationFolder | Out-Null

# get a handle to the inbox
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#create a property set (to let us access the body & other details not available from the FindItems call)
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;

# Find the items
Write-Host "Searching for items in mailbox... " -NoNewline
$items = $inbox.FindItems(500)
Write-Host -ForegroundColor Green "found $($items.items.Count)"

$inc = 0;
foreach ($item in $items.Items)
{
    # Create mail folder
    $inc += 1
    $mailFolder = "{0}\{1}" -f $destinationFolder, $inc; 
    mkdir $mailFolder | Out-Null

    # load the property set to allow us to get to the body
    $item.load($psPropertySet)
    Write-Host ("$inc - $($item.Subject)") -ForegroundColor Yellow

    # save the metadata to a file
    $item | Export-Clixml ("{0}\metadata.xml" -f $mailFolder)

    # save all attachments
    foreach($attachment in $item.Attachments) {
        if($attachment.ContentType -notlike "message/*") {
            Write-Host " - $($attachment.Name) ($($attachment.ContentType))"
            $fileName = "{0}\{1}" -f $mailFolder, $attachment.Name
            $attachment.Load($fileName)
        }
    }

    # delete the mail item
    $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete, $true)
}