A useful technique for Exchange Server administrators is to be able to send email messages via SMTP from PowerShell. In this series of articles I will take you through different scripting techniques for sending email from your scripts.
- Part 1 – How to Send SMTP Email Using PowerShell
- Part 2 – How to Add a Message Body to Emails Sent from Scripts
- Part 3 – How to Add a HTML Message Body to Emails Sent from Scripts
- Part 4 – How to Create Formatted HTML Output from Scripts
There are a few different ways to do this, depending on the version of PowerShell installed on your computer or server. You can check the version number by typing $host in a PowerShell window.
PowerShell 1.0 will show this result:
PS C:\> $host Name : ConsoleHost Version : 1.0.0.0
PowerShell 2.0 will show this result:
PS C:\> $host Name : ConsoleHost Version : 2.0
Let’s take a look at how we can send SMTP email using each version of PowerShell.
Sending SMTP Email with PowerShell 1.0
For PowerShell 1.0 we can send mail by running these commands.
PS C:\> $smtp = New-Object Net.Mail.SmtpClient("ho-ex2010-caht1.exchangeserverpro.net") PS C:\> $smtp.Send("reports@exchangeserverpro.net","administrator@exchangeserverpro.net","Test Email","This is a test")
So what did we just do there? Let’s break it down.
- Created a new instance of a .NET object of class SmtpClient, connected to the SMTP server ho-ex2010-caht1 (a Hub Transport server)
- Used the Send method of the object to send an email message with the following:
- From address of “reports@exchangeserverpro.net”
- To address of “administrator@exchangeserverpro.net
- Subject of “Test Email”
- Body of “This is a test”
That works fine, though perhaps a bit cumbersome to type it out every time. Instead what we could do is create a script to send SMTP email using PowerShell 1.0.
# #.SYNOPSIS #Sends SMTP email via the Hub Transport server # #.EXAMPLE #.Send-Email.ps1 -To "administrator@exchangeserverpro.net" -Subject "Test email" -Body "This is a test" # param( [string]$to, [string]$subject, [string]$body ) $smtpServer = "ho-ex2010-caht1.exchangeserverpro.net" $smtpFrom = "reports@exchangeserverpro.net" $smtpTo = $to $messageSubject = $subject $messageBody = $body $smtp = New-Object Net.Mail.SmtpClient($smtpServer) $smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)
We can save that code as Send-Email.ps1 and run it from the PowerShell window.
PS C:\Scripts> .\Send-Email.ps1 -To "administrator@exchangeserverpro.net" -Subject "Test email" -Body "This is a test"
Less typing required, especially when you hard-code some of the variables such as the From address and SMTP server.
Sending SMTP Email with PowerShell 2.0
PowerShell 2.0 makes life a little easier thanks to the built in cmdlet Send-MailMessage. To send the same email as the above example we would run this command:
PS C:\> Send-MailMessage -From "reports@exchangeserverpro.net" -To "administrator@exchangeserverpro.net" -Subject "Test email" -Body "This is a test email"
One of the first things you might notice in the command above is that no SMTP server was specified. Send-MailMessage does have a -SmtpServer parameter, but if you don’t specify one it will just use the $PSEmailServer preference variable instead. This can be set for the session by running the following command:
PS C:\> $PSEmailServer = "ho-ex2010-caht1.exchangeserverpro.net"
Another point to note with Send-MailMessage is that is uses authenticated SMTP connections. By default it will use the credentials of the user executing the command. So you need to make sure you’re using an SMTP server that either:
- Permits that authenticated user credential to send email messages via SMTP
- Accepts anonymous SMTP/relay for the IP address of the sending host (you can see how to configure a relay connector for Exchange here)
Those are just a few simple examples of how to send email using SMTP and PowerShell 1.0 or 2.0.
I notice it is not leaving a copy in the outbox. How to do that? Also, how to send a blind copy? Thanks!
is there a way to write it using a Send As?
Is there a way to send a local file as an attachment for example a log file?
The Real Person!
Author Paul Cunningham acts as a real person and passed all tests against spambots. Anti-Spam by CleanTalk.
Yes, Send-MailMessage has an -Attachments parameter.
Pingback: Sending mail from Exchange powershell command line. – Damirov's blog
For my opinion, the command:set-senderidconfig “internalenablue” parameter NEED to be “TRUE” to prevent internal user sending fake emails to other staff.
Thank you for your sharing. I tried with your command to send email from Office 365. But with some of the computer, got error:
Exception calling “Send” with “4” argument(s): “The remote certificate is invalid according to the validation procedure”
Can you please me with this error?
Thank you.
$EmailFrom = “myaccount@domain.com”
$EmailTo = “emailaddress@domain.com”
$Subject = “Test from O365 SMTP”
$Body = “Test from O365 SMTP Authentication”
$SMTPServer = “smtp.office365.com”
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“myaccount@domain.com”, “*****”);
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Thanks paulfor all this informations, it’s very kind of you,
Pingback: [powershell] Envoyer un email avec des accents
Dear All,
Can anyone help me out to create a powershell script as per below requirements.
1. We are planning to add new SMTP address to our existing users and so we want to set auto reply message as per below to all user mailbox.
2. Script should take user display name with old email id and new email id and set below customize message on each of individual mailboxes
3. Reply message should be as per below
4. Script should take all BOLD content from excel sheet and set customize auto reply message to each individual mailboxes
Dear Sender,
Please note that my email id has been changed from abc@test.com to xyz@test.com , hence for the please send mail on new email id only…
Regards,
‘User name’
Note: We are having Exchange 2010 environment
Pingback: 2015 Year in Review for Exchange Server Pro
Im obliged for the blog article. Really Great.
Researching a little bit i found the solution!
It was just add a one more line
$smtp.UseDefaultCredentials=$true
The script is working fine now!
Hi, I wrote this code to send email requesting a few parameters to send an attached file with information between exchange servers in two different organizations
Write-Host -NoNewLine “Ingrese el fqdn del dominio de correo: ” -ForeGroundColor Yellow;$Suffix=Read-Host
Write-Host -NoNewLine “Ingrese el nombre de nuestro servidor Exchange: “-ForeGroundColor Yellow; $Server=Read-Host
Write-Host -NoNewLine “Ingrese la dirección de correo destino: “-ForeGroundColor Yellow;$Receipt_Mail_Address=Read-Host
Write-Host -NoNewLine “Ingrese la dirección de correo remitente: “-ForeGroundColor Yellow;$Sender_Mail_Address=Read-Host
Write-Host ” ”
Write-Host ” ”
$filename=“c:SyncContacts-“+$Suffix+”.txt”
$msg=new-object Net.Mail.MailMessage
$att=new-object Net.Mail.Attachment($filename)
$smtp=new-object Net.Mail.SmtpClient($Server)
$msg.From=$Sender_Mail_Address
$msg.To.Add($Receipt_Mail_Address)
$msg.Subject = “Correo automatizado – Contacts-“+$Suffix+”.TXT”
$msg.Body=“Envío automatizado del archivo Contacts-“+$Suffix+”.TXT”
$msg.Attachments.Add($filename)
$smtp.Send($msg)
Write-Host “Enviando Correo automatizado, por favor espere … ” -ForeGroundColor Green
Write-Host ” ”
Write-Host ” ”
Write-Host “Correo enviado” -ForeGroundColor Green
In Exchange 2010 it works fine, but in Exchange 2013 I receive an SMTP error 5.7.1 unable to relay, thats mean the script works fine but the server are not allowing to relay to the remote host, how can i solve this?
HOW TO ermits that authenticated user credential to send email messages via SMTP
If you want to foricbly send mails anonymous you can use the following script, it also reads a logfile for error strings and parses it in the e-mail for added benefit. 🙂
$User = “anonymous”
$PWord = ConvertTo-SecureString –String “anonymous” –AsPlainText -Force
$Creds = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pword
Send-MailMessage -From “from@from.com” -To “to@to.com” `
-SmtpServer “localmailserveriphere” `
-Subject “Subject” `
-BodyAsHtml `
-Credential $creds `
-Body @”
Errors! “`r”
$(Get-ChildItem C:TEMPsynctool*.log | `
Select-String -Pattern errors -AllMatches -SimpleMatch |
Foreach-Object {$_.Line}
out-string)
“@
Thanks…It works for me
I’m using Send-Mailmessage to generate a number of messages via foreach loop, but it recycles the session for each one. The relay server limit is 15 messages per smtp session, so I’m wondering if there is a way to force close the current SMTP session and make send-mailmessage start a new one.
thanks!
Hi Paul,
Yes i did change the server name and valid addresses!
Did you change the name of the SmtpClient to match your server name? And change the to/from address to match valid addresses?
The Real Person!
Author Paul Cunningham acts as a real person and passed all tests against spambots. Anti-Spam by CleanTalk.
I really need to update this tutorial for PS 2.0+ 🙂
Edit: oh wait, I already did!
I am trying to send mail by same command as gave above i.e.
PS C:\> $smtp = New-Object Net.Mail.SmtpClient(“ho-ex2010-caht1.exchangeserverpro.net”)
PS C:\> $smtp.Send(“reports@exchangeserverpro.net”,”administrator@exchangeserverpro.net”,”Test Email”,”This is a test”)
However i am getting error “Exception calling “Send” with “4” argument(s): “Failure sending mail.”
At line:1 char:11″
Can you please help me in this.
Appreciate your kind help.
hello,
if i’ve understand you can add ath the end of command -smtpserver and put @IP or mail server name,without using objects.try this
Send-MailMessage -From “reports@exchangeserverpro.net” -To “administrator@exchangeserverpro.net
” -Subject “Test email” -Body “This is a test email” -smtpserver “IP or server’s name”
This was a very easy to use script. Thanks!
Thanks Paul …
Can you help me with a simple problem I am having due to not being very good at Powershell.
I am using a super-so-simple get-content command to read a file with a list of users and move their mailbox to another mailstore and I would like to be able to use a send-mailmessage at the end to email each user to say the move has finished.
The line I am using is as follows,
Get-Content C:users.txt | Move-Mailbox -TargetDatabase “ServernameFirst Storage GroupMailbox Database” -Confirm:$false
This works OK enough but I would like to finish it off with the email functionality but I don’t know how to use the outputs of Get-Content such a System.Object, which I presume would do it for me if I knew my a*** from my elbow!
Any help greatly appreciated.
Very Useful Info. Delivered in an excellent way !!! Thanks much !!!
By having a quick looking I realized this site contains very helpfull information related to PowerShell.
Whenever I’ve got enough time I will have a closer look, because with PowerShell you can get almost everything you want to know and to export this information to any format as Word, Excel etc..
Thanks for the article. One question though. Will this be useful to test scenarios related to journaling. For instance, I have a requirement to automate tests related to journaling. With the above steps will the exchange server send out journaling messages to the configured connectors? Thanks.
The Real Person!
Author Paul Cunningham acts as a real person and passed all tests against spambots. Anti-Spam by CleanTalk.
I would assume so but you will quickly find out if you just test it.
Pingback: Scambler
Pingback: How to Set Up an Automated Exchange 2010 Database Backup Alert Email « Yogesh(Yogi)
Pingback: PowerShell Script: Check Exchange 2010 Database Backups
Pingback: How to Automate Exchange 2010 Database Backup Alert Emails
Pingback: PowerShell: How to Create Formatted HTML Output from Scripts
Pingback: PowerShell: How to Add a Message Body to Emails Sent from Scripts
Nice info. Learned a couple of things from this, including the $PSEmailServer info and the authenticated sending part.
Keep it up!
Tip: Put the line defining $PSEmailServer in your profile script so you always have it.