Tuesday, 29 January 2013

Sending SMTP Emails with Powershell using Authentication

The following script can be used to send an email message using SMTP. This method is slightly different to my previous post about sending email messages in Powershell as this method uses the smtpClient method rather than mailmessage in order to allow for authentication to occur.

$From = "fromaddress@domain.com"
$To = "toaddress@domain.com"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "username@gmail.com"
$Password = "gmailpassword"
$subject = "Email Subject"
$body = "Insert body text here"

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);

$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($From, $To, $subject, $body);

You will need to update the values of the first 8 variables to match what is required for the email account/domain you are sending from.

The SMTP Server and Port number will vary for different email providers - I can confirm the server and port specified above for Gmail are correct though.

UPDATE - 29/11/13

You can also use the System.Net.Mail.MailMessage class to give you the additional option to add CC, BCC, attachments etc, as per the below script. Simply update the first 9 variables below to configure your email message.

$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "username@gmail.com"
$Password = ""

$to = "user1@domain.com"
$cc = "user2@domain.com"
$subject = "Email Subject"
$body = "Insert body text here"
$attachment = "C:\test.txt"

$message = New-Object System.Net.Mail.MailMessage
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.cc.add($cc)
$message.from = $username
$message.attachments.add($attachment)

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)
write-host "Mail Sent"

