26

#PSTip Sending emails using your Gmail account

Note: This tip requires PowerShell 3.0 or above.

The Send-MailMessage cmdlet enables you to quickly and easily send e-mail message from within Windows PowerShell. In version 2.0, establishing connections that required alternate port numbers wasn’t possible simply because there wasn’t a way to specify them.

In PowerShell 3.0, we now have the Port parameter, together with the UseSsl switch (required to secure the session). You can send an email using your Gmail account.

The following example creates a splatting hash table and passes it to the Send-MailMessage cmdlet as one object. Execute the code (change the values to match your own and supply your Gmail credentials when prompted), and then check your email account.

$param = @{
    SmtpServer = 'smtp.gmail.com'
    Port = 587
    UseSsl = $true
    Credential  = 'you@gmail.com'
    From = 'you@gmail.com'
    To = 'someone@somewhere.com'
    Subject = 'Sending emails through Gmail with Send-MailMessage'
    Body = "Check out the PowerShellMagazine.com website!"
    Attachments = 'D:\articles.csv'
}

Send-MailMessage @param

For a PowerShell 2.0 solution, see this forum thread.

Filed in: Columns, Tips and Tricks Tags: , , , ,

26 Responses to "#PSTip Sending emails using your Gmail account"

  1. JVimes says:

    Note that if you use two-factor authentication you’ll need to set up and use an Application Specific Password. See https://support.google.com/accounts/answer/185833?hl=en

  2. Sathish Chandra says:

    it is asking password.. is it possible to specify password in this script..

    • ShayLevy says:

      Yes

      $pwd = ConvertTo-SecureString ‘P@ssw0rd’ -AsPlainText -Force
      $cred = New-Object System.Management.Automation.PSCredential you@gmail.com,$pwd

      $param = @{
      (…)
      Credential = $cred
      }

      Send-MailMessage @param

      • Sathish Chandra says:

        Hi levy

        i don’t want to specify password in this code.

        am storing encrypted password in .txt file. i want to use this file as a password.
        my code:

        $pwd = Get-Content E:PSscript by mesecurepassword.txt | ConvertTo-SecureString -AsPlainText -Force

        $cred = New-Object System.Management.Automation.PSCredential —@gmail.com,$pwd

        $param = @{
        #Credential = ‘—@gmail.com’
        Credential = $cred
        To = ‘–@gmail.com’
        Subject = ‘PS Test Mail From —-bhanu—-‘
        From = ‘—@gmail.com’
        Body = “PS Test Mail”
        SmtpServer = ‘smtp.gmail.com’
        Attachments = ‘C:UsersbhanuPicturesHD Photo Backgroundswall (2).jpg’
        #encrypted = Get-Content E:PSscript by mesecurepassword.txt | ConvertTo-SecureString
        #password = get-content E:PSscript by mesecurepassword.txt | convertto-securestring
        Port = 587
        UseSsl = $true
        }
        Send-MailMessage @param

        —-
        it is giving following error and its asking password again.
        PS C:windowssystem32> E:PSscriptbymesendmail-f.ps1
        Get-Content : A positional parameter cannot be found that accepts argument ‘by’.
        At E:PSscriptbymesendmail-f.ps1:1 char:8
        + $pwd = Get-Content E:PSscript by mesecurepassword.txt | ConvertTo-SecureStrin …

        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : InvalidArgument: (:) [Get-Content], ParameterBindingException
        + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetContentCommand

        New-Object : Cannot find an overload for “PSCredential” and the argument count: “2”.

        At E:PSscriptbymesendmail-f.ps1:2 char:9
        + $cred = New-Object System.Management.Automation.PSCredential –@gmail.com,$pwd
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
        + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

        plz suggest me…

        • ShayLevy says:

          Remove the -AsPlainText -Force parameters when you read the password from the file. The content is already secured, it is not plain text:

          $pwd = Get-Content E:PSscript by mesecurepassword.txt | ConvertTo-SecureString

          • Sathish Chandra says:

            Hi levy

            Even after removing -AsPlainText -Force parameters, Still its giving same error & asking for credentials.

          • ShayLevy says:

            Works fine for me, please post the full procedure you took to encrypt the password as well as the code snippet you used to send the mail.

          • Sathish Chandra says:

            Procedure to encrypt password:

            “01000000d08c9ddf0115d1118c7a00c04fc297eb010000000ffb51b2e604034a982598093219de570000000002000000000003660000c0000000100000004387d7a6f294bdcf25725159f7edaa390000000004800000a000000010000000efac6eb2cb924bf1cf893a9ddfdeeff71800000079b98b725901857051e84b78ba6e20da94752516a02833c114000000dbf49438a6ea07c06c3846fc23e725a081792782”

            $user = “labsukhijv”

            $password = ConvertTo-SecureString -string $encrypted

            $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $user,$password

            —————-

            Code i using:

            $encrypted = $pwd = Get-Content E:PSscriptbymesecurepassword.txt | ConvertTo-SecureString

            $cred = New-Object System.Management.Automation.PSCredential —–@gmail.com,$pwd

            $param = @{
            #Credential = ‘—–@gmail.com’
            Credential = $cred
            To = ‘—@gmail.com’
            Subject = ‘PS Test Mail From —-bhanu—-‘
            From = ‘—-@gmail.com’
            Body = “PS Test Mail”
            SmtpServer = ‘smtp.gmail.com’
            Attachments = ‘C:UsersbhanuPicturesHD Photo Backgroundswall (2).jpg’
            Port = 587
            UseSsl = $true
            }

            Send-MailMessage @param

            —————————————————

            Error msg:
            PS C:windowssystem32> E:PSscriptbymesendmail-f.ps1
            ConvertTo-SecureString : Key not valid for use in specified state.
            At E:PSscriptbymesendmail-f.ps1:1 char:58
            + $pwd = Get-Content E:PSscriptbymesecurepassword.txt | ConvertTo-SecureString

            + ~~~~~~~~~~~~~~~~~~~~~~

            + CategoryInfo : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException

            + FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand

            New-Object : Exception calling “.ctor” with “2” argument(s): “Cannot process argument because the value of argument “password” is null. Change the value of argument

            “password” to a non-null value.”

            At E:PSscriptbymesendmail-f.ps1:2 char:9

            + $cred = New-Object System.Management.Automation.PSCredential banu4me@gmail.com,$ …

            +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException

            + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

            ————-
            Still it is asking credentials.

          • ShayLevy says:

            Looks like the user name is not a gmail valid name, it should be ‘name@gmail.com’ and not ‘labsukhijv’.

            Give this snippet a try, I’ve just tested it and it worked perfectly. Make changes to the first three variables to match your info and execute it.

            $gmailPwd = ‘P@ssw0rd’
            $gmailUser = ‘name@gmail.com’
            $passFile = ‘d:tempsecurepassword.txt’

            #save password to file
            ConvertTo-SecureString $gmailPwd -AsPlainText -Force | ConvertFrom-SecureString | Out-File $passFile

            # read the password from the file
            $pass = Get-Content $passFile | ConvertTo-SecureString

            # create a new credential object
            $cred = New-Object System.Management.Automation.PSCredential $gmailUser,$pass

            $param = @{
            SmtpServer = ‘smtp.gmail.com’
            Port = 587
            UseSsl = $true
            Credential = $cred
            From = $gmailUser
            To = $gmailUser
            Subject = ‘Sending emails through Gmail with Send-MailMessage’
            Body = “Check out the PowerShellMagazine.com website!”
            }

            Send-MailMessage @param

          • Sathish Chandra says:

            Hi levy.
            now its working…
            thank you so much…for your help

      • Thomas Pawlowski says:

        I am trying to find a full script that will send a gmail email all automatic. So far I have this:

        $param = @{

        Credential = $cred
        SmtpServer = ‘smtp.gmail.com’
        Port = 587
        UseSsl = $true
        From = ‘MYEMAIL@gmail.com’
        To = ‘MYEMAIL@gmail.com’
        Subject = ‘TEST’
        Body = “TEST”
        $pwd = ConvertTo-SecureString ‘MYPASSWORD’ -AsPlainText -Force
        $cred = New-Object System.Management.Automation.PSCredential MYEMAIL@gmail.com,$pwd

        }

        Send-MailMessage @param

        I either end up getting an error or a pop up asking for the password. Do you know of a FULL script that currently works? Thanks

  3. Robert says:

    I ran across this script and it works perfectly, is there any way to easily wrap it in a function so I can feed it the subject and recipients?

    I kind of hack my way through Powershell and the couple of things I tried didn’t work.

  4. Shay Levy says:

    Sure, here’s a very basic function:

    function Send-GmailMessage
    {
    param(
    [string]$SmtpServer,
    [int]$Port,
    $Credential=(Get-Credential),
    [string]$From,
    [string[]]$To,
    [string]$Subject,
    [string]$Body,
    [string[]]$Attachments

    )

    $param = @{
    SmtpServer = $SmtpServer
    Port = $Port
    UseSsl = $true
    Credential = $Credential
    From = $From
    To = $To
    Subject = $Subject
    Body = $Body
    Attachments = $Attachments
    }

    Send-MailMessage @param
    }

  5. Stephen says:

    Hello
    i came across this page and i would like to implement this but i keep getting the error
    Send-MailMessage : Unable to connect to the remote server

  6. daniel says:

    Hi Shay, Im trying to use your script ubt it still keeps asking for username and password (using win2012r2)
    Could you lead in the right direction?

    $pwd = ConvertTo-SecureString ‘mypassword’ -AsPlainText -Force
    $cred = New-Object System.Management.Automation.PSCredential myemail@gmail.com,$pwd
    $param = @{
    SmtpServer = ‘smtp.gmail.com’
    Port = 587
    UseSsl = $true
    Credential = ‘myemail@gmail.com’
    From = ‘kdb001@gmail.com’
    To = ‘support@kdb.com’
    Subject = ‘Sending emails through Gmail with Send-MailMessage’
    Body = “Check out the PowerShellMagazine.com website!”
    Attachments = ‘C:\EmailNotification\backupresults.txt’
    }
    Credential = $cred
    Send-MailMessage @param

  7. Kirk Munro says:

    You’re getting prompted because you are invoking Send-MailMessage with a string as the credential parameter. Replace this line in your $param hashtable:

    Credential = ‘myemail@gmail.com’

    with this:

    Credential = $cred

    Then remove the Credential = $cred line just above your call to Send-MailMessage. Once you have made those two changes, you should be good to go.

    • Thomas Michael says:

      I am trying to run this:

      $pwd = ConvertTo-SecureString ‘MYPASSWORD’ -AsPlainText -Force
      $cred = New-Object System.Management.Automation.PSCredential myemail@gmail.com,$pwd
      $param = @{
      SmtpServer = ‘smtp.gmail.com’
      Port = 587
      UseSsl = $true
      Credential = $cred
      From = ‘MYEMAIL@gmail.com’
      To = ‘MYEMAIL@gmail.com’
      Subject = ‘TEST’
      Body = “TEST”
      }
      Send-MailMessage @param

      I keep getting this error:

      Send-MailMessage : 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:13 char:1
      + Send-MailMessage @param
      + ~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
      + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

      Do you know what is wrong or how I could fix it? Thanks!

      • Thomas Michael says:

        the “myemail@gmail.com” on the third line down was a typo, I meant to write “MYEMAIL@gmail.com, meaning my personal email address. 😀

  8. ymbird says:

    how to send to more than one email address

  9. ymbird says:

    solved by ,

  10. Jessa Lasin says:

    Hi, I am having problem with my code. Can anyone please help me . I am a beginner.

    #============================================================
    Param(
    [String]$Att,
    [String]$Subj,
    [String]$Body
    )

    Function Send-EMail
    {
    Param(
    [Parameter(
    Mandatory=$true)]
    [String]$To,
    [Parameter(

    Mandatory=$true)]
    [String]$From,
    [Parameter(
    Mandatory=$true)]
    [String]$Password,
    [Parameter(

    Mandatory=$true)]
    [String]$Subject,
    [Parameter(
    Mandatory=$true)]
    [String]$Body,
    [Parameter(

    Mandatory=$true)]
    [String]$attachment
    )

    try
    {
    $Msg = New-Object System.Net.Mail.MailMessage($From, $To, $Subject, $Body)
    $Srv = “smtp.gmail.com”
    if($attachment -ne $null)
    {
    try
    {
    $Attachments = $attachment -split (“\:\:”);

    ForEach($val in $Attachments)
    {
    $attch = New-Object System.net.Mail.Attachment($val)
    $Msg.Attachments.Add($attch)
    }
    }
    catch
    {
    exit 2;
    }

    $Client = New-Object Net.Mail.SmtpClient($Srv, 587)
    $Client.EnableSsl = $true
    $Client.Credentials = New-Object System.Net.NetworkCredential($From.Split(“@”)[0], $Password);
    $Client.Send($Msg)
    Remove-Variable -Name Client
    Remove-Variable -Name Password
    exit 7;
    }
    }
    catch
    {
    exit 3;
    }
    }

    try
    {
    Send-EMail
    -attachment $Att
    -To “someemail@gmail.com”
    -Body $Body
    -Subject $Subj
    -Password “somepassword”
    -From “someemail@gmail.com”
    }
    catch
    {
    exit 4;
    }
    #============================================================

    It give me this error and I dont know what is wrong with my code.

    PS C:\Users\Administrator> C:\Users\Administrator\AppData\Roaming\Microsoft\CLR\sm.ps1
    Missing expression after unary operator ‘-‘.
    At C:\Users\Administrator\AppData\Roaming\Microsoft\CLR\sm.ps1:70 char:10
    + – <<<< attachment $Att
    + CategoryInfo : ParserError: (-:String) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingExpressionAfterOperator

Leave a Reply

Submit Comment

© 2016 PowerShell Magazine. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
%d bloggers like this: