Creating Email Population Scripts

As I am building my lab setup script, I continually run into what I call ‘challenges’. These challenges stem from lack of a complete understanding of all the features and functions of PowerShell. With a bit of experimentation and reading about what others have done to get over their own challenges with script writing, I am able to construct a script that does what I need.

The current challenge has to do with scheduling email traffic in a lab environment. I previously posted about job scheduling in PowerShell with this post I am combining this into a useful way to schedule PowerShell scripts. The scheduled PowerShell scripts in this case will send emails through Exchange to simulate a ‘live’ environment. My plan is to simulate traffic for testing with CU updates as well as features built into Exchange like quotas, message limits retention policies, transport rules and more.

The Script
With this script I am going to try a different approach to explaining how the script works, so I am going to visually break out the major script parts below:

codesection1

function random-mailboxes {
    # Prep Random mailboxes (version 1)
    $mbxcount = (get-mailbox | where {($_.RecipientTypeDetails -ne "DiscoveryMailbox") -and ($_.RecipientTypeDetails -ne "RoomMailbox")}).count
    $range =  get-random -minimum 0 -maximum $mbxcount
    $mailbox = (get-mailbox | where {($_.RecipientTypeDetails -ne "DiscoveryMailbox") -and ($_.RecipientTypeDetails -ne "RoomMailbox")}).primarysmtpaddress

    # Create Random User List
    $counter = 0
    $userlist = @()
    while ($counter -lt $range) {
        $position = get-random -minimum 0 -maximum $mbxcount
        $alias = $mailbox[$position].local+"@"+$mailbox[$position].domain
        $validation = $false
        if ($userlist -contains $alias) {
                $validation = $true
                $counter--
        } 
        $counter++
        if ($validation -eq $false) {
                # Put all the mailboxes into a list of unique results
                $global:userlist += @($alias)
        }
    }
}

The above section of code is for choosing random mailboxes for use in the script. The thought process is if this were to simulate a list of mailboxes that are sending emails, then a random group would be good because that would simulate a ‘real world’ environment where emails being sent to and from people are not predictable as compared to a controlled lab environment. From the code you can see that I am gathering up the PrimarySMTPAddresses of all mailboxes and randomly adding these to a user list (global variable) to be used by other parts of the script. Because of the way the primarysmtpaddres is stored, I need to reassemble it use it later in the script.

Next Section

Explanation1

This section of code gathers information for the email messages that will be scheduled later. All variables will be used by either of the three choices in the script (all, random, csv).

