Simulate User Message Sends leveraging EWS

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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.