Email multiple people individual attachments - powershell

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)
}

Related

Send Mail from Powershell failing [duplicate]

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.

Send email via SMTP Mail server

I have installed SMTP Virtual Server in windows server 2012 r2. Later I have used following PowerShell script to send the email. Which was successful
$email = "xxxxxxxxxx#xxxxxx.com"
$pass = "xxxxxxx"
$smtpServer = "smtp.office365.com"
$smtpPort = "25"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.EnableSsl = $true
$msg.From = "$email"
$attachment = New-Object Net.Mail.Attachment("C:abcd/123.txt");
$msg.Attachments.Add($attachment);
$msg.To.Add("xxxx#xxxxx.com")
$msg.BodyEncoding = [system.Text.Encoding]::Unicode
$msg.SubjectEncoding = [system.Text.Encoding]::Unicode
$msg.IsBodyHTML = $true
$msg.Subject ="List of users"
$msg.Body=$msg.Body = "<h2> hi everyone </h2>
$SMTP.Credentials = New-Object System.Net.NetworkCredential("$email", "$pass");
$smtp.Send($msg)
here my question is can I send email without using from address in the above script(Is there any chance to save from email address and credentials somewhere in SMTP virtual server settings so that script can take credentials directly). I don't want to use from email address and credentials in above script
I'd suggest using Send-MailMessage instead of manual .NET manipulation:
$Creds = Import-CliXml -Path 'C:\mycreds.xml'
$MailArgs = #{ 'SmtpServer' = 'smtp.office365.com'
'Port' = 25
'To' = 'xxxx#xxxxx.com'
'From' = $Creds.UserName
'Subject' = 'List of users'
'Attachments' = 'C:\abcd\123.txt'
'Body' = '<h2> hi everyone </h2>'
'Encoding' = [Text.Encoding]::Unicode
'BodyAsHtml' = $true
'UseSsl' = $true
'Credential' = $Creds
}
Send-MailMessage #MailArgs
And you would create your $Creds object as follows:
Get-Credential -Credential 'xxxxxxxxxx#xxxxxx.com' | Export-CliXml -Path 'C:\mycreds.xml'
There are a couple extra options you might be interested in (such as notification of delivery) you can read about in the doc linked above.
Additionally, your password is encrypted when exported using Export-CliXml specific to that device and account utilizing DPAPI.

Send mail via powershell without authentication

I was using nant to send mail and it is working fine - something like
<mail
from="Test#b.c"
tolist="A#b.c"
subject="Test"
mailhost="myhost.mydomain.com"
isbodyhtml="true"
message= "${Test}">
</mail>
I didn't have to use any kind of authentication.
Now when using powershell it seems I am forced to use authentication - something like this would fail:
Send-MailMessage -To $to -From $from -Subject "Test" –Body “Test (body) -SmtpServer "myhost.mydomain.com"
I would get the following message:
Send-MailMessage : No credentials are available in the security package
Am I missing some way to send mails without specifying credentials if the server supports that?
Edit:
I've also tried the answer here to send anonymous mails but it just times out:
send anonymous mails using powershell
Sending mails using Powershell v1 method works fine without authentication as shown here
My Powershell version is 5 yet this is apparently the way to go, unless someone has another idea.
$smtpServer = "ho-ex2010-caht1.exchangeserverpro.net"
$smtpFrom = "reports#exchangeserverpro.net"
$smtpTo = $to
$messageSubject = $subject
$messageBody = $body
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)
I was looking for another issue and found this question here...
As #AngelicCore already explained one approach,
Here is another one if someone using Outlook dektop app...
The mail sent will appear in your outbox.
using outlook object
Try
{
#Email structure
$Outlook = New-Object -ComObject Outlook.Application
$Mail = $Outlook.CreateItem(0)
#Email Recipients
$Mail.To = "abc#domain.com;xyz#domain.com"
$Mail.Cc = "tuv#domain.com; pqr#domain.com"
#Email Subject
$date = Get-Date -Format g
$Mail.Subject = "Subject here $date"
#Email Body
$Mail.Body = "Body Here"
#Html Body
$Mail.HTMLBody == "<html> HTML Body Here </html>"
#Email Attachment
$file = "C:\path\xyz.txt"
$Mail.Attachments.Add($file)
$Mail.Send()
Write-Host -foreground green "Mail Sent Successfully"
}
Catch
{
write-host -foreground red $error[0].Exception.Message
}
pause
exit

In PowerShell, is there a way to dispose of Send-MailMessage resources?

I've written a PowerShell script that sends an email message. Originally I used the Send-MailMessage commandlet.
Send-MailMessage -SmtpServer $MailServer `
-To $MailTo `
-From $MailFrom `
-Subject $MailSubject `
-Body $MailBody
This is concise. But if I execute the script rapidly in succession on my workstation, the following error appears in the PowerShell console.
Unable to read data from the transport connection: An established
connection was aborted by the software in your host machine.
What I suspect is that resources aren't being released or that a thread is getting blocked. Below is my current workaround, which has the advantage of being disposable. And I can run this in rapid succession with no transport connection errors. But this is more verbose than Send-MailMessage.
[object]$SMTPClient = New-Object System.Net.Mail.SmtpClient
[object]$MailMessage = New-Object System.Net.Mail.MailMessage
$SMTPClient.Host = $MailServer
$MailMessage.To.Add($MailTo)
$MailMessage.From = $MailFrom
$MailMessage.Subject = $MailSubject
$MailMessage.Body = $MailBody
$SMTPClient.Send($MailMessage)
$MailMessage.Dispose()
$SMTPClient.Dispose()
Is there some way to force Send-MailMessage to release resources when I'm done with it, perhaps via Dispose or a C# style using statement? Thanks.
Frankly, "it works but it's verbose" shouldn't be a huge concern, especially when "verbose" means 10 lines. And I mean, you can simplify your syntax by using the class constructors:
$SMTPClient = New-Object -TypeName System.Net.Mail.SmtpClient -ArgumentList $MailServer
$MailMessage = New-Object -TypeName System.Net.Mail.MailMessage -ArgumentList $MailFrom, $MailTo, $MailSubject, $MailBody
$SMTPClient.Send($MailMessage)
$MailMessage.Dispose()
$SMTPClient.Dispose()
Based on the comment, you could be overflowing whatever buffer there is for the cmdlet. This answer is more a point on style for the future (less chance of mistakes happening) by using splatting:
$MailMessage = #{
SmtpServer = $MailServer;
To = $MailTo;
From = $MailFrom;
Subject = $MailSubject;
Body = $MailBody;
}
Send-MailMessage #MailMessage
Edit-
This can also be done with the selected answer:
$Client = #{
TypeName = 'System.Net.Mail.SmtpClient';
ArgumentList = $MailServer;
}
$Message = #{
TypeName = 'System.Net.Mail.MailMessage';
ArgumentList = #($MailFrom,$MailTo,$MailSubject,$MailBody);
}
$SMTPClient = New-Object #Client
$MailMessage = New-Object #Message

Powershell, send email with outlook as different email

We have some powershell automation in place which sends an email with outlook with one email account but we are looking for a way to be able to set the sender email address to a different outlook account we have access to.
I've tried googling and looking round on here and cant seem to find the way of doing it.
here is the code we are using.
$Outlook = New-Object -comObject Outlook.Application
$Mail = $Outlook.CreateItem(0)
start-sleep 5
$Mail.subject = ""
$mail.
$Mail.To = ""
$Mail.Cc = ""
$Mail.Body = "Test"
$Mail.Display()
$Mail.Send()
Just use the below Outlook function to send the email. You are actually doing the same over there. Is there any error you are getting ? Anyways, Use the below one:
Follow all the comments in the function for your reference.
Function Global:Send-Email {
[cmdletbinding()]
Param (
[Parameter(Mandatory=$False,Position=0)]
[String]$Address = "user2#domain.com",
[Parameter(Mandatory=$False,Position=1)]
[String]$Subject = "Mail Subject",
[Parameter(Mandatory=$False,Position=2)]
[String]$Body = "MailBody"
)
Begin {
Clear-Host
# Add-Type -assembly "Microsoft.Office.Interop.Outlook"
}
Process {
# Create an instance Microsoft Outlook
$Outlook = New-Object -ComObject Outlook.Application
$Mail = $Outlook.CreateItem(0)
$Mail.To = "$Address"
$Mail.Subject = $Subject
$Mail.Body =$Body
# $Mail.HTMLBody = "HTML BODY"
# $File = "D:\CP\timetable.pdf"
# $Mail.Attachments.Add($File)
$Mail.Send()
} # End of Process section
End {
# Section to prevent error message in Outlook
$Outlook.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook)
$Outlook = $null
} # End of End section!
} # End of function
# Example of using this function
Send-Email #-Address User2#domain.com
Note: If you want to send email from someone's behalf then you have to enable anonymous mail from the connectors or the user should have the permission to send mail from someone's behalf. In that case, you can add one more object as
$mail.From=""
One sample example to send mail from GMAIl as reference.
$From = "YourEmail#gmail.com"
$To = "AnotherEmail#YourDomain.com"
$Cc = "YourBoss#YourDomain.com"
$Attachment = "C:\temp\Some random file.txt"
$Subject = "Email Subject"
$Body = "Insert body text here"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject `
-Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `
-Credential (Get-Credential) -Attachments $Attachment
Hope it helps...