66 comments:

  1. Perfect! This is just what I needed. thanks!

    ReplyDelete
  2. It helped me, thanks much!

    ReplyDelete
  3. Please help me to advise how to add cc and attachment in this scripts, Thanks

    ReplyDelete
    Replies
    1. Hi Baktash - thanks for your comment. I have updated the original post to give you details on how to do this (add CC and attachment).

      Delete
  4. Great tutorial. Do you have any idea how the message body can have newlines? My body gets concatenated in a single line...

    ReplyDelete
    Replies
    1. To start a new line use `r`n

      eg. $body = "line 1 text `r`n line 2 text `r`n line 3 text

      The inverted single quote (next to the "1" key) is an escape character, used to format text. Hope this helps :-)

      Delete
  5. Perfect! Exactly what I'm looking for! Great job! Thanks.

    ReplyDelete
  6. Good Job..Much Appreciated

    ReplyDelete
  7. This post has everything I needed to set up my email script. Thanks so much!!!!!!

    ReplyDelete
  8. Good Job.. But How To Add Many attachments?

    ReplyDelete
  9. Hi friend, I followed your script but the error message appears:
    -------------------------------------------------------------------------------------
    Exception calling "Send" with "1" argument(s): "Failure sending mail."
    At C:\Users\Rodrigo\Desktop\MonitorPS\SendMail.ps1:148 char:5
    + $smtp.Send($msg)
    + ~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SmtpException
    --------------------------------------------------------------------------------------
    Please, do you have any idea?
    Thanks,
    Rodrigo

    ReplyDelete
  10. Hi Peter
    Great post, may thnx. I'm getting the same error as Rodrigo. Somehow it seems as though the credentials do not get applied correctly in PS4. Any tips on that? (Applying creds in PS4)
    Many thanks again
    Willem

    ReplyDelete
    Replies
    1. Rodrigo/Willem - I just tested this myself using Powershell 4.0, copy and pasted both of my examples above and it worked fine. What email domain are you sending from? eg. Gmail, Yahoo, Hotmail?

      Delete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Hello Peter, this command works perfectly when using standard Gmail authentication method, but do you know if there is a way to send 2-step verification codes?

    ReplyDelete
    Replies
    1. # Google provides the ability to create "App passwords" that allows you to configure a 16 character application specific password.
      # Login to your google account, then go to https://myaccount.google.com/security
      # scroll down page and select "App passwords"
      # then select "Mail" or "Other" and specify a device name (for your own information), then Generate
      # the 16 char password becomes a direct login password to your gmail account that you can use with your normal login user id in powershell. I have used this technique successfully with powershell from Windows 10 and windows 8.1
      # when you decide you no longer need that app password, you can always revoke it using the same page

      Delete
    2. This is great.Thanks for sharing.I have enabled two steps verification and was getting authentication failure error.now it got fixed based on the above method

      Delete
  13. Hi

    It mainly works but I cannot work out how to find the correct path for the attachemnet/

    ReplyDelete
  14. Hi Peter,

    I am trying to use the powershell script to send mails but I am facing a problem with the University gmail setup. When we login into mail.google.com we use the external account and we are redirect into the internal shibboleth authentication.
    So I am trying to figure out how to solve this problem inside the script without success.

    Have you any idea how to do that?

    Thanks for your help

    Mirco

    ReplyDelete
  15. Really worked!!!! thanks peter....
    It works fine across google Accounts but a delay seen when sending from a gmail account to other server accounts.

    ReplyDelete
  16. how can I add multiple recipients?

    ReplyDelete
  17. I need to send an email on specific event ID in event viewer. Can you please guide what I need to add to above script?

    ReplyDelete
    Replies
    1. Here's a powershell script to pull the specified events from the event log, you can redirect this to a text file. My example is looking for 3 different events, all related to restarts, but can be ANY event id you want to capture. This is run from the local machine but you can code it to pull from remote machines
      ===============codestart===============
      Get-EventLog System | Where-Object {$_.EventID -eq "1074" -or $_.EventID -eq "6008" -or $_.EventID -eq "1076"} | ft Machinename, TimeWritten, UserName, EventID, Message -AutoSize -Wrap
      ===============code end-===============

      Delete
    2. Here's a powershell script to pull the specified events from the event log, you can redirect this to a text file. My example is looking for 3 different events, all related to restarts, but can be ANY event id you want to capture. This is run from the local machine but you can code it to pull from remote machines
      ===============codestart===============
      Get-EventLog System | Where-Object {$_.EventID -eq "1074" -or $_.EventID -eq "6008" -or $_.EventID -eq "1076"} | ft Machinename, TimeWritten, UserName, EventID, Message -AutoSize -Wrap
      ===============code end-===============

      Delete
  18. Hi Peter, if I'm piping a command to the $body, can I still format the objects to display on different lines? Tried using carriage returns in the form of Get-Content C:\input.txt | ForEach-Object {$_.Line + "`r`n"} but doesn't seem to be working.

    ReplyDelete
  19. for me it work with this script , I run it from the local host of exchange
    $SMTPServer = "2k8x64Ex2k10.EXCHDOM.COM"
    #$SMTPPort = "587"
    $SMTPPort = "25"
    #Username = "2k8x64Ex2k10@EXCHDOM.COM"
    #$Username = "Administrator@EXCHDOM.COM"
    $Username = "test@EXCHDOM.COM"
    $Password = "rrrrrrrrr"

    $to = "test@EXCHDOM.COM"
    $cc = "test@EXCHDOM.COM"
    $subject = "Email Subject"
    $body = "Insert body text here"
    #$attachment = "C:\test.txt"
    #$message = New-Object [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true }
    $message = New-Object System.Net.Mail.MailMessage
    $message.subject = $subject
    $message.body = $body
    $message.to.add($to)
    $message.cc.add($cc)
    $message.from = $username
    #$message.attachments.add($attachment)

    $smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
    $smtp.EnableSSL = $true
    $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true }
    #$smtp.UseDefaultCredentials=$true
    $smtp.send($message)
    write-host "Mail Sent"

    ReplyDelete
  20. Tried using this script with both gmail accounts and other email accounts, using the correct info etc. but always fails with a timeout and never actually sends the email, any ideas?

    ReplyDelete
    Replies
    1. log into your gmail, you should see an "unauthorized" login attempt, this script, like all the others, is missing a critical piece to force it to basic authentication. this script will work on an exchange server, but as written here, will not authenticate to gmail.

      Delete
    2. This script, like all the others has been tested and works with my gmail account and has done so since the article was first published
      Have you got any local firewall/antivirus software that may be blocking the connection?

      Delete
    3. For this to work, you have to turn on the option to allow access to less secure apps in your Google account security settings.

      Delete
  21. Hi Peter,

    I am using Powershell 3.0 ISE and have tried running the code you provided to send a basic e-mail to and from my personal g-mail account.

    I keep getting the following error message:

    Exception calling "Send" with "4" arguments: "The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first. p39sm5629990qkp.47 - gsmtp"

    Any thoughts?

    ReplyDelete
    Replies
    1. I am getting a similar message

      Exception calling "Send" with "1" argument(s): "The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1
      Authentication Required. Learn more at"
      At line:21 char:1
      + $smtp.send($message)
      + ~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
      + FullyQualifiedErrorId : SmtpException

      Delete
  22. Thank you for the information, I think this article is very useful for all who read it.
    .

    ReplyDelete
  23. Thanks so very much for this. Been trying to send mail to a restricted DL using send-mailmessage and simply cannot get it to accept the credentials I feed it. The method detailed here works like a charm, though!

    ReplyDelete
  24. Hi Peter,
    useful post mate, now become my collection of powershell script. Recently I use powershell to let me know about free disk space condition on the server, I post it here http://yunarwinardi.com/free-disk-space-alerts-to-your-email-easy-steps/

    Thanks

    ReplyDelete
  25. Nice post. It worked good. Thanks

    ReplyDelete
  26. I am using SendGrid SMTP (smtp.sendgrid.net) for sending email, but getting the error
    Send-MailMessage : Unable to read data from the transport connection: net_io_connectionclosed.
    At line:36 char:5
    + Send-MailMessage -smtpServer $SMTPServer -Credential $SGCredentia ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage],
    SmtpException
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

    ReplyDelete
  27. Great tutorial. Do you have any idea how the message body can have newlines? My body gets concatenated in a single line...

    Oxford Security

    ReplyDelete
  28. I love this great article

    ReplyDelete
  29. This comment has been removed by a blog administrator.

    ReplyDelete
  30. This comment has been removed by a blog administrator.

    ReplyDelete
  31. Do you have any idea how the message body can have newlines?

    ReplyDelete
    Replies
    1. As the body is html code, use < br > for a new line, or < p > for a new paragrah (remove the spaces between the brackets and characters - needs to be formatted like this in order for it to post)

      Delete
  32. Nice post. It worked good. Thanks

    ReplyDelete
  33. this script will work on an exchange server, but as written here, will not authenticate to gmail.

    ReplyDelete
  34. This comment has been removed by the author.

    ReplyDelete
  35. Great article, Thanks for sharing

    ReplyDelete
  36. Now i can send an email message using SMTP. Thanks for sharing such awesome information.

    ReplyDelete
  37. Exception calling "Send" with "1" argument(s): "The SMTP server requires a secure connection or the client was not
    authenticated. The server response was: 5.5.1 Authentication Required

    ReplyDelete
    Replies
    1. sounds like you aren't configured to send using SSL - make sure the $smtp.EnableSSL = $true is present

      Delete
  38. Thanks for sharing such awesome information.

    ReplyDelete
  39. what is username and password in this script? Is it system username and password..?

    ReplyDelete
    Replies
    1. You need to use the username and password for the email account you are sending from

      The username would typically be the email address

      Delete
  40. Peter, I stumbled upon your "Sending SMTP Emails with Powershell using Authentication" last night after having tried so many others - exactly what I needed , well almost! I'd really like only to send, say, the last dozen lines of a log file which has the pertinent information? Many thanks for your efforts and all respondents! Michael

    ReplyDelete
  41. Hi Michael - you can use the following to include text (the last 12 lines) from a log file in the body of the email

    $body = get-content "C:\blah\logfile.log"
    $body = $body[-12..-1]

    -12 represents the 12th last line of the file, -1 represents the last line of the file. You just need to change the path above to match where your log file is located

    The $body variable is already used in my original example above for the body text of the email ($message.body = $body)

    Hope this helps!

    ReplyDelete
  42. Hi Peter,

    Thanks for sharing, however I'm getting the error that was raised by some ppl on earlier comments. Please see below:

    "Send" with "1" argument(s): "The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required.

    I just changed the values with my creds but still getting the error. I'm using a gmail account.

    TIA

    Regards,
    Chii

    ReplyDelete
    Replies
    1. You may have to allow access to "less secure apps" in your google account settings

      Go to https://myaccount.google.com/lesssecureapps and set it to "On" and try again

      Delete
  43. You may have to allow access to "less secure apps" in your google account settings

    Go to https://myaccount.google.com/lesssecureapps and set it to "On" and try again

    ReplyDelete
  44. This comment has been removed by a blog administrator.

    ReplyDelete
  45. Hey men, i have a problem with the premission for the System.Net.Mail.Attachment and the last line get another error: Exception calling "Send" with "1" argument(s): "Faild to send the mail."
    At line:23 char:1
    + $smtp.send($message)
    + ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SmtpException

    ReplyDelete
  46. Found this and used it on my Windows 2012 PS script
    It worked exactly as described when I needed my PS script to bounce SMTP mail through the Earthlink (smtpauth.earthlink.net 587) using my Earthlink account to authenticate.
    Copied and pasted, changed the needed details for my account and it worked.
    There was one confusing error message from the SMTP server when I 1st tried it due to a typo in the password. It complained it could not deliver the email to all recipients.

    ReplyDelete