Kent Dyer
asked on
Powershell - send to multiple recipients
I have been playing with PowerShell's Send-MailMessage and seems to work fine with one person to send to.. I have previously used Blat.exe with VBScript and it works fine. I even tried to convert the Blat Script over to PowerShell..
I have also seen this, but does not seem to work either..
http://powershell.com/cs/blogs/tips/archive/2012/04/23/sending-email-to-multiple-recipients.aspx
I have read that you need to setup multiple recipients in the following manner:
$To = ("recipient1@company.com", "recipient 2@company. com")
If I convert the blat Script..
Results are (have tried to pass individual parameters and the whole thing as one parameter):
Multiple recipients using Send-MailMessage:
I am reading in a "mapping" (settings) file as well.
Mapping Construct is:
And here is the code..
Here are the results..
Thanks,
Kent
I have also seen this, but does not seem to work either..
http://powershell.com/cs/blogs/tips/archive/2012/04/23/sending-email-to-multiple-recipients.aspx
I have read that you need to setup multiple recipients in the following manner:
$To = ("recipient1@company.com",
If I convert the blat Script..
function blat-Mail
{
param(
[Parameter(Mandatory = $true)]
[String[]]
$To,
[Parameter(Mandatory = $true)]
$Subject,
[Parameter(Mandatory = $true)]
$Body,
[Parameter(Mandatory = $true)]
$Attachment,
$From = "CustomerCare@somecompany.com",
$SmtpServer="RELAY.COMPANY.COM"
)
try {
$strCommand = """D:\WORK\Scripts\Blat.exe"
$strCommand = $strCommand + " -log $MailResult"
$strCommand = $strCommand + " -f ""$from"""
$strCommand = $strCommand + " -to ""$To"""
$strCommand = $strCommand + " -server ""$smtpserver"""
$strCommand = $strCommand + " -subject ""$subject"""
$strCommand = $strCommand + " -body ""$body"""
$strCommand = $strCommand + " -attach ""$Attachment"""
$strCommand = $strCommand + " -q"""
& $strCommand
##write-host $strCommand
Write-Host "Email successfully sent." -ForegroundColor Green
}
catch {
Write-Host "Email did not go through: $_" -ForegroundColor Red
}
}
$FullDate = Get-Date -format "yyyyMMdd000000"
$applog = "D:\WORK\Scripts\p1\AppLog\"
$mailresult = "$applog"+$FullDate+"_MailResult.txt"
blat-Mail "recipient1@company.com" "Daily Reports" "Attached are reports. If there are any issues or concerns please contact your Customer Service Representative immediately." "D:\WORK\Scripts\p1\ReportDownload\Temp\20130713_foo.zip"
Results are (have tried to pass individual parameters and the whole thing as one parameter):
D:\WORK\ps\Reports\kt.ps1
Email did not go through: The term '"D:\WORK\Scripts\Blat.exe-log D:\WORK\Scripts\p1\AppLog\ 2013071500 0000_MailR esult.txt -f "Cust
omerCare@somecompany.com" -to "recipient@fcompany.com" -server "RELAY.company.COM" -subject "Daily Reports" -body "Attached are
reports. If there are any issues or concerns please contact your Customer Service Representative immediately." -attach "D:\W
ORK\Scripts\p1\ReportDownload\Temp\2 0130713_fo o.zip" -q"' is not recognized as the name of a cmdlet, function, script fil
e, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Multiple recipients using Send-MailMessage:
I am reading in a "mapping" (settings) file as well.
Mapping Construct is:
COMPANY1,recipient1@somecompany.com; recipient2 @somecompa ny.com
COMPANY2,recipient1@anothercompany.c om;recipie nt2@anothe rcompany.c om;recipie nt3@anothe rcompany.c om;recipie nt4@anothe rcompany.c om
COMPANY3,recipien1@yetanothercompany .com
And here is the code..
#7 Email the resulting Zip files to companies
## to do: work on event log
$ScriptDir = Split-Path $MyInvocation.MyCommand.Path
#$applog = "$ScriptDir\AppLog\"
$applog = "D:\WORK\Scripts\p1\AppLog\"
#$bkup = "$ScriptDir\ReportDownload\BkUp\"
$bkup = "D:\WORK\Scripts\p1\ReportDownload\BkUp\"
#$temp = "$ScriptDir\ReportDownload\Temp\"
$temp = "D:\WORK\Scripts\p1\ReportDownload\Temp\"
#$Settings = "$ScriptDir\Settings.Txt"
$Settings = "D:\WORK\Scripts\Settings.Txt"
#READ IN SETTINGS FROM TEXT FILE
$setting = Get-Content $Settings -encoding String
foreach ( $set in $setting )
{
If ($set.split("=")[0] -eq "AdminRecipient")
{
$AdminRecipient = $set.split("=")[1]
}
If ($set.split("=")[0] -eq "smtpserver")
{
$smtpserver = $set.split("=")[1]
}
}
$FullDate = Get-Date -format "yyyyMMdd000000"
$Mapping = "D:\WORK\Scripts\p1\Mapping.Txt"
##$Mapping = "D:\WORK\Scripts\p1\Testing.Txt"
$mailresult = "$applog"+$FullDate+"_MailResult.txt"
# $sw = [Diagnostics.Stopwatch]::StartNew()
% { $i = 1 }
$DateLogged = Get-Date -format u
"Run Start: $DateLogged" | Out-File -append -filepath $MailResult -encoding ASCII
#NEED TO CHECK FOR THE EXISTENCE OF THE Mapping file
If (Test-Path $Mapping) {
$results=''
$count = @(Get-Content $Mapping).Length
$lists = Get-Content $Mapping -encoding String
"Number of COMPANIES: " + $count | Out-File -append -filepath $MailResult -encoding ASCII
foreach ($list in $lists)
{
$CompanyName = $list.split(",")[0]
$Email = $list.split(",")[1]
#IF THERE ARE MORE THAN ONE $EMAIL IN THE RECIPIENT LIST AND CONTAIS A ; IT NEEDS TO BE REPLACED
$files = Get-ChildItem -Path $temp
# verify if the list of source files is empty
foreach ($file in $files)
##if ($file -ne $null)
{
$filename = $file.name
$fullname = $file.FullName
#Need to check to be sure that the file has not been previously sent
$ORGName = $filename.Substring(0, $filename.length-4)
$ORGName = $ORGName.Substring(9, $ORGName.length-9)
$result = Test-Path $BkUp$ORGName\$filename
if (!(Test-Path $BkUp$ORGName\$filename))
{
$count = $file.count
$e = $filename.contains($CompanyName)
if ($CompanyName -eq $ORGName)
##if ($e -eq $true)
{
If ($Email.contains(";"))
{
$Email=$Email -replace(';',""", """)
}
#ForEach ($y in $Email) {
#if($results -ne '') { $results += "','" }
#$tmpy = $y
#$results += $tmpy
#}
$Email=$Email -replace '([^_]*).*','"$1'
$Email=($Email)
##$Email=$Email -replace (';',"','")
Write-host ($Email)
$DateLogged = Get-Date -format u
Send-MailMessage -To ($Email) -From "CustomerCare@company.com" -subject "Daily Reports for $ORGName" -Body "Attached are Daily reports. If there are any issues or concerns please contact your Customer Service Representative immediately." -Attachment $fullname -smtpServer "$smtpserver"
#####"$i ,On: "+Get-Date+" ,e-mail was sent for: $ORGName ,To: $EMail ,Attachment: $fullname" | Out-File -append -filepath $MailResult -encoding ASCII
"$i,On: $DateLogged,e-mail was sent for: $ORGName,To: $EMail,Attachment: $fullname" | Out-File -append -filepath $MailResult -encoding ASCII
$i++
}
}
}
}
#$sw.Stop()
##$sw.Elapsed
"" | Out-File -append -filepath $MailResult -encoding ASCII
#"time taken: " + $sw.Elapsed | Out-File -append -filepath $MailResult -encoding ASCII
"Number of Companies: " + $count | Out-File -append -filepath $MailResult -encoding ASCII
#Measure-Command { Get-Process }
#$timetaken = Measure-Command { Get-Process }
#http://social.technet.microsoft.com/Forums/windowsserver/en-US/e172f039-ce88-4c9f-b19a-0dd6dc568fa0/writing-to-different-event-logs-and-sources-registered-to-a-single-event-log
$src = [System.Diagnostics.EventLog]::SourceExists("Daily_reports")
#IF THE EVENTLOG DOES NOT EXIST, WE NEED TO CREATE IT
if (!$src)
{
New-EventLog -source "Daily_Reports" -logname "Application" > $null
}
write-eventlog -logname "Application" -source "Daily_Reports" -eventID 3001 -entrytype "Information" -message "Daily Reports have been sent and process is complete." -category 1 -rawdata 10,20
}
Here are the results..
PS C:\Documents and Settings\kent> D:\WORK\ps\Reports\7-b.ps1
"recipient1@anothercompany.com", "recipient2@anothercompany .com", "recipient3@anothercompany .com", "recipient4@anothercompany .com"
Send-MailMessage : The specified string is not in the form required for an e-mail address.
At D:\WORK\ps\Reports\7-b.ps1:160 char:25
+ Send-MailMessage <<<< -To ($Email) -From "CustomerCare@company.com"-subject "Daily Reports for $ORGName" -Body
"Attached are Daily reports. If there are any issues or concerns please contact your Customer Service Representative immediately
." -Attachment $fullname -smtpServer "$smtpserver"
+ CategoryInfo : InvalidType: (:) [Send-MailMessage], FormatException
+ FullyQualifiedErrorId : FormatException,Microsoft.PowerShell .Commands. SendMailMe ssage
Send-MailMessage : A recipient must be specified.
At D:\WORK\ps\Reports\7-b.ps1:160 char:25
+ Send-MailMessage <<<< -To ($Email) -From "CustomerCare@company.com"-subject "Daily Reports for $ORGName" -Body
"Attached are Daily reports. If there are any issues or concerns please contact your Customer Service Representative immediately
." -Attachment $fullname -smtpServer "$smtpserver"
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClie nt) [Send-MailMessage], InvalidOperationExceptio
n
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft. PowerShell .Commands. SendMailMe ssage
Thanks,
Kent
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
Something still is not right with these results.
It still cannot parse out and use multiple e-mails no matter what I do.
I have reverted back to VBScript for the time being.
Thanks,
Kent
It still cannot parse out and use multiple e-mails no matter what I do.
I have reverted back to VBScript for the time being.
Thanks,
Kent
Is this code a translation from VBS?
Do you get an error, or only one receipient, or what?
Do you get an error, or only one receipient, or what?
Have you tried using my method?
ASKER
The code I placed above, is not a direct translation of the VBS method I am using today. The reasons are many and varied, but the one thing that I want to get away from is the requirement of having to code-sign the scripts when used in our production servers. This can be argued in the positive sense you don't have rampant code running that cannot be explained like a Melissa.. The close second reason is that IMHO, PowerShell is much more powerful than VBS. The multiple e-mail send - or rather send to multiple recipients is something we are doing today and does not work at all right in PowerShell. I will be the first to admit, it is probably something that I am doing the reading of the text mapping file in comparison to the working folder/file structure to e-mail our customers daily.
Here is the method that I am using on a daily basis to send something on the order of 500 messages a daily using VBS and Blat..
Thanks,
Kent
Here is the method that I am using on a daily basis to send something on the order of 500 messages a daily using VBS and Blat..
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set fso = CreateObject("Scripting.FileSystemObject")
Set WshNetwork = CreateObject("Wscript.Network")
Set objWS = CreateObject("WScript.Shell")
strMachineName = WshNetwork.ComputerName
ScriptDir = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
MappingFile = ScriptDir & "Mapping.Txt"
ReportFileFolder = ScriptDir & "ReportDownload\" ' -- Base Download for latest.zip, temp folder under here is used for processing
YYYY = Year(Date)
MM = Right(100 + Month(Date), 2)
DD = Right(100 + Day(Date), 2)
HH = Right(100 + Hour(Date), 2)
MN = Right(100 + Minute(Date), 2)
SS = Right(100 + Second(Date), 2)
DTSTR = YYYY & MM & DD & HH & MN & SS
'(8) Read the Mapping.txt
Set f1 = fso.OpenTextFile(MappingFile, ForReading, True)
Do Until f1.AtEndOfStream
line = f1.ReadLine
If Len(line) > 0 Then
'CompanyName = Mid(Split(line, ",") (0), 13, Len(Split(line, ",") (0))) ' -- Company Name
SomeCompanyName = Split(line, ",") (0) ' -- Company Name
Set objFolder = fso.GetFolder(ReportFileFolder & "Temp")
Set colFiles = objFolder.Files
For Each objFile In colFiles
FLPath = objFile.Path
FLName = objFile.Name
FITest = Mid(FLName, InStr(FLName, "_") + 1, InStr(FLName, ".zip") - InStr(FLName, "_") - 1)
If Instr(FLName,CompanyName)>0 Then
EMail = Split(line, ",") (1)
If InStr(EMail, ";") Then
EMail = Replace(EMail, ";", ",")
End If
Dest = BkupFolder & CompanyName & "\" & FLName
If Not fso.fileexists(Dest) Then
If fso.fileexists(FLPath) Then
Mailer EMail, Chr(34) & FLPath & Chr(34), CompanyName
'WScript.sleep 300
End If
End If
End If
Next
End If
Loop
f1.Close
Set f1 = Nothing
Sub Mailer(recipient, Attachment, Nm)
Dim WshShell, server, from, subject, body, strCommand, oExec
Set objWS = CreateObject("WScript.Shell")
If Attachment <> "" Then
If InStr(strMachineName, "ABC") Or InStr(strMachineName, "DEF") Or InStr(strMachineName, "GHI") Then
server = "1.2.3.4"
End If
If InStr(strMachineName, "JKL") Then
server = "5.6.7.8" '
End If
from = "CustomerCare@company.com"
subject = "Daily Reports for: " & Nm
body = "Attached are Daily reports. If there are any issues or concerns please contact your Customer Service Representative immediately."
strCommand = "%comspec% /c " & ScriptDir & "Blat.exe "
strCommand = strCommand & " -log " & Chr(34) & ScriptDir & "AppLog\" & DTSTR & "_MailResult.txt" & Chr(34) & ""
strCommand = strCommand & " -f " & Chr(34) & from & Chr(34) & ""
strCommand = strCommand & " -to " & Chr(34) & recipient & Chr(34) & ""
strCommand = strCommand & " -server " & Chr(34) & server & Chr(34) & ""
strCommand = strCommand & " -subject " & Chr(34) & subject & Chr(34) & ""
strCommand = strCommand & " -body " & Chr(34) & body & Chr(34) & ""
strCommand = strCommand & " -attach " & Attachment & ""
strCommand = strCommand & " -q"
intReturn = objWS.Run(strCommand, 0, True)
While Not intReturn = 0
WScript.Sleep 10
Wend
Set objWS = Nothing
End If
End Sub
Thanks,
Kent
And what is the effect if you use the code?
Do you get an error, or only one receipient, or what?
ASKER
Do you get an error, or only one receipient, or what?
See the following error:
"recipient@company.com", "recpient@gmail.com"
Send-MailMessage : The specified string is not in the form required for an e-mail address.
At D:\WORK\ps\Reports\7.ps1:122 char:25
+ Send-MailMessage <<<< -To ($Email) -From "CustomerCare@company.com"-subject "Daily Reports for $ORGName" -Body
"Attached are Daily Reports. If there are any issues or concerns please contact your Customer Service Representative immediately
." -Attachment $fullname -smtpServer "$smtpserver"
+ CategoryInfo : InvalidType: (:) [Send-MailMessage], FormatException
+ FullyQualifiedErrorId : FormatException,Microsoft.PowerShell .Commands. SendMailMe ssage
Send-MailMessage : A recipient must be specified.
At D:\WORK\ps\Reports\7.ps1:122 char:25
+ Send-MailMessage <<<< -To ($Email) -From "CustomerCare@company.com"-subject "Daily Reports for $ORGName" -Body
"Attached are Daily Reports. If there are any issues or concerns please contact your Customer Service Representative immediately
." -Attachment $fullname -smtpServer "$smtpserver"
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClie nt) [Send-MailMessage], InvalidOperationExceptio
n
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft. PowerShell .Commands. SendMailMe ssage
code is..
If ($Email.contains(";"))
{
$Email=$Email -replace(';',""", """)
}
$Email=$Email -replace '([^_]*).*','"$1'
$Email=($Email)
Write-host ($Email)
$DateLogged = Get-Date -format u
Send-MailMessage -To ($Email) -From "CustomerCare@company.com" -subject "Daily Reports for $ORGName" -Body "Attached are Daily reports. If there are any issues or concerns please contact your Customer Service Representative immediately." -Attachment $fullname -smtpServer "$smtpserver"
Thanks,
Kent
ASKER
This is partially correct..
You posted:
$msg.To.Add(”recipient1@yo urdomain.c om, recipient2@yourdomain.com, ”)
It actually needs to be:
$msg.To.Add(”recipient1@yo urdomain.c om, recipient2@yourdomain.com" )
You posted:
$msg.To.Add(”recipient1@yo
It actually needs to be:
$msg.To.Add(”recipient1@yo
Line 45 & 46:
Open in new window
Lines 66-79:Open in new window
and all you need is provide $EMail to the -To parameter as already done by you (you can remove the surrounding parens - they have no use, but do not harm).