Reputation: 63
I need to send one unique email to different email addresses exporting
them from a .csv
file. I have a code but it just sends the message to all
of the emails in one email.
#Import the file that store username and emails
$data = import-csv "C:.csv"
#Declare email content
$email = $data.Email | select -unique
ForEach ($email in $data)
{
$From = "***@gmail.com"
$To = $data.Email
$Subject = "Test"
$Body = "Test"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
}
#Sending email
Send-MailMessage -From $From -to $To -Subject $Subject `
-Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `
-Credential (Get-Credential -Message "Please input valid credentials")
The code above works but as mentioned it sends just one email to all the email addresses in the file. I need it to send one for each email.
Upvotes: 3
Views: 698
Reputation: 61028
The main problem I see in your code is that you first create an array of unique email addresses from the csv file in a variable $email
, but later on you overwrite that same value by using it in the foreach
loop.
There, in every iteration, the $email
variable will become a complete row from the CSV file which is obviously not what you expect it to be.
Below a slightly adjusted version of your code. Note that I also used Splatting to create a hashtable with all properties for the Send-MailMessage
cmdlet, to avoid having to use the easy to overlook backtick.
#Import the file that store username and emails
$data = import-csv "D:\mail.csv"
# Get a unique array of email addresses
$addresses = $data.Email | Select-Object -Unique
# Declare Credentials
$creds = (Get-Credential -Message "Please input valid credentials")
# loop through the email addresses array and send a mail to each of them
foreach ($email in $addresses) {
$splat = @{
From = "***@gmail.com"
To = $email
Subject = "Test"
Body = "Test"
SmtpServer = "smtp.gmail.com"
Port = 587
Credential = $creds
UseSsl = $true
}
#Sending email
Send-MailMessage @splat
}
Note that the -Port
parameter is of type Int32
, so you should not quote that
As requested in your comment, if you want to use more fields from the CSV file, then the code would change.
Let's assume your CSV looks anything like:
"User","Email","ManagerEmail" "Tom","[email protected]","[email protected]" "Dick","[email protected]","[email protected]" "Harry","[email protected]","[email protected]" "Dick","[email protected]","[email protected]"
(note, user Dick is duplicated)
Then the following will read the csv, deduplicate it on the Email property and send emails to each user:
# Import the file that store username and emails
# and uniquify the objectson property Email
$data = Import-Csv "D:\mail.csv" | Sort-Object -Property Email -Unique
# Declare Credentials
$creds = (Get-Credential -Message "Please input valid credentials")
# loop through the csv objects array and send a mail to each of them
foreach ($item in $data) {
# every item is an object with properties .User, .Email and .ManagerEmail
$splat = @{
From = "***@gmail.com"
To = $item.Email
Cc = $item.ManagerEmail
Subject = "Hi there {0}" -f $item.User
Body = "Test"
SmtpServer = "smtp.gmail.com"
Port = 587
Credential = $creds
UseSsl = $true
}
#Sending email
Send-MailMessage @splat
}
Hope that helps
Upvotes: 2
Reputation: 5217
Most important error you made is
$To = $data.Email
where you add all the emails to To:
field. Drew's suggestion is almost what you want to follow but with one remark. Your $To=
assignment should use $email
which represents single object from array, instead of the whole array (which is $data
).
$To = $email.Email
Edit: As @Theo suggested in the comments, it's worth mentioning that the line
$email = $data.Email | select -unique
won't work as you use the same variable name later in foreach
loop. What I'd suggest is to save unique email addresses to other variable
$uniqueEmails = $data.Email | select -unique
then iterate that one
# Change this
ForEach ($email in $data) {
# To this
ForEach ($email in $uniqueEmails ) {
And of course as you already saved Email
propert to $uniqueEmails
:
# This line
$To = $email.Email
# Should be changed to
$To = $email
Upvotes: 0
Reputation: 4020
As per comments, please find the adjusted script and reasoning.
You were looping through the CSV but only sending the email once. It looks like it would have originally sent the email to ONE person, that being the last in your CSV.
This version will loop through and send an email for each line in the CSV.
#Import the file that store username and emails
$data = import-csv "C:.csv"
#Declare email content
$email = $data.Email | select -unique
# Declare Credentials
$creds = (Get-Credential -Message "Please input valid credentials")
ForEach ($email in $data) {
$From = "***@gmail.com"
$To = $email.Email
$Subject = "Test"
$Body = "Test"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
#Sending email
Send-MailMessage -From $From -to $To -Subject $Subject `
-Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `
-Credential $creds
}
Upvotes: 1