2

We have a mailbox that receives status emails that we need to keep essentially for ever, and they contain potentially large attachments. I need to be able to move these messages to a PST on a regular (daily or weekly) basis so want to automate this.

At the moment I am using a MailboxExportRequest to get them into a PST:

New-MailboxExportRequest -ContentFilter {(Received -ge '01/01/2013') -and (Received -lt '01/02/2013')} -Mailbox "MonitorMailbox" -FilePath "\\Server\backup\EmailLog\MonitorMailbox 2013-01.pst"

And I follow this with a SearchMailbox -DeleteContent:

Get-Mailbox -Identity "MonitorMailbox" | Search-Mailbox -SearchQuery "Received:01/01/2013..01/02/2013" -DeleteContent

The problem is that I'm having to manually update the date parameters each time in four places, and I'm worried that it's not very transactional (if that even makes sense in this context).

I'm trying to create a little PS script to iterate through dates by month and build a set of commands to spin through and export this information, but was wondering if there's a simpler way to "move to PST", or if I need to try and build the above statements dynamically.


Here's a more complete script, as I have it so far, which should export all items for the 10 days preceding the beginning of this month (to speed up testing):

$mailbox = "Cylindric"
$endDate = Get-Date -Day 1 "00:00:00"
$startDate = $endDate.AddDays(-10)

$month = "{0:D2}" -f [int]$startDate.Month
$year = "{0:D4}" -f [int]$startDate.Year


Write-Host -NoNewline "Exporting items between $startDate and $endDate..."
New-MailboxExportRequest -Name "EmailLog$year$month" -ContentFilter {(Received -ge $startDate) -and (Received -lt $endDate)} -Mailbox $mailbox -FilePath "\\ReadyNAS\backup\Mailboxes\EmailLog\EmailLog${year}-${month}.pst"
Write-Host "Done."


Write-Host -NoNewline "Waiting for export to complete..."
While(!(Get-MailboxExportRequest -Mailbox $mailbox -Name "EmailLog$year$month" -Status Completed))
{
    #Sleep for a  few minutes
    Write-Host -NoNewline "."
    Start-Sleep -s 60
}
Write-Host "Done."


Write-Host -NoNewline "Removing Export Request..."
Get-MailboxExportRequest -Mailbox $mailbox -Status Completed -Name "EmailLog$year$month" | Remove-MailboxExportRequest
Write-Host "Done."

And the output:

Exporting items between 05/22/2013 00:00:00 and 06/01/2013 00:00:00...
Name            Mailbox       Status
----            -------       ------
EmailLog201305  Cylindric     Queued
Done.
Waiting for export to complete..........Done.

This seems to be exporting a lot more than these 10 days though. The PST appears to contain ALL emails!

2

2 Answers 2

2

Use the Get-Date cmdlet!

The snippet below will check what month it is, subtract 1 and export all messages to your .pst file

$endDate = Get-Date -Day 1 "00:00:00"
$startDate = $endDate.AddMonths(-1)
$month = "{0:D2}" -f [int]$startDate.Month

# Convert dates to short date strings
$endDate = $endDate.ToShortDateString()
$startDate = $startDate.ToShortDateString()

New-MailboxExportRequest -ContentFilter {(Received -ge $startDate) -and (Received -lt $endDate)} -Mailbox "MonitorMailbox" -FilePath "\\Server\backup\EmailLog\MonitorMailbox 2013-${month}.pst"

while(!(Get-MailboxExportRequest -Mailbox "MonitorMailbox" -Status Completed))
{
    #Sleep for a  few minutes
    Start-Sleep -s 300
}
Get-MailboxExportRequest -Mailbox "MonitorMailbox" -Status Completed | Remove-MailboxExportRequest

Get-Mailbox -Identity "MonitorMailbox" | Search-Mailbox -SearchQuery "Received:'${startDate}'..'${endDate}'" -DeleteContent

Simple run this once a month to get the last months emails archived

5
  • The New-ExportRequest runs asynchronously, how can I make sure the delete doesn't try to start before the export is finished?
    – Cylindric
    May 31, 2013 at 14:57
  • See my added suggestion. Remember to test it before setting it up May 31, 2013 at 15:04
  • 1
    Not sure why, but I'm always getting my entire mailbox exported. I had something like this before when using the ContentFilter, and I could only get it working with manual date strings as the parameters instead of variables.
    – Cylindric
    Jun 3, 2013 at 10:14
  • Just realized why, see my updated example Aug 8, 2013 at 14:42
  • For anyone having a hard time getting this to work, the content filter may need to be specified as "(Received -ge '$startDate') -and (Received -lt '$endDate')"; otherwise, it would become $null as reported in this question: serverfault.com/questions/591798/…
    – wandersick
    Mar 14, 2016 at 6:36
0

If you're willing to put this into a scheduled task, this should get what you're looking for:

$now=get-datetime
$fromtime=$now.addHours(-$now.hour).addMinutes(-$now.minute).addSeconds(-$now.second).addDay(-2)
$totime=$now.addHours(-$now.hour).addMinutes(-$now.minute).addSeconds(-$now.second).addDay(-1)
New-MailboxExportRequest -ContentFilter {(Received -ge $fromtime) -and (Received -lt $totime)} -Mailbox "MonitorMailbox" -FilePath "\\Server\backup\EmailLog\MonitorMailbox "+$totime.year+"-"+$totime.month+"-"+$totime.day"+".pst"
$mailQuery="Received:"+fromtime.toString("d")+".."+$totime.toString("d")
Get-Mailbox -Identity "MonitorMailbox" | Search-Mailbox -SearchQuery $mailQuery -DeleteContent

What it does is take advantage of Powershell's date handling functions. The $fromtime and $totime variables are first zeroed to midnight, then set to a distance of one day. We then use those variables in constructing the queries needed by the Exchange cmdlets.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .