send email using powershell from command prompt - powershell

i'm using this powershell script to send emails:
param($EmailFrom,$EmailTo,$Subject,$Body)
$Username = 'user#gmail.com';
$Password = 'pass';
$emailMsg = New-Object System.Net.Mail.MailMessage
$emailMsg.From = $EmailFrom
$emailMsg.To.Add($EmailTo)
$emailMsg.Subject = $Subject
$emailMsg.Body = $Body
$smtpClient = New-Object System.Net.Mail.SmtpClient
$smtpClient.Host = 'smtp.gmail.com'
$smtpClient.Port = 587
$smtpClient.EnableSsl = $true
$smtpClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtpClient.Send($emailMsg);
write-host "Mail Sent"
Calling it from command prompt like this works (I send the email to myself and I get in my inbox):
powershell -command "& {C:\path\sendGmailPSS.ps1 -EmailFrom mail -EmailTo mail2 -Subject 'test' -Body 'test'}"
But putting it in a bat file like this:
#echo off
powershell -command "& {C:\path\sendGmailPSS.ps1 -EmailFrom %1 -EmailTo %2 -Subject '%~3' -Body '%~4'}"
and calling it like this:
sendGmail.bat mail mail2 "test" "test"
doesn't work (I send the email to myself and even though in cmd I get the "Mail Sent" message, I don't get anything in my inbox)
what i'm doing wrong?

Related

Launch a powershell function in a new window from inside a windows service

I have the following function:
Function Email{
param ($to, $Subject, $Body, $Attachment)
$Outlook = New-Object -Com Outlook.Application
$Mail = $Outlook.CreateItem(0)
$Mail.To = $To
$Mail.Subject = $Subject
$Mail.Body = $Body
$Mail.Attachments.Add($Attachment)
$Mail.Send()
}
It works perfectly in tests in the ISE, but from within another script running as a service it fails. So within that parent script I am trying to launch it in a new powershell instance to see if it will run there, but it does not seem to. Within the parent script I have:
Import-Module C:\...\Email.ps1
$to = Myemail
$Subject = "Test"
$Result = $Result[0].FullName
$Body = (-join("'",$Result,"'"))
write-host $to $Subject $Body $Result #test to make sure params are visible, test successful
$Command = Email $to $Subject $Body $Result
Start-Process powershell -ArgumentList "-WindowStyle Maximized -command invoke-command -scriptblock {$command} -argumentlist $to $Subject $Body $Result"
However it still appears to be non-functional within the service. Is this because of an error on my part?

Use powershell to send an email in outlook without locking up if Outlook is already running

I have the following program:
Function Email{
param ($to, $Subject, $Body, $Attachment)
if($process=(get-process 'outlook'))
{
kill($process)
Stop-Process $process -Force
#$namespace = $outlook.GetNameSpace("MAPI")
#$namespace.Logon("outlook")
}
$Outlook = New-Object -Com Outlook.Application
$session = $outlook.Session
$session.Logon("Outlook")
$Mail = $Outlook.CreateItem(0)
foreach ($person in $to){
$Mail.Recipients.add($person)
}
$Mail.Subject = $Subject
$Mail.Body = $Body
$Mail.Attachments.Add($Attachment)
$Mail.Send()
}
When tested in ISE and in batch, it functions as expected. However, when used in another powershell script, it randomly causes the script to hang up and I cannot open outlook manually due to an error about multiple instances.
How can I re-write this to properly account for an instance of outlook running (or at least so that it doesn't cause a script that uses it to hang up)?
Update: I have also tried it as:
Function Email{
param ($to, $Subject, $Body, $Attachment)
$Creds = Import-CliXml c:\localdata\cred.clixml
$username= myemail
Send-MailMessage -To $to -subject $Subject -body $Body -Attachment $Attachment -UseSsl -Port 587 -SmtpServer smtp.office365.com -From $username -Credential $creds
}
and I cannot get past the "cannot connect to remote server" error
Running telnet smtp.office365.com 587 or telnet smtp.office365.com 25 doesn't seem to return anything.

Powershell email not including attachment?

I am trying to set up a batch file which will call a Powershell and ultimately send a file on the users computer to a given email address. While I can get the email to send, it always sends without the attachment included.
The batch file code i have is:
powershell.exe -executionpolicy bypass -file C:\Users\attachment2.ps1
and the Powershell code I have is:
$attachment = "C:\Users\SearchResults\37.csv"
$EmailFrom = "david#gmail.com"
$EmailTo = "john#gmail.com"
$Subject = "The subject of your email"
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$Body = "This is just a test mail to verify the working of CMD"
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxx", "xxxx");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $attach, $Body)
If anyone knows as to why the attachment is not being included it would be of great help. I have looked at other examples on stackoverflow as well as other sites but have been not able to fix my own code. Any help would be greatly appreciated.

Sending email fails with error "unable to connect to remote server" [duplicate]

I'm having difficulty passing my credentials to the Send-MailMessage command
This is what I am running:
Send-MailMessage -smtpServer smtp.gmail.com -from 'myself#gmail.com' `
-to 'myself#gmail.com' -subject 'Test' -attachment C:\CDF.pdf
it errors with below the message which is obviously because I have not passed my gmail credentials
Send-MailMessage : 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.
I googled a bit and also went through the man page of Send-MailMessage and found that the "-credential" parameter needs to be passed.
My issue is: HOW ?
I tried with Get-Credentials as below:
$mycredentials = Get-Credential
Then entered my usrname and password for gmail in the box that pops up.
then I run below command:
Send-MailMessage -smtpServer smtp.gmail.com -credentail $mycredentials `
-from 'myself#gmail.com' -to 'myself#gmail.com' -subject 'Test' -attachment C:\CDF.pdf
and still it fails with the exact same error.
So I need help from you guys on how do I pass my Credentials to the Send-MailMessage command. I learned about PScredentials but not exactly sure what it is and how to use it in this context.
I found this blog site: Adam Kahtava
I also found this question: send-mail-via-gmail-with-powershell-v2s-send-mailmessage
The problem is, neither of them addressed both your needs (Attachment with a password), so I did some combination of the two and came up with this:
$EmailTo = "myself#gmail.com"
$EmailFrom = "me#mydomain.com"
$Subject = "Test"
$Body = "Test Body"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "C:\CDF.pdf"
$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("username", "password");
$SMTPClient.Send($SMTPMessage)
Since I love to make functions for things, and I need all the practice I can get, I went ahead and wrote this:
Function Send-EMail {
Param (
[Parameter(`
Mandatory=$true)]
[String]$EmailTo,
[Parameter(`
Mandatory=$true)]
[String]$Subject,
[Parameter(`
Mandatory=$true)]
[String]$Body,
[Parameter(`
Mandatory=$true)]
[String]$EmailFrom="myself#gmail.com", #This gives a default value to the $EmailFrom command
[Parameter(`
mandatory=$false)]
[String]$attachment,
[Parameter(`
mandatory=$true)]
[String]$Password
)
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
if ($attachment -ne $null) {
$SMTPattachment = New-Object System.Net.Mail.Attachment($attachment)
$SMTPMessage.Attachments.Add($SMTPattachment)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($EmailFrom.Split("#")[0], $Password);
$SMTPClient.Send($SMTPMessage)
Remove-Variable -Name SMTPClient
Remove-Variable -Name Password
} #End Function Send-EMail
To call it, just use this command:
Send-EMail -EmailTo "Myself#gmail.com" -Body "Test Body" -Subject "Test Subject" -attachment "C:\cdf.pdf" -password "Passowrd"
I know it's not secure putting the password in plainly like that. I'll see if I can come up with something more secure and update later, but at least this should get you what you need to get started. Have a great week!
Edit: Added $EmailFrom based on JuanPablo's comment
Edit: SMTP was spelled STMP in the attachments.
And here is a simple Send-MailMessage example with username/password for anyone looking for just that
$secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
Send-MailMessage -SmtpServer mysmptp -Credential $cred -UseSsl -From 'sender#gmail.com' -To 'recipient#gmail.com' -Subject 'TEST'
It took me a while to combine everything, make it a bit secure, and have it work with Gmail. I hope this answer saves someone some time.
Create a file with the encrypted server password:
In Powershell, enter the following command (replace myPassword with your actual password):
"myPassword" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\EmailPassword.txt"
Create a powershell script (Ex. sendEmail.ps1):
$User = "usernameForEmailPassword#gmail.com"
$File = "C:\EmailPassword.txt"
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)
$EmailTo = "emailTo#yahoo.com"
$EmailFrom = "emailFrom#gmail.com"
$Subject = "Email Subject"
$Body = "Email body text"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "C:\fileIwantToSend.csv"
$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($cred.UserName, $cred.Password);
$SMTPClient.Send($SMTPMessage)
Automate with Task Scheduler:
Create a batch file (Ex. emailFile.bat) with the following:
powershell -ExecutionPolicy ByPass -File C:\sendEmail.ps1
Create a task to run the batch file. Note: you must have the task run with the same user account that you used to encrypted the password! (Aka, probably the logged in user)
That's all; you now have a way to automate and schedule sending an email and an attachment with Windows Task Scheduler and Powershell. No 3rd party software and the password is not stored as plain text (though granted, not terribly secure either).
You can also read this article on the level of security this provides for your email password.
PSH> $cred = Get-Credential
PSH> $cred | Export-CliXml c:\temp\cred.clixml
PSH> $cred2 = Import-CliXml c:\temp\cred.clixml
That hashes it against your SID and the machine's SID, so the file is useless on any other machine, or in anyone else's hands.
So..it was SSL problem. Whatever I was doing was absolutely correct. Only that I was not using the ssl option. So I added "-Usessl true" to my original command and it worked.
in addition to UseSsl, you have to include smtp port 587 to make it work.
Send-MailMessage -SmtpServer smtp.gmail.com -Port 587 -Credential $credential -UseSsl -From 'yyy#gmail.com' -To 'xxx#email.com' -Subject 'TEST'
Along with the other answers i would like to point out that if you have two factor authentication, you will need to create an application password on your google account.
For the detailed explanations : https://support.google.com/accounts/answer/185833

How to pass credentials to the Send-MailMessage command for sending emails

I'm having difficulty passing my credentials to the Send-MailMessage command
This is what I am running:
Send-MailMessage -smtpServer smtp.gmail.com -from 'myself#gmail.com' `
-to 'myself#gmail.com' -subject 'Test' -attachment C:\CDF.pdf
it errors with below the message which is obviously because I have not passed my gmail credentials
Send-MailMessage : 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.
I googled a bit and also went through the man page of Send-MailMessage and found that the "-credential" parameter needs to be passed.
My issue is: HOW ?
I tried with Get-Credentials as below:
$mycredentials = Get-Credential
Then entered my usrname and password for gmail in the box that pops up.
then I run below command:
Send-MailMessage -smtpServer smtp.gmail.com -credentail $mycredentials `
-from 'myself#gmail.com' -to 'myself#gmail.com' -subject 'Test' -attachment C:\CDF.pdf
and still it fails with the exact same error.
So I need help from you guys on how do I pass my Credentials to the Send-MailMessage command. I learned about PScredentials but not exactly sure what it is and how to use it in this context.
I found this blog site: Adam Kahtava
I also found this question: send-mail-via-gmail-with-powershell-v2s-send-mailmessage
The problem is, neither of them addressed both your needs (Attachment with a password), so I did some combination of the two and came up with this:
$EmailTo = "myself#gmail.com"
$EmailFrom = "me#mydomain.com"
$Subject = "Test"
$Body = "Test Body"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "C:\CDF.pdf"
$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("username", "password");
$SMTPClient.Send($SMTPMessage)
Since I love to make functions for things, and I need all the practice I can get, I went ahead and wrote this:
Function Send-EMail {
Param (
[Parameter(`
Mandatory=$true)]
[String]$EmailTo,
[Parameter(`
Mandatory=$true)]
[String]$Subject,
[Parameter(`
Mandatory=$true)]
[String]$Body,
[Parameter(`
Mandatory=$true)]
[String]$EmailFrom="myself#gmail.com", #This gives a default value to the $EmailFrom command
[Parameter(`
mandatory=$false)]
[String]$attachment,
[Parameter(`
mandatory=$true)]
[String]$Password
)
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
if ($attachment -ne $null) {
$SMTPattachment = New-Object System.Net.Mail.Attachment($attachment)
$SMTPMessage.Attachments.Add($SMTPattachment)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($EmailFrom.Split("#")[0], $Password);
$SMTPClient.Send($SMTPMessage)
Remove-Variable -Name SMTPClient
Remove-Variable -Name Password
} #End Function Send-EMail
To call it, just use this command:
Send-EMail -EmailTo "Myself#gmail.com" -Body "Test Body" -Subject "Test Subject" -attachment "C:\cdf.pdf" -password "Passowrd"
I know it's not secure putting the password in plainly like that. I'll see if I can come up with something more secure and update later, but at least this should get you what you need to get started. Have a great week!
Edit: Added $EmailFrom based on JuanPablo's comment
Edit: SMTP was spelled STMP in the attachments.
And here is a simple Send-MailMessage example with username/password for anyone looking for just that
$secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
Send-MailMessage -SmtpServer mysmptp -Credential $cred -UseSsl -From 'sender#gmail.com' -To 'recipient#gmail.com' -Subject 'TEST'
It took me a while to combine everything, make it a bit secure, and have it work with Gmail. I hope this answer saves someone some time.
Create a file with the encrypted server password:
In Powershell, enter the following command (replace myPassword with your actual password):
"myPassword" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\EmailPassword.txt"
Create a powershell script (Ex. sendEmail.ps1):
$User = "usernameForEmailPassword#gmail.com"
$File = "C:\EmailPassword.txt"
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)
$EmailTo = "emailTo#yahoo.com"
$EmailFrom = "emailFrom#gmail.com"
$Subject = "Email Subject"
$Body = "Email body text"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "C:\fileIwantToSend.csv"
$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($cred.UserName, $cred.Password);
$SMTPClient.Send($SMTPMessage)
Automate with Task Scheduler:
Create a batch file (Ex. emailFile.bat) with the following:
powershell -ExecutionPolicy ByPass -File C:\sendEmail.ps1
Create a task to run the batch file. Note: you must have the task run with the same user account that you used to encrypted the password! (Aka, probably the logged in user)
That's all; you now have a way to automate and schedule sending an email and an attachment with Windows Task Scheduler and Powershell. No 3rd party software and the password is not stored as plain text (though granted, not terribly secure either).
You can also read this article on the level of security this provides for your email password.
PSH> $cred = Get-Credential
PSH> $cred | Export-CliXml c:\temp\cred.clixml
PSH> $cred2 = Import-CliXml c:\temp\cred.clixml
That hashes it against your SID and the machine's SID, so the file is useless on any other machine, or in anyone else's hands.
So..it was SSL problem. Whatever I was doing was absolutely correct. Only that I was not using the ssl option. So I added "-Usessl true" to my original command and it worked.
in addition to UseSsl, you have to include smtp port 587 to make it work.
Send-MailMessage -SmtpServer smtp.gmail.com -Port 587 -Credential $credential -UseSsl -From 'yyy#gmail.com' -To 'xxx#email.com' -Subject 'TEST'
Along with the other answers i would like to point out that if you have two factor authentication, you will need to create an application password on your google account.
For the detailed explanations : https://support.google.com/accounts/answer/185833