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"

53 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