Powershell send email to recipients in Excel spreadsheet - powershell

I have a spreadsheet located at C:\scripts\test.csv containing a list of user email addresses.
I'm trying to send the below email to each of these users, but it's only sending to one of the users. How can I send it to all users?
$recipients = get-content C:\scripts\test.csv
$smtpServer = "mail.server.com"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "FromUser#email.com"
$msg.To.Add($recipients)
$msg.subject = "Requiring Updates"
$msg.IsBodyHTML = $true
$body = #'
<html>
<body>
<font face="calibri">Hello, please read this test email.</font>
</body>
</html>
'#
$msg.body = $body
$smtp.Send($msg)

So you have to iterate them one by one in a foreach loop.
Change your existing code to this:
$recipients = get-content C:\scripts\test.csv
foreach($rcpt in $recipients)
{
$smtpServer = "mail.server.com"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "FromUser#email.com"
$msg.To.Add($rcpt)
$msg.subject = "Requiring Updates"
$msg.IsBodyHTML = $true
$body = #'
<html>
<body>
<font face="calibri">Hello, please read this test email.</font>
</body>
</html>
'#
$msg.body = $body
$smtp.Send($msg)
}
Hope it helps.

This is the new answer since your requirement changed now.
Put the emailIds directly in the csv file one by one without quotes since I am already appending that. Now this will send one email to all the recipients reading from the file.
$recipients = get-content C:\scripts\test.csv
Remove-Variable rcpt -ErrorAction Ignore
Remove-Variable result -ErrorAction Ignore
Remove-Variable final_result -ErrorAction Ignore
foreach($rcpt in $recipients)
{
$result += "'$rcpt'" + ","
$final_result=$result.Trim(',')
$smtpServer = "mail.server.com"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "FromUser#email.com"
$msg.To.Add($final_result)
$msg.subject = "Requiring Updates"
$msg.IsBodyHTML = $true
$body = #'
<html>
<body>
<font face="calibri">Hello, please read this test email.</font>
</body>
</html>
'#
$msg.body = $body
}
$smtp.Send($msg)

Related

Powershell scripts to send multiple attachements as HTML format

I have prepared the below scripts to send multiple files as HTML format (not as attachments). But it is adding the company disclaimer within the table of 1st report while sending email.
[No issue with 2nd report].
############ START ############
$report = "C:\Reports\ADReport16.htm"
$report1 = "C:\Reports\ADReport26.htm"
$BodyReport1 = Get-Content "$report" -Raw
$BodyReport2 = Get-Content "$report1" -Raw
$BodyReport1 += $BodyReport2
Send-MailMessage -SmtpServer '10.10.10.10' -From 'AD.REPORT#microsoft.com' -To 'xxx.zzz#cisco.net' -Subject "Active Directory Health Report" -Body $BodyReport1 -BodyAsHtml
############ END ############
After reproducing from my end, I could able to make this work by setting IsBodyHtml to $true Below is the complete script that worked for me.
$report = "Report1.html"
$report1 = "Report2.html"
$BodyReport1 = Get-Content "$report" -Raw
$BodyReport2 = Get-Content "$report1" -Raw
$BodyReport1 += $BodyReport2
$emailPassword = "<PASSWORD>"
$emailCredential = New-Object System.Net.NetworkCredential("<EMAIL>", $emailPassword)
$smtpServer = "smtp.office365.com"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Port = 587
$smtp.EnableSSl = $true
$smtp.Credentials = $emailCredential
$messageObject = new-object Net.Mail.MailMessage
$messageObject.IsBodyHtml = $true
$messageObject.From = "<FROM>"
$messageObject.To.add("<TO>")
$msg.subject = "<SAMPLE_SUBJECT>"
$msg.body = $BodyReport1
$smtp.Send($msg)
RESULTS:

Powershell RDS CAL email Report

