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!

Cylindric
  • 1,127
  • 5
  • 24
  • 45

2 Answers2

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

Mathias R. Jessen
  • 25,161
  • 4
  • 63
  • 95
  • 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 '13 at 14:57
  • See my added suggestion. Remember to test it before setting it up – Mathias R. Jessen May 31 '13 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 03 '13 at 10:14
  • Just realized why, see my updated example – Mathias R. Jessen Aug 08 '13 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: http://serverfault.com/questions/591798/mailboxexportrequest-contentfilter-is-received-ne-null-when-querying-by-date – wandersick Mar 14 '16 at 06: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.

sysadmin1138
  • 133,124
  • 18
  • 176
  • 300