ozcanovunc
ozcanovunc

Reputation: 713

Escape sequence issue - Batch

I want to send an e-mail using PowerShell commands in a batch file. To do this, I implemented a function called sendMail. I'm calling it like this:

setlocal enabledelayedexpansion
call:sendMail
powershell -command "!_mailCommand!"
endlocal
pause&goto:eof

And my sendMail function:

:sendMail

set "_mailCommand=&{$filenameAndPath = '!resultFile!';"
set "_mailCommand=%_mailCommand%$SMTPMessage = New-Object System.Net.Mail.MailMessage('%_mailFrom%', '%_mailTo%', '%_mailSubject%', '%_mailBody%');"
set "_mailCommand=%_mailCommand%$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath);"
set "_mailCommand=%_mailCommand%$SMTPMessage.Attachments.Add($attachment);"
set "_mailCommand=%_mailCommand%$SMTPClient = New-Object Net.Mail.SmtpClient('%_mailHost%', %_mailPort%);"
set "_mailCommand=%_mailCommand%$SMTPClient.EnableSsl = $true;"
set "_mailCommand=%_mailCommand%$SMTPClient.Credentials = New-Object System.Net.NetworkCredential('%_mailFrom%','%_mailSenderPassword%');"
set "_mailCommand=%_mailCommand%$SMTPClient.Send($SMTPMessage)}"
echo %_mailSenderPassword%

Unexpectedly I get an output like this:

12345Aa!

Exception calling "Send" with "1" argument(s): "Failure sending mail."

At line:1 char:499 ... m','12345Aa^');$SMTPClient.Send($SMTPMessage)}

CategoryInfo : NotSpecified: (:) [], MethodInvocationException

FullyQualifiedErrorId : SmtpException

As you can guess, my password is 12345Aa! and I defined it at the beginning of my code as set "_mailSenderPassword=12345Aa^^!"

So what am I missing? Thanks in advance!

Upvotes: 2

Views: 163

Answers (2)

jeb
jeb

Reputation: 82237

When you are using delayed expansion, then you should avoid percent expansion, else you get problems with carets^ and exclamation marks! and sometimes also with quotes.

As after the percent expansion the content will be parsed for special characters, but after delayed expansion it will be used unchanged.

setlocal EnableDelayedExpansion
set "_mailSenderPassword=12345Aa^!"
call :sendMail
powershell -command "!_mailCommand!"
exit /b

:sendMail
set "_mailCommand=&{$filenameAndPath = '!resultFile!';"
set "_mailCommand=!_mailCommand!$SMTPMessage = New-Object System.Net.Mail.MailMessage('!_mailFrom!', '!_mailTo!', '!_mailSubject!', '!_mailBody!');"
set "_mailCommand=!_mailCommand!$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath);"
set "_mailCommand=!_mailCommand!$SMTPMessage.Attachments.Add($attachment);"
set "_mailCommand=!_mailCommand!$SMTPClient = New-Object Net.Mail.SmtpClient('!_mailHost!', !_mailPort!);"
set "_mailCommand=!_mailCommand!$SMTPClient.EnableSsl = $true;"
set "_mailCommand=!_mailCommand!$SMTPClient.Credentials = New-Object System.Net.NetworkCredential('!_mailFrom!','!_mailSenderPassword!');"
set "_mailCommand=!_mailCommand!$SMTPClient.Send($SMTPMessage)}"
echo !_mailSenderPassword!
exit /b

Upvotes: 1

ForNeVeR
ForNeVeR

Reputation: 6955

The following simplified example worked for me (it successfully echoed 12345Aa^!):

set "_mailSenderPassword=12345Aa^!"

setlocal enabledelayedexpansion
call:sendMail
powershell -command "!_mailCommand!"
endlocal
pause&goto:eof

:sendMail
set "_mailCommand=echo '%_mailSenderPassword%';"
echo %_mailSenderPassword%
echo %_mailCommand%

Note that I had to set _mailSenderPassword before I call setlocal enabledelayedexpansion.

Also there's one funny quirk: you still can get the same result while under enabledelayedexpansion, but you have to use 3 (three) caret characters. E.g. the following will work:

setlocal enabledelayedexpansion
set "_mailSenderPassword=12345Aa^^^!"

call:sendMail
powershell -command "!_mailCommand!"
endlocal
pause&goto:eof

:sendMail
set "_mailCommand=echo '%_mailSenderPassword%';"
echo %_mailSenderPassword%
echo %_mailCommand%

Upvotes: 0

Related Questions