Summary: Microsoft Scripting Guy Ed Wilson shows how to use Windows PowerShell to send random email messages at random times.
Microsoft Scripting Guy, Ed Wilson, is here. It is Sunday in Charlotte, North Carolina in the deep south of the United States. This morning I am reflecting on a conversation I had with Ashley McGlone, a Microsoft PFE and my mentee. I had just finished hearing him make his first ever presentation at TechReady, and I was evaluating his performance (he did an awesome job, by the way). Somehow, I got off on a tangent (if you have ever talked to me, you will realize immediately how rare of an occurrence this is), and I began discussing a script I wrote when I was teaching a VBScript class based on my VBScript Step-by-Step book from Microsoft Press.
I called the script the LoveOmatic (basing the title on the famous series of Scripting Guys tools–including my own PowerShell ScriptOmatic tool). When I used to travel every week teaching scripting workshops around the world, I would send short email messages to Teresa at various times of the day (generally when the students were working on their labs, in addition to before class, after class, after dinner, and so on). In class one day, a student mentioned that I could write a script to do that, and the LoveOmatic was born.
First get rid of “magic numbers”
In my Windows PowerShell 2.0 Best Practices book, I talk at great length about the importance of readability for your Windows PowerShell code. One thing that destroys readability is the presence of “magic numbers.” A magic number is a number that appears in a script with very little context. It simply appears in the script. One generally has to look up the value to see what the script is doing. I like to assign values to well named variables, and then use the variable in my code. It promotes readability and facilitates modification of the script. The following code illustrates my point.
$numberOfEmails = 6
$oneHour = 3600
$threeHours = 10800
Create an array of strings
Now, I need to create an array of messages. I create five different strings, and then I assign the variables that contain the strings into an array as shown here.
$message1 = "I am thinking of you."
$message2 = "You are the sunshine of my life."
$message3 = "You walk in beauty like the night."
$message4 = "I am glad I met you."
$message5 = "My life is richer with you part of it."
$message = $message1,$message2,$message3,$message4,$message5
All the normal email stuff
I use four variables to store the usual email stuff. The four essential email fields are from, to, subject, and the name of the mail server. The following four variables illustrate the technique.
$from = "edwilson@nwtraders.msft"
$to = "ScriptingWife@nwtraders.msft"
$subject = "I am thinking of you"
$smtpServer = "smtphost.nwtraders.msft"
Sending random mail messages at random times
The heart of the LoveOmatic uses the following Windows PowerShell cmdlets:
- Get-Random
- Send-MailMessage
- Get-Random
- Start-Sleep
Because of these cmdlets, the actual code to send email messages is very simple. I use a for statement to send a specific number of mail messages. The for statement counts up to the value stored in the $numberOfEmails variable. This is shown in the code that follows.
For($i=0; $i -le $numberOfEmails; $i++)
Now, I need to generate a random number that goes from 0 to the number of messages I have stored in my $message array. I keep the returned random number in the $rnd variable. One thing to keep in mind when you use the Get-Random cmdlet, is that the maximum number is never reached. Therefore, the command that is shown here creates random numbers between 0 and 4. It will never return a random number equal to 5.
$rnd = Get-Random -Minimum 0 -Maximum 5
The following command sends the email message. It uses the $to variable and the values contained in $from and $subject. Because the $message variable is an array of message strings, I use the random number stored in the $rnd variable, and then index into the collection of messages. This permits selecting a random mail message to send. For more randomness, the same technique could be applied to the subject field. Here is the code that sends the email.
Send-MailMessage -to $to -body $message[$rnd] `
-from $from -subject $subject `
-smtpServer $smtpServer
I display a message to the console just for status updates as the script runs. This is shown here.
"message: $($message[$rnd]) sent at $((get-date).tostring())"
Now I need to pause the script. I pause it a random amount between 1 hour and 3 hours. To do this, I use the seconds parameter from the Start-Sleep cmdlet, and I choose a random number between 3600 and 10,800. But rather than listing these numbers directly, I store them in variables to make the code easier to read. The Start-Sleep cmdlet is shown here.
Start-Sleep -Seconds (Get-Random -Minimum $oneHour -Maximum $threeHours)
When the script runs, output similar to the one shown in the following image appears.
I uploaded the complete script to the Scripting Guys Script Repository.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Windows PowerShell, Scripting Guy!, Weekend Scripter, Messaging & Communication, SMTP Mail, Sending email