I have a PowerShell command that will get an output of how many CAL's I have installed and how many are used. I would like to instead of write-host, change it to a variable so that I can add it to the body of an email and have it run on a schedule, to email me weekly reports on usage, I would like to have the variable something like $report as shown in the $body of the email, this is what I have so far..
$fileName = (Invoke-WmiMethod Win32_TSLicenseReport -Name GenerateReportEx).FileName
$summaryEntries = (Get-WmiObject Win32_TSLicenseReport|Where-Object FileName -eq $fileName).FetchReportSummaryEntries(0,0).ReportSummaryEntries
$summaryEntries|ForEach {Write-Host $_.ProductVersion $_.TSCALType "Installed:" $_.InstalledLicenses "Issued:" $_.IssuedLicenses}
$EmailTo = "itgroup#contonso.com"
$EmailFrom = "admin#contonso.com"
$user = 'admin#contonso.com'
$password = Unprotect-CmsMessage -Path C:\Scripts\Powershell\EncryptedSecret.txt
$Subject = "Alert: CAL USAGE "
$Body = "Alert; $Report"
$SMTPServer = "smtp#contonso.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
$SMTPClient.EnableSsl = $false
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($user, $password)
$SMTPClient.Send($SMTPMessage)
I have used both parts of this script separately, but I would like to join them together, to make more useful. Thanks in advance PowerShell newbie..
Here is the full code that I used to get this to work, simply changing 'Write-Host' to 'Write-Output'
$fileName = (Invoke-WmiMethod Win32_TSLicenseReport -Name GenerateReportEx).FileName
$summaryEntries = (Get-WmiObject Win32_TSLicenseReport|Where-Object FileName -eq $fileName).FetchReportSummaryEntries(0,0).ReportSummaryEntries
$Report = $summaryEntries|ForEach {Write-Output $_.ProductVersion $_.TSCALType "Installed:" $_.InstalledLicenses "Issued:" $_.IssuedLicenses}
$EmailTo = "itgroup#contonso.com"
$EmailFrom = "admin#contonso.com"
$user = 'admin#contonso.com'
$password = Unprotect-CmsMessage -Path C:\Scripts\Powershell\EncryptedSecret.txt
$Subject = "RDS CAL USAGE REPORT"
$Body = "Alert; $Report"
$SMTPServer = "smtp#contonso.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
$SMTPClient.EnableSsl = $false
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($user, $password)
$SMTPClient.Send($SMTPMessage)

New to error handling

The path that I have set is not valid, when the copy fails I want to send an email to someone. If there is no error then send an email stating the copy was successful.
Current it doesnt give me an error and it doesnt send an email. I know that the email part is correct and confirmed it does work.
My script block.
try
{
Copy-Item -path "\\main-
4\info\SmartPlant\app\CitrixRelease\domain\app\*" -Destination "\\domain.com\citrix\Installation Media\app\" -force -ErrorAction Stop
}
catch
{
$from = "alerts#domain.com"
$to = "me#domain.com"
$subject = "Copy Failed"
$body = "The Copy failed to complete, please make sure the servers rebooted"
$msg = "$file"
$Attachment = "$file"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient("mail.domain.com")
$msg.From = $From
$msg.To.Add($To)
if($Attachment.Length -gt 1)
{
$msg.Attachments.Add($Attachment)
}
$msg.Subject = $Subject
$msg.IsBodyHtml = $true
$msg.Body = $Body
$smtp.Send($msg)
}
How about this as a solution for sending an email for both failure and success without duplicating the email send code:
$Status = 'Succeeded'
try{
Copy-Item -path "\\main-4\info\SmartPlant\app\CitrixRelease\domain\app\*" -Destination "\\domain.com\citrix\Installation Media\app\" -force -ErrorAction Stop
}catch{
$Status = 'Failed'
}finally{
$from = "alerts#domain.com"
$to = "me#domain.com"
$subject = "Copy $Status"
$body = "The Copy $Status"
If ($Status = 'Failed') {$body += ", please make sure the server is rebooted" }
$Attachment = "$file"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient("mail.domain.com")
$msg.From = $From
$msg.To.Add($To)
if($Attachment.Length -gt 1){
$msg.Attachments.Add($Attachment)
}
$msg.Subject = $Subject
$msg.IsBodyHtml = $true
$msg.Body = $Body
$smtp.Send($msg)
}
You don't really need to use a Finally block, but it does create a nice code block to make explicit what the email functionality belongs to.

