Condividi tramite


Send Authenticated SMTP with PowerShell

Today, while I was testing out some transport rules, I wanted to send a bunch of test messages to make sure they were firing correctly.  I wanted to create some custom messages and be able to automate them, and I wanted to use an outside relay service that requires SMTP authentication.

It took a good bit of tinkering, but here's what I cobbled together:

 # Sender and Recipient Info
$MailFrom = "sender@senderdomain.com"
$MailTo = "recipient@recipientdomain.com"

# Sender Credentials
$Username = "SomeUsername@SomeDomain.com"
$Password = "SomePassword"

# Server Info
$SmtpServer = "smtp.domain.com"
$SmtpPort = "2525"

# Message stuff
$MessageSubject = "Live your best life now" 
$Message = New-Object System.Net.Mail.MailMessage $MailFrom,$MailTo
$Message.IsBodyHTML = $true
$Message.Subject = $MessageSubject
$Message.Body = @'
<!DOCTYPE html>
<html>
<head>
</head>
<body>
This is a test message to trigger an ETR.
</body>
</html>
'@

# Construct the SMTP client object, credentials, and send
$Smtp = New-Object Net.Mail.SmtpClient($SmtpServer,$SmtpPort)
$Smtp.EnableSsl = $true
$Smtp.Credentials = New-Object System.Net.NetworkCredential($Username,$Password)
$Smtp.Send($Message)

There's a few other interesting properties to the message and ways to get them in there.  As I am wont to do, I like to dig and poke around:

As you see, there are are plenty of things you can do.  Want to add an attachment?  Easy as pie:

 $Message.Attachments.Add("C:\Temp\pie.txt")
$Message.Attachments.Add("C:\Temp\pie2.txt")

Of course, maybe you didn't want to share both pie recipes.  I know how you are.  You can remove them (though it's not quite as intuitive, at least when I've tried to do it).

 $Message.Attachments.RemoveAt("0") # Remove the attachment at index 0
$Message.Attachments.RemoveAt("1") # Remove the attachment at index 1

One of the interesting properties that we have available is Headers.  The MSDN documentation doesn't have too much on it, but if you want to use it to add a custom header, you can use the ... wait for it ... Add method:

 $Message.Headers.Add("X-My-Test-Header","SomeData")

In this example, I populated $Message.Body with a Here-String.  If you have a larger HTML message body, you can also import it using Get-Content:

 $Message.Body = Get-Content htmlemail.html

And yes, I'm familiar with Send-MailMessage.  One of the things it doesn't have is the ability to modify message headers, so when you absolutely, positively need to emulate some very specific parameters or settings, accept no substitutes.

Hopefully this is helpful to someone out there in the universe.  If not, just disregard as the ramblings of an increasingly older man.

And

Comments

  • Anonymous
    May 22, 2018
    This is definitely an older way of doing it. A new option (>= PowerShell 5): https://blogs.technet.microsoft.com/ccarroll/2017/11/28/use-powershell-to-send-email-from-o365-account/
    • Anonymous
      May 28, 2018
      Yes, indeed. The Send-MailMessage cmdlet is what I use in several other places. :-)
  • Anonymous
    May 22, 2018
    Morning Aaron, quick question, why not use Send-MailMessage? https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-5.1
    • Anonymous
      May 28, 2018
      The comment has been removed
  • Anonymous
    May 25, 2018
    Nice script. Improvement idea > after sending the email successfully, copy it to the "sent items" folder of the account which is used to authenticate.many moons back, I was looking for a similar script & needed the option to see sent emails.G****e implements this in their SMTP server ( which is not in the SMTP specifications ) and I had a tough time convincing the customer to move their application email from G to an exchange server. eventually moved it to a script which used EWS instead of SMTP and has this capability.
    • Anonymous
      May 28, 2018
      That would definitely be cool to add. I've done a bit of EWS work in the past (though I am by no means an EWS expert). :-)
  • Anonymous
    August 21, 2018
    If you fine a way to send a message with Powershell that has different From than MailFrom let me know :-)
    • Anonymous
      August 23, 2018
      Well, they're supposed to be differentiated by the From and Sender properties, but my understanding is the .NET ignores the Sender.You can try this:# Create message$Message = New-Object System.Net.Mail.MailMessage# P1 address$Message.From = New-Object System.Net.Mail.MailAddress 'p1sender@domain.com','P1 Sender'# P2 address$Message.Sender = New-Object System.Net.Mail.MailAddress 'p2sender@domain.com','P2 Sender'$Message.To.Add('recipient@company.com')$Message.Subject = 'Test senders'$Message.Body = @'Check out my sender names!-I'm P1 or P2, but you'll never know'@# Send using SmtpClient$SmtpClient = New-Object System.Net.Mail.SmtpClient 'mailhost.domain.com'$SmtpClient.Send($Message)