I'm trying to figure out how to use PowerShell V2's Send-MailMessage with Gmail.
Here's what I have so far.
$ss = New-Object Security.SecureString
foreach ($ch in "password".ToCharArray())
{
$ss.AppendChar($ch)
}
$cred = New-Object Management.Automation.PSCredential "uid#example.com", $ss
Send-MailMessage -SmtpServer smtp.gmail.com -UseSsl -Credential $cred -Body...
I get the following 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 foo.ps1:18 char:21
+ Send-MailMessage <<<< `
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
Am I doing something wrong, or is Send-MailMessage not fully baked yet (I'm on CTP 3)?
Some additional restrictions:
I want this to be non-interactive, so Get-Credential won't work.
The user account isn't on the Gmail domain, but a Google Apps registered domain.
For this question, I'm only interested in the Send-MailMessage cmdlet. Sending mail via the normal .NET API is well understood.
Here's my PowerShell Send-MailMessage sample for Gmail...
Tested and working solution:
$EmailFrom = "notifications#somedomain.com"
$EmailTo = "me#earth.com"
$Subject = "Notification from XYZ"
$Body = "this is a notification from XYZ Notifications.."
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Just change $EmailTo, and username/password in $SMTPClient.Credentials... Do not include #gmail.com in your username...
This should fix your problem:
$credentials = New-Object Management.Automation.PSCredential “mailserver#yourcompany.com”, (“password” | ConvertTo-SecureString -AsPlainText -Force)
Then use the credential in your call to Send-MailMessage -From $From -To $To -Body $Body $Body -SmtpServer {$smtpServer URI} -Credential $credentials -Verbose -UseSsl
I just had the same problem and ran into this post. It actually helped me to get it running with the native Send-MailMessage command-let and here is my code:
$cred = Get-Credential
Send-MailMessage ....... -SmtpServer "smtp.gmail.com" -UseSsl -Credential $cred -Port 587
However, in order to have Gmail allowing me to use the SMTP server, I had to log in into my Gmail account and under this link https://www.google.com/settings/security set the "Access for less secure apps" to "Enabled". Then finally it did work!!
I'm not sure you can change port numbers with Send-MailMessage since Gmail works on port 587. Anyway, here's how to send email through Gmail with .NET SmtpClient:
$smtpClient = New-Object system.net.mail.smtpClient
$smtpClient.Host = 'smtp.gmail.com'
$smtpClient.Port = 587
$smtpClient.EnableSsl = $true
$smtpClient.Credentials = [Net.NetworkCredential](Get-Credential GmailUserID)
$smtpClient.Send('GmailUserID#gmail.com', 'yourself#somewhere.com', 'test subject', 'test message')
I used Christian's Feb 12 solution and I'm also just beginning to learn PowerShell. As far as attachments, I was poking around with Get-Member learning how it works and noticed that Send() has two definitions... the second definition takes a System.Net.Mail.MailMessage object which allows for Attachments and many more powerful and useful features like Cc and Bcc. Here's an example that has attachments (to be mixed with his above example):
# append to Christian's code above --^
$emailMessage = New-Object System.Net.Mail.MailMessage
$emailMessage.From = $EmailFrom
$emailMessage.To.Add($EmailTo)
$emailMessage.Subject = $Subject
$emailMessage.Body = $Body
$emailMessage.Attachments.Add("C:\Test.txt")
$SMTPClient.Send($emailMessage)
Enjoy!
I am really new to PowerShell, and I was searching about gmailing from PowerShell. I took what you folks did in previous answers, and modified it a bit and have come up with a script which will check for attachments before adding them, and also to take an array of recipients.
## Send-Gmail.ps1 - Send a gmail message
## By Rodney Fisk - xizdaqrian#gmail.com
## 2 / 13 / 2011
# Get command line arguments to fill in the fields
# Must be the first statement in the script
param(
[Parameter(Mandatory = $true,
Position = 0,
ValueFromPipelineByPropertyName = $true)]
[Alias('From')] # This is the name of the parameter e.g. -From user#mail.com
[String]$EmailFrom, # This is the value [Don't forget the comma at the end!]
[Parameter(Mandatory = $true,
Position = 1,
ValueFromPipelineByPropertyName = $true)]
[Alias('To')]
[String[]]$Arry_EmailTo,
[Parameter(Mandatory = $true,
Position = 2,
ValueFromPipelineByPropertyName = $true)]
[Alias('Subj')]
[String]$EmailSubj,
[Parameter(Mandatory = $true,
Position = 3,
ValueFromPipelineByPropertyName = $true)]
[Alias('Body')]
[String]$EmailBody,
[Parameter(Mandatory = $false,
Position = 4,
ValueFromPipelineByPropertyName = $true)]
[Alias('Attachment')]
[String[]]$Arry_EmailAttachments
)
# From Christian # stackoverflow.com
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SMTPClient($SmtpServer, 587)
$SMTPClient.EnableSSL = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("GMAIL_USERNAME", "GMAIL_PASSWORD");
# From Core # stackoverflow.com
$emailMessage = New-Object System.Net.Mail.MailMessage
$emailMessage.From = $EmailFrom
foreach ($recipient in $Arry_EmailTo)
{
$emailMessage.To.Add($recipient)
}
$emailMessage.Subject = $EmailSubj
$emailMessage.Body = $EmailBody
# Do we have any attachments?
# If yes, then add them, if not, do nothing
if ($Arry_EmailAttachments.Count -ne $NULL)
{
$emailMessage.Attachments.Add()
}
$SMTPClient.Send($emailMessage)
Of course, change the GMAIL_USERNAME and GMAIL_PASSWORD values to your particular user and password.
After many tests and a long search for solutions, I found a functional and interesting script code at #PSTip Sending emails using your Gmail 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
On a Windows 8.1 machine I got Send-MailMessage to send an email with an attachment through Gmail using the following script:
$EmFrom = "user#gmail.com"
$username = "user#gmail.com"
$pwd = "YOURPASSWORD"
$EmTo = "recipient#theiremail.com"
$Server = "smtp.gmail.com"
$port = 587
$Subj = "Test"
$Bod = "Test 123"
$Att = "c:\Filename.FileType"
$securepwd = ConvertTo-SecureString $pwd -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $securepwd
Send-MailMessage -To $EmTo -From $EmFrom -Body $Bod -Subject $Subj -Attachments $Att -SmtpServer $Server -port $port -UseSsl -Credential $cred
Send email with attachment using PowerShell -
$EmailTo = "udit043.ur#gmail.com" // abc#domain.com
$EmailFrom = "udit821#gmail.com" // xyz#gmail.com
$Subject = "zx" //subject
$Body = "Test Body" // Body of message
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "G:\abc.jpg" // Attachment
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body)
$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
$SMTPMessage.Attachments.Add($attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("udit821#gmail.com", "xxxxxxxx"); // xxxxxx-password
$SMTPClient.Send($SMTPMessage)
I had massive problems with getting any of those scripts to work with sending mail in powershell. Turned out you need to create an app-password for your gmail-account to authenticate in the script. Now it works flawlessly!
Here it is:
$filename = “c:\scripts_scott\test9999.xls”
$smtpserver = “smtp.gmail.com”
$msg = New-Object Net.Mail.MailMessage
$att = New-Object Net.Mail.Attachment($filename)
$smtp = New-Object Net.Mail.SmtpClient($smtpServer )
$smtp.EnableSsl = $True
$smtp.Credentials = New-Object System.Net.NetworkCredential(“username”, “password_here”); # Put username without the #GMAIL.com or – #gmail.com
$msg.From = “username#gmail.com”
$msg.To.Add(”boss#job.com”)
$msg.Subject = “Monthly Report”
$msg.Body = “Good MorningATTACHED”
$msg.Attachments.Add($att)
$smtp.Send($msg)
Let me know if it helps you San. Also use the send-mailmessage also at
Www.techjunkie.tv
For that way also that I think is way better and pure to use.
I haven't used PowerShell V2's Send-MailMessage, but I have used System.Net.Mail.SMTPClient class in V1 to send messages to a Gmail account for demo purposes. This might be overkill, but I run an SMTP server on my Windows Vista laptop (see this link). If you're in an enterprise you will already have a mail relay server, and this step isn't necessary. Having an SMTP server I'm able to send email to my Gmail account with the following code:
$smtpmail = [System.Net.Mail.SMTPClient]("127.0.0.1")
$smtpmail.Send("myacct#gmail.com", "myacct#gmail.com", "Test Message", "Message via local SMTP")
I agree with Christian Muggli's solution, although at first I still got the error that Scott Weinstein reported. How you get past that is:
EITHER first login to Gmail from the machine this will run on, using the account specified. (It is not necessary to add any Google sites to the Trusted Sites zone, even if Internet Explorer Enhanced Security Configuration is enabled.)
OR, on your first attempt, you will get the error, and your Gmail account will get a notice about suspicious login, so follow their instructions to allow future logins from the machine this will run on.
I am using Send-MailMessage to email multiple different recipients each with an individual report. I have just been repeating the Send-Mail command with the different attachment paths for each recipient however the problem I am running into since I also have to use -UseSsl -credential I have to authenticate each time a new message is sent. Is there a way to authenticate once without having to do it each time?
Send-MailMessage is a wrapper for .net smtpclient. You can do your custom version of it, for example:
$client = New-Object System.Net.Mail.SmtpClient
$client.EnableSsl = $true
$client.Host = "smtp.server.com"
$client.Credentials = $creds
foreach ($r in $recipients) {
$from = "from#mail.com"
$to = $r
$msg = New-Object System.Net.Mail.MailMessage $from, $to
$msg.Subject = "subject"
$msg.Body = "body"
$msg.Attachments.Add("C:\temp\test.html")
$client.Send($msg)
}
Okay so i'm trying to send one email using powershell v2 to some recipients in a text file named emailtargets formatted in new line. below is the sendmailer script.
$emailSmtpServer = "mail.xxxxxxxxx.com"
$emailSmtpServerPort = "587"
$SourceRCPT = "xxxxx#xxxxxxxxx.com"
$DestFile = "emailTargets.txt"
$BodyFile = "emailBody.txt"
$SubjectLine = "testing"
$Pass = "xxxxxxx"
# Start Loop for Email Sending
$file = Get-Content $DestFile
$body = Get-Content $BodyFile
foreach ($line in $file){
$DestinationRCPT = $line.Split(",")[0]
$firstName = $line.Split(",")[1]
$lastName = $line.Split(",")[2]
$body =(Get-Content $BodyFile) | foreach-object {$_ -replace '\[firstName\]',$firstName}| foreach-object {$_ -replace '\[lastName\]',$lastName}
$emailSmtpUser = "$SourceRCPT"
$emailSmtpPass = "$Pass"
$emailFrom = "$SourceRCPT"
$emailTo = "$DestinationRCPT"
$emailMessage = New-Object System.Net.Mail.MailMessage( $emailFrom , $emailTo )
$emailMessage.Subject = $SubjectLine
$emailMessage.IsBodyHtml = $true
$emailMessage.Body = $body
$SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer , $emailSmtpServerPort )
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser.Split("#")[0] , $emailSmtpPass );
$SMTPClient.Send( $emailMessage )
Write-Host "Sending Email to $DestinationRCPT"
Now the question is i keep getting the error below while testing with office 365
And i get the below error while testing with a different smtp server
What am i doing wrong?
Its a certificate validation issue, If you are okay in suppressing it, you can do
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
before sending the message.
Here a set of samples that should assist you in re-writing this to function.
Overview of Cmdlets Available in Windows PowerShell Windows
PowerShell 2.0
https://technet.microsoft.com/en-us/library/ff714569.aspx
Use this example
https://gallery.technet.microsoft.com/scriptcenter/Send-MailMessage-3a920a6d
...
$params = #{
InlineAttachments = $images
Attachments = 'C:\temp\attachment1.txt', 'C:\temp\attachment2.txt'
Body = $body
BodyAsHtml = $true
Subject = 'Test email'
From = 'username#gmail.com'
To = 'recipient#domain.com'
Cc = 'recipient2#domain.com', 'recipient3#domain.com'
SmtpServer = 'smtp.gmail.com'
Port = 587
Credential = (Get-Credential -Credential 'username#gmail.com')
UseSsl = $true
}
Send-MailMessage #params
Or
# Using the PS built-in / online help files.
Get-Command -Name Send-MailMessage
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Send-MailMessage
3.1.0.0 Microsoft.PowerShell.Utility
# get function / cmdlet details
(Get-Command -Name Send-MailMessage).Parameters.Keys
Attachments
Bcc
Body
BodyAsHtml
Encoding
Cc
DeliveryNotificationOption
From
SmtpServer
Priority
Subject
To
Credential
UseSsl
Port
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
# Get the examples and modify per your use case, splatting used to make it easier to read on the forum.
Get-help -Name Send-MailMessage -Examples
# Example 1: Send an email from one user to another
$Params = #{
To = "User01 <user01#example.com>"
From = "User02 <user02#example.com>"
Subject = "Test mail"
Credential = (Get-Credential -Credential 'user#fabrikam.com')
SmtpServer = "smtp.fabrikam.com"
UseSsl = $true
Port = 587
}
Send-MailMessage #Params
# This command sends an email message from User01 to User02.
#
# The mail message has a subject, which is required, but it does not have a
# body, which is optional. Also, because the SmtpServer parameter is not
# specified,
#
# Send-MailMessage uses the value of the $PSEmailServer preference variable
# for the SMTP server.
# Example 2: Send an attachment
$Params = #{
From = "User01 <user01#example.com>"
To = "User02 <user02#example.com>", "User03 <user03#example.com>"
Subject = "Sending the Attachment"
Body = "Forgot to send the attachment. Sending now."
Attachments = "data.csv"
Priority = High
dno = 'onSuccess, onFailure'
Credential = (Get-Credential -Credential 'user#fabrikam.com')
SmtpServer = "smtp.fabrikam.com"
UseSsl = $true
Port = 587
}
Send-MailMessage #Params
# This command sends an email message with an attachment from User01 to two
# other users.
# It specifies a priority value of High and requests a delivery notification
# by email when the email messages are delivered or when they fail.
# Example 3: Send email to a mailing list
$Params = #{
To = "User01 <user01#example.com>"
From = "ITGroup <itdept#example.com>"
Cc = "User02 <user02#example.com>"
bcc = "ITMgr <itmgr#example.com>"
Subject = "Don't forget today's meeting!"
Credential = 'domain01\admin01'
UseSsl = $true
SmtpServer = "smtp.fabrikam.com"
Port = 587
}
Send-MailMessage #Params
# This command sends an email message from User01 to the ITGroup mailing list
# with a copy (Cc) to User02 and a blind carbon copy (Bcc) to the IT manager
# (ITMgr).
#
# The command uses the credentials of a domain administrator and the UseSsl
# parameter.
Get-help -Name Send-MailMessage -Full
Get-help -Name Send-MailMessage -Online
What I am hoping to do is once a new email hits a folder containing a specific subject. That email is then forwarded to another inbox and a specific file is automatically attached. The code I have been able to cobble together so far is this. Is a .Net method the appropriate method to achieve my goal or would using Send-MailMessge to a hastable be better method? I am new to PowerShell code I am able to get both methods to work. But was wondering A. which method is preferred. B. is there a better/more efficient way?
#####Define Variables########
$fromaddress = "donotreply#fromemail.com"
$toaddress = "blah#toemail.com"
$bccaddress = "blah#bcc.com"
$CCaddress = "blah#cc.com"
$Subject = "ACtion Required"
$body = get-content .\content.htm
$attachment = "C:\sendemail\test.txt"
$smtpserver = "smtp.labtest.com"
##############################
$message = new-object System.Net.Mail.MailMessage
$message.From = $fromaddress
$message.To.Add($toaddress)
$message.CC.Add($CCaddress)
$message.Bcc.Add($bccaddress)
$message.IsBodyHtml = $True
$message.Subject = $Subject
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$message.body = $body
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)
(Example of the hashtable method
$emailHashSplat = #{ To = $toAddress
From = $fromAddress
Subject = $emailSubject
Body = $emailBody SMTPServer = $smtpServer BodyAsHtml =
$true Attachments = "C:\sendemail\test.txt" # Attachments =)
Stick with Powershell commands whenever possible, .NET might be faster in some cases but it is a best practice to use only Powershell commands when possible.
Also make sure your code is easy to read and understand by others, using hastables with splatting wil help with this, see the following example: Github Gist Link (Click Me!)
Copy of the code, in case of link failure.
### Script Global Settings
#Declare SMTP Connection Settings
$SMTPConnection = #{
#Use Office365, Gmail, Other or OnPremise SMTP Relay FQDN
SmtpServer = 'outlook.office365.com'
#OnPrem SMTP Relay usually uses port 25 without SSL
#Other Public SMTP Relays usually use SSL with a specific port such as 587 or 443
Port = 587
UseSsl = $true
#Option A: Query for Credential at run time.
Credential = Get-Credential -Message 'Enter SMTP Login' -UserName "emailaddress#domain.tld"
<#
#Option B: Hardcoded Credential based on a SecureString
Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList #(
#The SMTP User Emailaddress
"emailaddress#domain.tld"
#The Password as SecureString encoded by the user that wil run this script!
#To create a SecureString Use the folowing Command: Read-Host "Enter Password" -AsSecureString | ConvertFrom-SecureString
"Enter the SecureString here as a single line" | ConvertTo-SecureString
)
#>
}
### Script Variables
#Declare Mailmessages.
$MailMessageA = #{
From = "emailaddress#domain.tld"
To = #(
"emailaddress#domain.tld"
)
#Cc = #(
# "emailaddress#domain.tld"
#)
#Bcc = #(
# "emailaddress#domain.tld"
#)
Subject = 'Mailmessage from script'
#Priority = 'Normal' #Normal by default, options: High, Low, Normal
#Attachments = #(
#'FilePath'
#)
#InlineAttachments = #{
#'CIDA'='FilePath'
#} #For more information about inline attachments in mailmessages see: https://gallery.technet.microsoft.com/scriptcenter/Send-MailMessage-3a920a6d
BodyAsHtml = $true
Body = "Something Unexpected Occured as no Content has been Provided for this Mail Message!" #Default Message
}
### Script Start
#Retrieve Powershell Version Information and store it as HTML with Special CSS Class
$PSVersionTable_HTLM = ($PSVersionTable.Values | ConvertTo-Html -Fragment) -replace '<table>', '<table class="table">'
#Retrieve CSS Stylesheet
$CSS = Invoke-WebRequest "https://raw.githubusercontent.com/advancedrei/BootstrapForEmail/master/Stylesheet/bootstrap-email.min.css" | Select-Object -ExpandProperty Content
#Build HTML Mail Message and Apply it to the MailMessage HashTable
$MailMessageA.Body = ConvertTo-Html -Title $MailMessageA.Subject -Head "<style>$($CSS)</style>" -Body "
<p>
Hello World,
</p>
<p>
If your recieved this message then this script works.</br>
</br>
<div class='alert alert-info' role='alert'>
Powershell version
</div>
$($PSVersionTable_HTLM)
</P>
" | Out-String
#Send MailMessage
#This example uses the HashTable's with a technique called Splatting to match/bind the Key's in the HashTable with the Parameters of the command.
#Use the # Symbol instead of $ to invoke Splatting, Splatting improves readability and allows for better management and reuse of variables
Send-MailMessage #SMTPConnection #MailMessageA
I'd like to send email from PowerShell,
so I use this command:
$EmailFrom = "customer#yahoo.com"
$EmailTo = "receiver#ymail.com"
$Subject = "today date"
$Body = "TODAY SYSTEM DATE=01/04/2016 SYSTEM TIME=11:32:05.50"
$SMTPServer = "smtp.mail.yahoo.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object
System.Net.NetworkCredential("customer#yahoo.com", "password")
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
This command didn't work for Yahoo mail or Outlook mail, but works for my Gmail.
Is there anything wrong that I have done?
Following code snippet really works for me:
$Username = "MyUserName";
$Password = "MyPassword";
$path = "C:\attachment.txt";
function Send-ToEmail([string]$email, [string]$attachmentpath){
$message = new-object Net.Mail.MailMessage;
$message.From = "YourName#gmail.com";
$message.To.Add($email);
$message.Subject = "subject text here...";
$message.Body = "body text here...";
$attachment = New-Object Net.Mail.Attachment($attachmentpath);
$message.Attachments.Add($attachment);
$smtp = new-object Net.Mail.SmtpClient("smtp.gmail.com", "587");
$smtp.EnableSSL = $true;
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message);
write-host "Mail Sent" ;
$attachment.Dispose();
}
Send-ToEmail -email "reciever#gmail.com" -attachmentpath $path;
I use this:
Send-MailMessage -To hi#abc.com -from hi2#abc.com -Subject 'hi' -SmtpServer 10.1.1.1
You can simply use the Gmail smtp.
Following is The powershell code to send a gmail message with an Attachment:
$Message = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient("smtp.gmail.com", 587)
$smtp.Credentials = New-Object System.Net.NetworkCredential("From#gmail.com", "password");
$smtp.EnableSsl = $true
$smtp.Timeout = 400000
$Message.From = "From#gmail.com"
$Message.To.Add("To#gmail.com")
$Message.Attachments.Add("C:\foo\attach.txt")
$smtp.Send($Message)
On the sender Google Account (From#gmail.com),
Make sure you have Turned ON Access for less-secure apps option,
from google Account Security Dashboard.
Finally, Save this Script As mail.ps1
To invoke the above Script Simple run below on Command Prompt or batch file:
Powershell.exe -executionpolicy remotesigned -File mail.ps1
By Default, For sending Large Attachments Timeout is Around 100 seconds or so.
In this script, it is increased to Around 5 or 6 minutes
Sometimes you may need to set the EnableSsl to false (in this case the message will be sent unencrypted over the network)