Wednesday, November 24, 2010

Sending SSL Emails using Powershell

We had recently experienced problems with our backup emails getting spammed or just having general difficulty getting out through the disparate array of local SMTP servers across our clientbase, and the security issued raised by allowing specific machines relay rights.

Also, our previous method of using blat meant our scripts were reliant on the existence of a 3rd party executable. Our way around this was to use SSL SMTP back to our own email server, and luckily, through the .NET Framework, Powershell can do this natively. Here's an example of an email function similar to one I use (it is very basic and doesn't really check what it is passed so be careful):

Function EmailSimple
{
Param($esRecipients, $esSubject, $esBody, $esFrom, $esAttachments, $esSmtpUser, $esSmtpPassword, $esSmtpServer)

#Create the credentials for the smtpauth connection
$credentials = New-Object System.Net.NetworkCredential($esSmtpUser, $esSmtpPassword);
#Create the message
$message = New-Object System.Net.Mail.MailMessage $esFrom, $esRecipients, $esSubject, $esBody
#Add attachment to $message if one exists
if ($esAttachments)
{
foreach ($esAttachment in $esAttachments)
{
$attachment = new-object System.Net.Mail.Attachment $esAttachment
$message.Attachments.Add($attachment)
}
}
# Set up server connection
$smtpClient = New-Object System.Net.Mail.SmtpClient $esSmtpServer, 587
$smtpClient.EnableSsl = $true
$smtpClient.Timeout = 100000
$smtpClient.UseDefaultCredentials = $false;
$smtpClient.Credentials = $credentials
#Send the message
$smtpClient.Send($message)
Write-Host "Message sent."
}
}

One of the most important things is the line

$credentials = New-Object System.Net.NetworkCredential($esSmtpUser, $esSmtpPassword);

This is where you create a credential that you can set in your System.Net.Mail.SmtpClient object that will allow you to connect to authenticate with an SSL server. I suggest keeping your script or configuration file in a location that is locked down to administrators so that you can minimise exposure of the username/password of the account you're using to send email with.

I found that our email server wasn't liking getting a lot of smtp connections at exactly the same time, so I added a random pause of up to 2 minutes just before doing a send to try an distribute the load:

#Add random sleep to stop smtp server overload
$randNum = New-Object System.Random
Start-Sleep -Seconds $randNum.next(0,120)

Powershell has some excellent capabilities, I'll post some more on scripting soon.

No comments:

Post a Comment