If you’ve read any of my posts in the past, you know that I’ve got a lab at the office. Part of this includes a handful of Exchange Servers. To better simulate “real-world” (not stress-test) simulations, I want to send messages around the organization. Thankfully, I’ve had some experience with Exchange Web Services (EWS) in the past.
Here’s what I came up with:
# Get the mailboxes directly from Active Directory $Mailboxes = Get-ADUser -LDAPFilter "(&(&(&((msExchHomeServerName=*EXMBX*)(description=*)))))" -Properties mail | Select-Object -ExpandProperty mail # Get possible attachments $AttachmentPath = "\\Demo.Lab\Files\Scripts\Exchange\Users\Attachments\" $AllAttachments = Get-ChildItem -Path $AttachmentPath -File #These are my possible Exchange Servers $ExchangeServers = "EASTEXMBX01v", "EASTEXMBX02v", "WESTEXMBX01v", "WESTEXMBX02v" # When does the simulated "workday" start and end?" # Numbers are in "hour" format: 8 = 8:00 AM = 08:00 / 19 = 7:00 PM = 19:00 $WordHourStart = 8 $WorkHourEnd = 20 # Calculate the current day of the week and the current hour of the day $WorkDay = ( get-date ).ToUniversalTime().DayOfWeek.value__ -in 1..5 # Monday through Friday $WorkHours = ( ( Get-Date ).ToUniversalTime().Hour -ge $WorkHourStart ) -and ( ( Get-Date ).ToUniversalTime().Hour -le $WorkHourEnd ) # Business Hours $MinSleepTime = 10 # seconds between message sending $MaxSleepTime = 15 # seconds between message sending
So now I’ve got the bounds of when I want to send these messages (Work hours/days) and how frequently I want to send messages.
Then I just begin a while loop when I’m in within “working hours” and repeat.
# Pick any email account for $FromMailbox = ( $Mailboxes | Get-Random -Count 1 ) $ToMailboxes = ( $Mailboxes | Get-Random -Count ( Get-Random -Minimum 1 -Maximum 10 ) )
Only one account can send a message – so I grab one at random. Then I need to select the possible recipients. Here I’m using between 1 and 10, but you can easily change this to whatever you like.
Then I setup my impersonation user (more about that here)
#region Impersonation User $EWSDomain = "DEMOLAB" $EWSUsername = "ExchangeSender" $EWSPassword = "YouDon'tGetThisFromMe" #endregion Impersonation User
Now I need to load the Exchange Web Services API into memory (download here)
#region Load the Managed API's DLL $EwsDll = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" try { # Load the Exchange Types [Void][Reflection.Assembly]::LoadFile($EwsDll) $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1 ## Create Exchange Service Object $EWS = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) ## Set Credentials to use explict credentials $ImpersonationUser = New-Object System.Net.NetworkCredential($EWSUsername,[string]$EWSPassword, $EWSDomain) $EWS.Credentials = $ImpersonationUser $EWS.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $FromMailbox) } catch [System.Exception] { Write-Error ( "Exchange Web Services Managed API load failed." ) return $null break } #endregion Load the Managed API's DLL
Since I want the mail to go through ANY mailbox server, I elected to not use Autodiscovery. You can choose how to do this for yourself. Then I create the email and need some random text for the subject and body. For this I shamelessly use the Web API available from LoremIpsum. The last construction step is to add the attachments (if I have any) and send the message.
#Write-Host "Performing AutoDiscovery" #$EWS.AutodiscoverUrl($FromMailbox, { $true }) $ExchangeServer = $ExchangeServers | Get-Random Write-Host "Building URL for EWS using $ExchangeServer" $EWS.Url = "https://$( $ExchangeServer ).demo.lab/EWS/Exchange.asmx" Write-Host "Creating new Email Object" $Email = New-Object -TypeName Microsoft.Exchange.WebServices.Data.EmailMessage($EWS) Write-Host "Assigning From Address: $FromMailbox" $Email.From = $FromMailbox Write-Host "Adding Recipients:" $i = 1 ForEach ( $Recipient in $ToMailboxes ) { Write-Host "`t#$( $i ): $Recipient" $Email.ToRecipients.Add($Recipient) | Out-Null $i++ } Write-Host "Adding Subject" -ForegroundColor DarkCyan $SubjectWordCount = Get-Random -Minimum 3 -Maximum 10 Write-Host "`tInvoking random word generator..." -ForegroundColor Cyan $Feed = Invoke-WebRequest -Uri "http://lipsum.com/feed/xml?amount=$SubjectWordCount&start=yes&what=words" $Email.Subject = ( [xml]( $Feed.Content ) ).feed.lipsum Write-Host "Adding Body" -ForegroundColor DarkCyan $BodyParagraphCount = Get-Random -Minimum 1 -Maximum 10 Write-Host "`tInvoking random paragraph generator..." -ForegroundColor Cyan $Feed = Invoke-WebRequest -Uri "http://lipsum.com/feed/xml?amount=$BodyParagraphCount&start=yes&what=paras" $Email.Body = ( [xml]( $Feed.Content ) ).feed.lipsum Write-Host "Adding Attachments" $AttachmentCount = Get-Random -Minimum 0 -Maximum $AllAttachments.Count if ( $AttachmentCount -gt 0 ) { $Attachments = $AllAttachments | Get-Random -Count $AttachmentCount $i = 1 ForEach ( $Attachment in $Attachments ) { Write-Host "`t#$( $i ): $( $Attachment.Name )" $Email.Attachments.AddFileAttachment($Attachment.FullName) | Out-Null $i++ } } else { Write-Host "No attachments" -ForegroundColor Yellow } Write-Host "Sending Email... " -NoNewline $Email.SendAndSaveCopy([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems) Write-Host "[Message Sent!]" -ForegroundColor Green $SleepTime = Get-Random -Minimum $MinSleepTime -Maximum $MaxSleepTime Write-Host "Sleeping for $SleepTime seconds" -ForegroundColor Yellow Start-Sleep -Seconds $SleepTime
Putting it all together yields the following:
# Send Random Messages # No longer done this way #$UserCsv = "\\Demo.Lab\Files\Scripts\Exchange\Users\AllUsers.csv" #$Mailboxes = Import-Csv -Path $UserCsv # Get the mailboxes directly from Active Directory $Mailboxes = Get-ADUser -LDAPFilter "(&(&(&((msExchHomeServerName=*EXMBX*)(description=*)))))" -Properties mail | Select-Object -ExpandProperty mail # Get possible attachments $AttachmentPath = "\\Demo.Lab\Files\Scripts\Exchange\Users\Attachments\" $AllAttachments = Get-ChildItem -Path $AttachmentPath -File #These are my possible Exchange Servers $ExchangeServers = "EASTEXMBX01v", "EASTEXMBX02v", "WESTEXMBX01v", "WESTEXMBX02v" # When does the simulated "workday" start and end?" # Numbers are in "hour" format: 8 = 8:00 AM = 08:00 / 19 = 7:00 PM = 19:00 $WordHourStart = 8 $WorkHourEnd = 20 # Calculate the current day of the week and the current hour of the day $WorkDay = ( get-date ).ToUniversalTime().DayOfWeek.value__ -in 1..5 # Monday through Friday $WorkHours = ( ( Get-Date ).ToUniversalTime().Hour -ge $WorkHourStart ) -and ( ( Get-Date ).ToUniversalTime().Hour -le $WorkHourEnd ) # Business Hours $MinSleepTime = 10 # seconds between message sending $MaxSleepTime = 15 # seconds between message sending $CurrentMessage = 1 While ( $WorkDay -and $WorkHours ) { # Calculate the current day of the week and the current hour of the day $WorkDay = ( Get-date ).ToUniversalTime().DayOfWeek.value__ -in 1..5 # Monday through Friday $WorkHours = ( ( Get-Date ).ToUniversalTime().Hour -ge $WorkHourStart ) -and ( ( Get-Date ).ToUniversalTime().Hour -le $WorkHourEnd ) # Business Hours Write-Host "Writing Message #$( $CurrentMessage )" -ForegroundColor Red # Pick any email account for $FromMailbox = ( $Mailboxes | Get-Random -Count 1 ) $ToMailboxes = ( $Mailboxes | Get-Random -Count ( Get-Random -Minimum 1 -Maximum 10 ) ) #region Impersonation User $EWSDomain = "DEMOLAB" $EWSUsername = "R2D2" $EWSPassword = "C-3POLuke" #endregion Impersonation User #region Load the Managed API's DLL $EwsDll = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" try { # Load the Exchange Types [Void][Reflection.Assembly]::LoadFile($EwsDll) $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1 ## Create Exchange Service Object $EWS = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) ## Set Credentials to use explict credentials $ImpersonationUser = New-Object System.Net.NetworkCredential($EWSUsername,[string]$EWSPassword, $EWSDomain) $EWS.Credentials = $ImpersonationUser $EWS.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $FromMailbox) } catch [System.Exception] { Write-Error ( "Exchange Web Services Managed API load failed." ) return $null break } #endregion Load the Managed API's DLL #Write-Host "Performing AutoDiscovery" #$EWS.AutodiscoverUrl($FromMailbox, { $true }) $ExchangeServer = $ExchangeServers | Get-Random Write-Host "Building URL for EWS using $ExchangeServer" $EWS.Url = "https://$( $ExchangeServer ).demo.lab/EWS/Exchange.asmx" Write-Host "Creating new Email Object" $Email = New-Object -TypeName Microsoft.Exchange.WebServices.Data.EmailMessage($EWS) Write-Host "Assigning From Address: $FromMailbox" $Email.From = $FromMailbox Write-Host "Adding Recipients:" $i = 1 ForEach ( $Recipient in $ToMailboxes ) { Write-Host "`t#$( $i ): $Recipient" $Email.ToRecipients.Add($Recipient) | Out-Null $i++ } Write-Host "Adding Subject" -ForegroundColor DarkCyan $SubjectWordCount = Get-Random -Minimum 3 -Maximum 10 Write-Host "`tInvoking random word generator..." -ForegroundColor Cyan $Feed = Invoke-WebRequest -Uri "http://lipsum.com/feed/xml?amount=$SubjectWordCount&start=yes&what=words" $Email.Subject = ( [xml]( $Feed.Content ) ).feed.lipsum Write-Host "Adding Body" -ForegroundColor DarkCyan $BodyParagraphCount = Get-Random -Minimum 1 -Maximum 10 Write-Host "`tInvoking random paragraph generator..." -ForegroundColor Cyan $Feed = Invoke-WebRequest -Uri "http://lipsum.com/feed/xml?amount=$BodyParagraphCount&start=yes&what=paras" $Email.Body = ( [xml]( $Feed.Content ) ).feed.lipsum Write-Host "Adding Attachments" $AttachmentCount = Get-Random -Minimum 0 -Maximum $AllAttachments.Count if ( $AttachmentCount -gt 0 ) { $Attachments = $AllAttachments | Get-Random -Count $AttachmentCount $i = 1 ForEach ( $Attachment in $Attachments ) { Write-Host "`t#$( $i ): $( $Attachment.Name )" $Email.Attachments.AddFileAttachment($Attachment.FullName) | Out-Null $i++ } } else { Write-Host "No attachments" -ForegroundColor Yellow } Write-Host "Sending Email... " -NoNewline $Email.SendAndSaveCopy([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems) Write-Host "[Message Sent!]" -ForegroundColor Green $SleepTime = Get-Random -Minimum $MinSleepTime -Maximum $MaxSleepTime Write-Host "Sleeping for $SleepTime seconds" -ForegroundColor Yellow Start-Sleep -Seconds $SleepTime $CurrentMessage++ }
When running it looks something like this:

That’s it. Pretty simple, but it works.