How to send email with PowerShell

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)

How to attach a file to an email with PowerShell

I have written a PowerShell script that will create an email, however I can't seem to attach a file. The file does exist and PowerShell can open it, Could anyone tell me what I'm doing wrong?
$ol = New-Object -comObject Outlook.Application
$message = $ol.CreateItem(0)
$message.Recipients.Add("Deployment")
$message.Subject = "Website deployment"
$message.Body = "See attached file for the updates made to the website`r`n`r`nWarm Regards`r`nLuke"
# Attach a file this doesn't work
$file = "K:\Deploy-log.csv"
$attachment = new-object System.Net.Mail.Attachment $file
$message.Attachments.Add($attachment)
If you are on PowerShell 2.0, just use the built-in cmdlet Send-MailMessage:
C:\PS>Send-MailMessage -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." `
-Attachment "data.csv" -smtpServer smtp.fabrikam.com
If you copy/paste this watch out for the extra space added after the backtick. PowerShell doesn't like it.
I got the above to work by removing the line
$attachment = new-object System.Net.Mail.Attachment $file
and changing
$message.Attachments.Add($attachment)
to
$message.Attachments.Add($file)
While the solution provided by #Keith Hill would be better, even with a lot of goggling I couldn't get it to work.
This worked for me using powershell-
Define Variables:
$fromaddress = "donotreply#pd.com"
$toaddress = "test#pd.com"
$Subject = "Test message"
$body = "Please find attached - test"
$attachment = "C:\temp\test.csv"
$smtpserver = "mail.pd.com"
Use the variables in the script:
$message = new-object System.Net.Mail.MailMessage
$message.From = $fromaddress
$message.To.Add($toaddress)
$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)
You can use send-mailmessage or system.net.mail.MailMessage to accomplish it. Interestingly, there is a significant execution time difference between the two approaches. You can use measure-command to observe the execution time of the commands.
I have experienced such problem, (windows 10 / PS 5.1)
My SMTP is not authentified or secure ...
I have to finish by this line "MyAttacheObject.Dispose()"
... / and finally that's work :!
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$attach.Dispose()
this is my code with two attachments :
# Email configuration NO AUTH NO SECURE
$emailHost = "smtp.bot.com"
$emailUser = ""
$emailPass = ""
$emailFrom = "myemail#bot.com"
$emailsTo=#("toyoumylove#bot.com","toyoumybad#bot.com")
$emailSubject = $title
$emailbody=$body
$attachment1 = #($PATh+$outFile)
$attachment2 = #($PATh+$inFile)
#End of parameters
$msg = New-Object System.Net.Mail.MailMessage
$msg.from = ($emailFrom)
foreach ($d in $emailsTo) {
$msg.to.add($d)
}
$msg.Subject = $emailSubject
$msg.Body = $emailbody
$msg.isBodyhtml = $true
$att = new-object System.Net.Mail.Attachment($attachment1)
$msg.Attachments.add($att)
$att = new-object System.Net.Mail.Attachment($attachment2)
$msg.Attachments.add($att)
$smtp = New-Object System.Net.Mail.SmtpClient $emailHost
$smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPass);
$smtp.send($msg)
$att.Dispose()
"yourpassword" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "D:\Password.txt"
# The above command will encrypt the password you need to run this command only one time
# 1.Sign in to your work or school account, go to the My Account page, and select Security info.
2.Select Add method, choose App password from the list, and then select Add.
3.Enter a name for the app password, and then select Next. it will give password
# you should use this password in above mentioned command
$User = "mymail#company.net"
$File = "C:\Users\username\Desktop\Mail\Password.txt"
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString -AsPlainText -Force)
$EmailTo = "mymail#company.net"
$EmailFrom = "mymail#company.net"
$Subject = "SERVICE STOPPED"
$Body = "SERVICE STOPPED PFA Document to get more details."
$SMTPServer = "smtp.office365.com"
$filenameAndPath = "C:\Users\username\Desktop\new.txt"
$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)
I needed to drop the "-AsPlainText -Force"
$emailCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailUser, (Get-Content $emailPasswordFile | ConvertTo-SecureString)