Function create-emailps1 {
    cls
    write-host " "
    $filepath = read-host "Enter the filename and path of the PS1 file to be run for email population [i.e. c:\temp\scripttorun.ps1]"
    $sendto = read-host "Do you want to send emails to (a) All mailboxes, (r) Random mailboxes or (c) use a CSV file"
    
    # Set the email server used for email relay
    $transport = (get-transportservice).name
    $smtpserver = $transport[0]

Next Section

Explanation2

This section of code is for sending emails to all users in Exchange. Two email lists are created – $Sender and $recipient. For $sender the loop will go incrementally forward with the $counter variable in the loop, while $recipient will be going backwards (starting from the last value and proceeding to the first value) via the $mbxcount variable (total number of user mailboxes). The script also asks for a subject, body and attachment.

    if ($sendto -eq "a") {
        write-host " "
        write-host "This section is for sending test messages to all mailboxes" -ForegroundColor green
        write-host " "
        $noofcopies = read-host "How many test email messages to be sent per sender"
        $subject = read-host "Enter a subject line for the test message"
        $body = "This is a test message to help populate email in the mailboxes on Exchange 2013."
        $attachment = read-host "Specify an attachement for the test email"
        $mbxcount =  ($mailboxes = Get-Mailbox -Filter 'RecipientTypeDetails -eq "UserMailbox"' -resultsize unlimited).count
        $mbxcount--
        $mailboxes = (Get-Mailbox -Filter 'RecipientTypeDetails -eq "UserMailbox"' -resultsize unlimited).primarysmtpaddress
        # Create one line per mailbox
        foreach ($line in $mailboxes) {
            # Recipient - starts from the end of the mailbox variable
            $recipient = $mailboxes[$mbxcount]
            # Sender starts from the beginning of the mailbox variable
            $sender = $line
            $variable = '$counter'
            add-content $filepath "$variable = 0"
            add-content $filepath "while ('$counter' -lt $noofcopies) {"
            add-content $filepath "send-mailmessage -from '$sender' -to '$recipient' -subject '$subject' -body '$body' -smtpserver '$smtpserver' -attachment '$attachment'"
            add-content $filepath "$variable++"
            add-content $filepath "}"
            $mbxcount--
        }
    }

Next Section

Explanation3

This section of code is for sending emails to random users in Exchange. Two email lists are created – $Sender and $recipient. In this case I created two different loops. One for $sender (the outer loop) and $recipient (the inner loop). Essentially for each value in the $sender variable, we’ll created a set of code for entire list of values in the $recipient variable. The script also asks for a subject, body and attachment. A very similar setup to what was done for all mailboxes above.

if ($sendto -eq "r") {
        write-host " "
        write-host "This section is for sending test messages to random mailboxes" -ForegroundColor green
        write-host " "
        $noofcopies = read-host "How many test email messages to be sent per sender"
        $subject = read-host "Enter a subject line for the test message"
        $body = "This is a test message to help populate email in the mailboxes on Exchange 2013."
        $attachment = read-host "Specify an attachement for the test email"
        # Choose random mailboxes
        random-mailboxes
        $sender = $userlist
        random-mailboxes
        $recipient = $userlist
        # Create one line per mailbox
        foreach ($line in $sender) {
            foreach ($line2 in $recipient) {
                $sender = $line
                $recipient = $line2
                $variable = '$counter'
                add-content $filepath "$variable = 0"
                add-content $filepath "while ($variable -lt $noofcopies) {"
                add-content $filepath "send-mailmessage -from '$sender' -to '$recipient' -subject '$subject' -body '$body' -smtpserver '$smtpserver' -attachment '$attach'"
                add-content $filepath "$variable++"
                add-content $filepath "}"
            }
        }
    }

Final Section

Explanation4

This is a much smaller section of code, where a CSV file is utilized for the various parts of the email script. Simply laid out, this section asks for the CSV file, normalizes the variables and then writes everything to the PS1 file like the two above sections do.

    if ($sendto -eq "c") {
        write-host " "
        write-host "This section is for sending test messages using a CSV file" -ForegroundColor green
        write-host " "

      # CSV format should be sender,recipient,subject,body,attachment,noofcopies
        $csvfile = read-host "Specify a CSV file to read from"
        $csv = import-csv $csvfile
        foreach ($line in $csv) {
            $sender = $line.sender
            $recipient = $line.recipient
            $subject = $line.subject
            $body = $line.body
            $attachment = $line.attachment
            $noofcopies = $line.noofcopies
            $variable = '$counter'
            add-content $filepath "$variable = 0"
            add-content $filepath "while ($variable -lt $noofcopies) {"
            add-content $filepath "send-mailmessage -from '$sender' -to '$recipient' -subject '$subject' -body '$body' -smtpserver '$smtpserver' -attachment '$attachment'"
            add-content $filepath "$variable++"
            add-content $filepath "}"
     }
}

In Action
First tested was sending messages to all users in the organizations. Here is the run through:

EmailSchedule1

Contents of the PS1 file that can be scheduled later or run manually:

EmailSchedule2

Here is the run through with randomly picked senders and recipients:

EmailSchedule3

Contents of the PS1 file that can be scheduled later or run manually:

EmailSchedule4

Here is the run through with a pre-created CSV file:

EmailSchedule5

Contents of the PS1 file that can be scheduled later or run manually:

EmailSchedule6

Contents of the CSV file used:

EmailSchedule7

Scheduling
Combining the above code with the scheduling code from my previous post, you can then schedule some test mail flow by using the PS1 file that was created in the above sections of code. You can also manually run the script later if you wish. Here is a decision making code block I made for this:

Explanation5

This would then require my schedule-email function I wrote in a previous blog article. That’s it. A lot of line codes to create some easy to use PowerShell scripts for later use or scheduled use.

Resources
Get-Random
Add-Content
Send-MailMessage
New-JobTrigger
Register-ScheduledJob

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s