0

I wrote my own function to send out e-mails to end-users in HTML-format. This works flawless to one user or multiple users if I use the following format for the field To: within my script:

$MailTo = "<User1@domain.com>", "<User2@domain.com>"

However, when I try to start a scheduled task in Windows with the same arguments, PowerShell complains about Cannot find an object with identity User1@domain.com or the mail is only sent to one user and not both.

The way I launch the script as scheduled task or from the prompt, which does not work:

powershell -File "S:\Script\Send_Mail.ps1" -MailTo "<User1@domain.com>", "<User2@domain.com>"

Even if I try one of these arguments, only one mail gets sent:

-MailTo "<User1@domain.com>, <User2@domain.com>"
-MailTo "User1@domain.com, User2@domain.com"

I found this but it was not really clear what I did wrong. Thank you for your help guys.

The script:

[CmdletBinding(SupportsShouldProcess=$True)]
Param (
      [parameter(Mandatory=$true,Position=0)]
      [String[]] $MailTo,
      [parameter(Mandatory=$true,Position=1)]
      [String[]] $Subject,
      [parameter(Mandatory=$true,Position=2)]
      [String[]] $Message1
    )

Function Send-Mail {

[CmdletBinding(SupportsShouldProcess=$True)]
Param (
      [parameter(Mandatory=$true,Position=0)]
      [String[]] $To,
      [parameter(Mandatory=$true,Position=1)]
      [String[]] $Subject,
      [parameter(Mandatory=$true,Position=2)]
      [String[]] $Message1,
      [parameter(Mandatory=$false,Position=3)]
      [String[]] $Message2
    )

# Set SMTP server name
$PSEmailServer = "SMTP.Server"

# Check where we've been launched from
if($PSISE) {
  $LaunchedFrom = "Windows PowerShell ISE"
}
else {
     $LaunchedFrom = "Scheduled task or console (not ISE)"
}

$HTML = @"
<!DOCTYPE html>
<html><head><style type="text/css">
body {font-family:verdana;background-color:white;}
h1 {background-color:black;color:white;margin-bottom:5px;}
h2 {background-color:lightGrey;margin-top:5px;}
h3 {margin-left:10px;font-size: 14px;}
p {font-size: 14px;margin-left:10px;}
p.italic {font-style: italic;font-size: 12px;}
table, td, th {font-size: 14px;border-collapse: collapse; border: 1px lightGrey; padding: 3px; text-align: left; padding-right:10px;}
li {font-size: 14px;}
base {target="_blank"}
</style></head><body>
<h1>&nbsp;$(if(!$ScriptName){"Test"}else{$ScriptName})</h1>&nbsp;
<h2>&nbsp;The following has been reported:</h2>
<p>$Message1</p>
<p>$Message2</p>
<h2>&nbsp;About</h2>
<p><table>
$(if($ScriptStart){$("<tr><th>Start time</th><td>{0:00}/{1:00}/{2:00} {3:00}:{4:00} ({5})</td></tr>" -f `
$ScriptStart.Day,$ScriptStart.Month,$ScriptStart.Year,$ScriptStart.Hour,$ScriptStart.Minute,$ScriptStart.DayOfWeek)})
$(if($ScriptRunTime){"<tr><th>Total runtime</th><td>$ScriptRunTime</td></tr>"})
$(if($LogFolder){"<tr><th>Log folder</th><td>$("<a href=`""$LogFolder"`">$LogFolder</a>")</td></tr>"})
$(if($PSCommandPath){"<tr><th>Script location</th><td>$PSCommandPath</td></tr>"})
<tr><th>Launched from</th><td>$LaunchedFrom</td></tr>
</tr><tr><th>Server</th><td>$env:computername</td></tr>
</tr></tr><tr><th>Whoami</th><td>$("$env:USERDNSDOMAIN\$env:USERNAME")</td>
</tr><tr><th>Help</th><td><a href="http://www.google.com" target="_blank">Google</a></td></tr>
</table></p><p class=italic>"$(Get-Content "S:\Input\Extra\Quotes.txt" | Get-Random -ErrorAction SilentlyContinue)"</p1>
</body></html>
"@

# Mail content
Write-Verbose "Function Send-Mail: Sending mail"        
Send-MailMessage -To $To -From "$(if(!$ScriptName){"Test"}else{$ScriptName}) PowerShell@$env:computername" `
-Subject "$Subject" `
-BodyAsHtml "$HTML"
}


Send-Mail $MailTo $Subject $Message1

The solution

Correct the parameters to only accept an array where it's needed (multiple $MailTo):

Param (
      [parameter(Mandatory=$true,Position=0)]
      [String[]] $MailTo,
      [parameter(Mandatory=$true,Position=1)]
      [String] $Subject,
      [parameter(Mandatory=$true,Position=2)]
      [String] $Message1
    )

To run this from a scheduled task in Windows you can use these formats:

powershell "S:\Script\Send_Mail.ps1" -ImportFile "S:\Script\Servers.csv" -MailTo "User1@domain.com", "User2@domain.com"
powershell -ExecutionPolicy Bypass "S:\Script\Send_Mail.ps1" -ImportFile "S:\Script\Servers.csv" -MailTo "User1@domain.com", "User2@domain.com"

These formats are not accepted and will result in syntax errors or not all users receive their e-mail:

powershell -File "S:\Script\Send_Mail.ps1" -ImportFile "S:\Script\Servers.csv" -MailTo "User1@domain.com, User2@domain.com"
powershell -File "S:\Script\Send_Mail.ps1" -ImportFile "S:\Script\Servers.csv" -MailTo '"User1@domain.com", "User2@domain.com"'
powershell "S:\Script\Send_Mail.ps1" -ExecutionPolicy Bypass -ImportFile "S:\Script\Servers.csv" -MailTo "User1@domain.com, User2@domain.com"

All the lines above can be pasted for testing in the PowerShell ISE, so you can see the errors instead of relying on the scheduled task to tell you. I hope it helps you guys as it was freaking me out :P

DarkLite1
  • 13,637
  • 40
  • 117
  • 214
  • Problem here is parsing the command line. Have you tried sending parameter like this: -Mailto "user1@domain.com,user2@domain.com" – andyb Jul 23 '14 at 07:34
  • Yes I tried that one to, same problem. Only one of both users receives the mail. – DarkLite1 Jul 23 '14 at 07:36
  • #[Solved Problem for C# powershell eMail with multiple recipients!!!](http://stackoverflow.com/a/43471655/6198368) – Ricardo Fercher Apr 18 '17 at 12:09

2 Answers2

1

try like this:

powershell -File "S:\Script\Send_Mail.ps1" -MailTo "'User1@domain.com', 'User2@domain.com'"
CB.
  • 58,865
  • 9
  • 159
  • 159
  • Thanks for your help CB. I've updated the question with the whole script. Now it's complaining that the `Specified string is not in the form required for an e-mail address.` – DarkLite1 Jul 23 '14 at 08:59
  • try removing the `<` and `>` – CB. Jul 23 '14 at 09:05
  • Did that and then it's only arriving with one recipient. I'm like testing the whole morning on this one :P Very strange.. Maybe it's the way my parameters are declared in the script? – DarkLite1 Jul 23 '14 at 09:08
  • @DarkLite1 Have you used exactly as in my answer? With double quote that include email address each one enclosed in single quote? – CB. Jul 23 '14 at 09:27
  • Yes, I even copy pasted it multiple times to be sure. I did had to add extra arguments for the subject and body. What I did was your line + `-Subject "Test" -Message1 "Test"`. Error I get is `Send-MailMessage : Syntax error in parameters or arguments. The server response` – DarkLite1 Jul 23 '14 at 09:33
  • After a fresh start with a clear head I noticed I missed something in my `Parameter` section `[String[]]$MailTo` the double brackets... And of course changing `$Subject` and `$Message1` to not accept an array. Problem solved! Thank you again :) – DarkLite1 Jul 24 '14 at 07:15
  • Thx CB. Still something strange is happening. When I dot source it from the PowerShell prompt like this `.\Auto_Clean.ps1 -MailTo "User1@domain.com", "User2@domain.com" -ImportFile "S:\Script\Auto_Clean_Test.csv"` it works fine. But when I put the same line in a scheduled task and adding `powershell File "s:\Script\Auto_Clean.ps1"` in front of it, it's still complaining about `A positional parameter cannot be found..` I'm gonna search the web and if I can't find it ask a new question perhaps. – DarkLite1 Jul 24 '14 at 08:23
  • Found it! Updating the question with all the correct info so it might help others :) – DarkLite1 Jul 24 '14 at 08:40
0

You can define "To" variable like this:

$emailTo = @('Name <name1@domain.com>', 'Name2 <name2@domain.com>')

And then you can use it in function Send-MailMessage

Example:

$servername = hostname
$smtpserver = 'localhost'
$emailTo = @('username1 <user1@dom.com>', 'username2<user2@dom.com>')
$emailFrom = 'SomeServer <user3@dom.com>'
Send-MailMessage -To $emailTo -Subject 'Low available memory' -Body 'Warning' -SmtpServer $smtpserver -From $emailFrom
StephenTG
  • 2,579
  • 6
  • 26
  • 36
Alexander Shapkin
  • 1,126
  • 1
  • 13
  • 11