Reputation: 687
I have build a script that reads out all of my public folders and saves the emails to a local storage. The script has full access rigths and does impersonate as an admin user.
At first, I did a test run where I commented out the mail.Load()
row and the logic that saves the email content to the disc.
In this test run I printed out all my public folders and also all emails (Subject) and where they would be saved on my disc.
In this test run everything went fine so I did a real run. At first everything went fine but after a few hundred emails I get an error message back while trying to load the email content with mail.Load()
: "the remoteserver gives back an error: 401 not autorised".
The strange thing is, that this happens in a random email in a public folder. So i can read the first ~100 emails of this folder and then this error messages pops up.
Is there some kind of protection against to many api requests that just unautorises the api so no more calls can be made for a specific time frame?
Do you guys have an idea why this 401 error is happening?
The powershell code looks somewhat like that:
$folders = @()
$folders = FindAllFolders($null)
foreach($projectFolder in $folders){
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000)
$frFolderResult = $projectFolder.FindItems($sfCollection,$view)
$localFolder = FindLocalFolder($projectFolder)
if($localFolder -ne $null){
##Iterate Found Items
foreach ($miMailItems in $frFolderResult.Items){
$strSubject = $miMailItems.Subject
$TimeStamp = $miMailItems.DateTimeSent
$TmpMail = $localFolder.FullName + "\" + $TimeStamp.ToString("yyyyMMdd_HHmmss") + "-" + $strSubject + ".eml"
if(-Not(Test-Path $TmpMail -PathType Leaf)) {
$miMailItems.Load() #This part throws the error after a few hundred mails
$mailProps = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
$miMailItems.Load($mailProps)
#Write Item to Disc
$IoFile = New-Object System.IO.FileStream($TmpMail, [System.IO.FileMode]::Create)
$IoFile.Write($miMailItems.MimeContent.Content, 0, $miMailItems.MimeContent.Content.Length)
$IoFile.Close()
}
}
}
}
Upvotes: 0
Views: 469
Reputation: 22032
You won't get a 401 if you being throttled you'll get either a 200 with a throttling response code or a 50x error see Table 4: HTTP status codes returned by throttling errors in https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/ews-throttling-in-exchange
The mostly likely cause if you using oAuth is that you token has expired, tokens are only good for 60 minutes if you examine the full 401 response your getting using either tracing or something like fiddler you should see a token expiration error in the extended response.
A few other things with you code if you are going to be processing a lot of items you will get throttled as its not optimized. eg
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000)
EWS won't return any more then a 1000 items per page so don't use this keep it to 1000 or less.
$miMailItems.Load() #This part throws the error after a few hundred mails
$mailProps = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
$miMailItems.Load($mailProps)
Why are you calling Load Twice this is an expensive operation to be calling on its own and the first call is redundant. Typically if your optimizing your code for speed you would be batching https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-process-email-messages-in-batches-by-using-ews-in-exchange . In your case you want to consider the size of each message your downloading first through so batch based on size and number (but keep the numbered batches under 50).
Upvotes: 1