Reputation: 157
When I run my Powershell script from the command line, it fails, however if I copy line by line and run it in Powershell Console it runs fine.
powershell -ExecutionPolicy Bypass -File "F:\email.ps1" -FFFeatureOff
yields:
At F:\email.ps1:16 char:126 + ... ential("username", "password"); + ~~~ The string is missing the terminator: ".
At F:\email.ps1:9 char:1 + { + ~ Missing closing '}' in statement block or type definition.
Its just really odd if I open powershell window and paste the script in, it works, but running the ps1 file I get the error, even in the editor I get the same issues
Full Script:
$EmailTo = "xxxxx"
$EmailFrom = "xxxxxx"
$Subject = "LicenceKey & Instructions"
$Body = "This is an automated email"
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$files=Get-ChildItem "C:\Users\alber\Desktop\LicenceKey\newuser"
Foreach($file in $files)
{
Write-Host “Attaching File :- ” $file
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList "C:\Users\alber\Desktop\LicenceKey\newuser\$file"
$SMTPMessage.Attachments.Add($attachment)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($SMTPMessage)
Upvotes: 0
Views: 822
Reputation: 437052
The fact that James C.'s answer was accepted by the OP suggests that it was motivated by the OP's gratitude for the generally helpful, but non-specific - and ultimately potentially confusing - pointers contained in it.
Unfortunately, it falls short as an answer of general interest to future readers and is likely to cause confusion; as of this writing:
The issue here is that the $file is outside the param for the message, moving the quote will fix that:
Write-Host “Attaching File :- $file”
However, there is no problem with Write-Host “Attaching File :- ” $file
, because Write-Host simply concatenates multiple arguments with spaces - no strict need for a single argument.
(As stated, PowerShell recognizes "smart quotes" (non-ASCII quotes), assuming they're properly encoded - see below).
It does not explain the OP's symptoms as posted.
It almost makes it sound as if it weren't possible to embed a literal "
- or $
, for that matter - in a double-quoted string due to a limitation in PowerShell, which, of course, isn't true; escaping with backticks is all that is needed: "Pa`$`$`"w0rd"
.
Instead, PetSerAl's helpful comments on the question presumably point to the actual answer:
There may be a character encoding issue, given that "smart quotes" (non-ASCII quote characters) are used, which would surface in an incorrectly encoded script file.
PetSerAl's answer here suggests that UTF-8-encoded script content must be saved to a file with a BOM in order for PowerShell to recognize the encoding.
Update: PetSerAl surmises that the "actual troublemaker is an EN DASH here:
–ArgumentList
, which, when improperly decoded: [Text.Encoding]::GetEncoding(1250).GetString([Text.Encoding]::UTF8.GetBytes('–'))
, yields –
, an unpaired double quote."
Upvotes: 2
Reputation: 13207
At F:\email.ps1:9 char:1 + { + ~ Missing closing '}' in statement block or type definition.
The issue here is that the $file
is outside the param for the message, moving the quote will fix that:
Write-Host “Attaching File :- $file”
(Smart Quotes “ ”
are accepted by PowerShell but aren't but most other languages, I personally avoid them to be sure.)
At F:\email.ps1:16 char:126 + ... ential("username", "password"); + ~~~ The string is missing the terminator: ".
The double quotes you're using here: ("username", "password")
can cause Powershell to incorrectly interpret where the password ends if it contains certain special characters.
For example the password Pa$$"w0rd
will cause issues when used in your script because of the double quote within.
It will be interpreted as "Pa$$"
with the remaining w0rd"
remaining ( which only contains a single quoteation mark and is not correctly terminated as a string)
To avoid this you can use single quotes instead, they are not evaluated and are interpreted as literals:
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential('username', 'password')
See about about_quoting_rules for more info on single and double quotes.
Upvotes: 1