Sunday, August 30, 2015

Sending mail in powershell (poor man's ssmtp in Windows)

A lot of times in a server you want to have a service be able to send and email. Sometimes this service is nothing but a script you wrote. As mentioned in a previous post, sometimes you just want a lightweight solution. In Linux I like to use ssmtp, but it is not available in Windows. So let's see if we can come up with the next best thing.

If you know me or my posts long enough, this is usually the cue for Powershell. And you would be right: it does provide the function send-mailmessage that allows you to craft an email which can then be sent to a proper SMTP.

Here's a quick proof of concept that I called mailtest.ps1:

$touser = "That guy <80sguy@email.example.com>"
$hostname = hostname
$SMTP = "smtp.example.com"
$fromuser = "Me "
$body = "Nothing to see. Move along"

send-mailmessage -to $touser `
                 -from $fromuser `
                 -subject "Test mail from $($hostname)" `
                 -body $body `
                 -SmtpServer $SMTP
All it does is send a test mail to that guy from the machine we are currently at. It does grab the hostname and creates a return address based on that. I did that because in a production script I like to know where my email came from. How would I used it in a production system? Let's say I have a script that monitors the default gateway and let's me know if it changed (long story). In that script I might have something like
$touser = "Me "
$hostname = hostname
$SMTP = "smtp.example.com"
$fromuser = "Gateway monitoring on $hostname "

function Send-Mail ($message) {
    send-mailmessage -to $touser `
                     -from $fromuser `
                     -subject "Default Gateway on $($hostname) Changed!!!" `
                     -body $message `
                     -SmtpServer $SMTP 
}
Now, we have a function that sends an email to Me indicating the default gateway has changed. It could be called by something like this
function Verify-Gateway($originalGateway){
    [...]
        if( $currentGateway -ne $originalGateway ){
            $Card.SetGateways($originalGateway)
            $message = @"
$hostname lost its default gateway. 
It thinks it is $currentGateway, but it should 
be $originalGateway. So, we changed it back.
"@
            # Let's write to a log
            Log-Msg ($message)
            # Then email message
            Send-Mail($message)
        }
    }
}
Makes sense? You can add more features to it, but the above works fine to me including my multiline string. Noticed in my example the smtp server does not require me to authenticate since I am in a "blessed" network. If that was not the case, fear not since send-mailmessage has a way to use authentication. I will leave that as an exercise to you.

No comments: