If you need to send an email—even with an attachment—by having a PowerShell script with the logic that builds and sends the email, you can execute it via a batch script passing sensitive values in as arguments rather than hard-coding sensitive values into the script logic.
The PowerShell script logic can accept arguments such as the Gmail local mailbox username, the password to authenticate to send email, and anything else you don't want hard-coded in the script.
PowerShell Args
Within a script or function you can refer to unnamed arguments using
the $args array, for example passing all the arguments through to a
cmdlet. You can also refer to specific arguments by their position:
"First argument is " + $Args[0]
"
"Second argument is " + $Args[1]
"
You can also put logic in the batch script so it too has arguments you can pass sensitive values to it at execution time, and use argument placeholders rather than hard-coding sensitive values.
Batch Args
You can get the value of any argument using a %
followed by it's
numerical position on the command line. The first item passed is
always %1
the second item is always %2
and so on
%* in a batch script refers to all the arguments (e.g. %1 %2 %3 %4 %5
...%255
) only arguments %1
to %9
can be referenced by number.
This way if the scripts are opened, the sensitive values you need to protect will not be exposed or hard-coded into the script logic for anyone to see who may have read access to the script.
Important Note: There's a section at the bottom of each PowerShell script example name Batch Execute Script that has the logic to use from the batch script to execute or whatever so you will use pass the username, password, and/or attachment full path as the appropriate arguments to the batch script i.e. sendemail.bat "<GmailAccountName>" "<GmailPassword>" "<FullPathAttachment>"
PowerShell Script (no attachment)
$Username = $args[0]
$EmailPassword = $args[1]
$Username = $Username
$EmailTo = "EmailAddress@domain.com"
$EmailFrom = "noreply@Whatever.notify"
$Subject = "Email Subject"
$Body = "Email Body"
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $EmailPassword);
$SMTPClient.Send($SMTPMessage)
Batch Execute Script
SET GmailAccount=%~1
SET GmailPassword=%~2
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& 'C:\Scripts\SendEmail.ps1' '%GmailAccount%' '%GmailPassword%'"
PowerShell Script (with attachment)
$Username = $args[0]
$EmailPassword = $args[1]
$Attachment = $args[2]
$Username = $Username
$EmailTo = "EmailAddress@domain.com"
$EmailFrom = "noreply@Whatever.notify"
$Subject = "Email Subject"
$Body = "Email Body"
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body)
$Attachment = New-Object System.Net.Mail.Attachment($Attachment)
$SMTPMessage.Attachments.Add($Attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $EmailPassword);
$SMTPClient.Send($SMTPMessage)
Batch Execute Script
SET GmailAccount=%~1
SET GmailPassword=%~2
SET Attachment=%~3
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& 'C:\Scripts\SendEmail.ps1' '%GmailAccount%' '%GmailPassword%' '%Attachment%'"
Batch Script (dynamic)
Here's an all-in-one dynamic batch script that you just pass the Gmail account username, the Gmail account password, and the full path to the attachment.
@ECHO OFF
SET GmailAccount=%~1
SET GmailPassword=%~2
SET Attachment=%~3
CALL :PowerShell
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%' '%GmailAccount%' '%GmailPassword%' '%Attachment%'"
EXIT
:PowerShell
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
SET PSScript=%temp%\~tmpSendeMail.ps1
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"
ECHO $Username = $args[0]>> "%PSScript%"
ECHO $EmailPassword = $args[1]>> "%PSScript%"
ECHO $Attachment = $args[2]>> "%PSScript%"
ECHO >> "%PSScript%"
ECHO $Username = $Username >> "%PSScript%"
ECHO $EmailTo = "EmailAddress@domain.com" >> "%PSScript%"
ECHO $EmailFrom = "noreply@Whatever.notify" >> "%PSScript%"
ECHO $Subject = "Email Subject" >> "%PSScript%"
ECHO $Body = "Email Body" >> "%PSScript%"
ECHO $SMTPServer = "smtp.gmail.com" >> "%PSScript%"
ECHO $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body) >> "%PSScript%"
ECHO $Attachment = New-Object System.Net.Mail.Attachment($Attachment) >> "%PSScript%"
ECHO $SMTPMessage.Attachments.Add($Attachment) >> "%PSScript%"
ECHO $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) >> "%PSScript%"
ECHO $SMTPClient.EnableSsl = $true >> "%PSScript%"
ECHO $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $EmailPassword) >> "%PSScript%"
ECHO $SMTPClient.Send($SMTPMessage) >> "%PSScript%"
GOTO :EOF
You execute the batch script like so. . .
sendemail.bat "<GmailAccountName>" "<GmailPassword>" "<FullPathAttachment>"
Batch Script (static and self-deleting)
This script will have the hard-coded values set in the variables of GmailAccount=
, GmailPassword=
, and Attachment=
but once executed, it will delete [itself] the script entirely via "%~FN0"
where the 0
is the script itself. This means that you will want to be sure you copy this script and then run the copy only from the machine(s) you'll execute where you don't want this information exposed.
@ECHO OFF
SET GmailAccount=<GmailAccountName>
SET GmailPassword=<GmailPassword>
SET Attachment=<FullAttachmentPath>
CALL :PowerShell
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%' '%GmailAccount%' '%GmailPassword%' '%Attachment%'"
IF EXIST "%~FN0" DEL /Q /F "%~FN0"
EXIT
:PowerShell
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
SET PSScript=%temp%\~tmpSendeMail.ps1
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"
ECHO $Username = $args[0]>> "%PSScript%"
ECHO $EmailPassword = $args[1]>> "%PSScript%"
ECHO $Attachment = $args[2]>> "%PSScript%"
ECHO >> "%PSScript%"
ECHO $Username = $Username >> "%PSScript%"
ECHO $EmailTo = "EmailAddress@domain.com" >> "%PSScript%"
ECHO $EmailFrom = "noreply@Whatever.notify" >> "%PSScript%"
ECHO $Subject = "Email Subject" >> "%PSScript%"
ECHO $Body = "Email Body" >> "%PSScript%"
ECHO $SMTPServer = "smtp.gmail.com" >> "%PSScript%"
ECHO $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body) >> "%PSScript%"
ECHO $Attachment = New-Object System.Net.Mail.Attachment($Attachment) >> "%PSScript%"
ECHO $SMTPMessage.Attachments.Add($Attachment) >> "%PSScript%"
ECHO $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) >> "%PSScript%"
ECHO $SMTPClient.EnableSsl = $true >> "%PSScript%"
ECHO $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $EmailPassword) >> "%PSScript%"
ECHO $SMTPClient.Send($SMTPMessage) >> "%PSScript%"
GOTO :EOF
Further Resources
To send an email through Gmail without using a web browser, you need an SMTP based email client like Outlook or Mozilla Thunderbird. Do you have one installed? If so, which? – K7AAY – 2018-10-12T16:47:31.033
"Do you have one installed?". No i don't ... . is there any alternative email service that is ready to go (portable) like it doesn't need any additional soft installed?! – mina nageh – 2018-10-13T14:19:09.223
2@PimpJuiceIT, close voters' perception of "too broad" is influenced by the presence of a good, simple answer that demonstrates that it isn't so broad. Go for it. – fixer1234 – 2018-10-14T20:49:28.040
@fixer1234 .... So much for "simple" answer now, right!! – Pimp Juice IT – 2018-10-18T20:26:51.880
1@PimpJuiceIT, yeah, nobody in his right mind would answer a question that requires developing an app to solve the problem, so it's good that you demonstrated a trivial solution. I had to vote to reopen to ensure that this doesn't get deleted. Maybe it will even attract another answer. BTW your answer is a bit brief. You might want to beef it up by adding the meat from the bare links at the end. ONLY KIDDING! – fixer1234 – 2018-10-18T23:13:46.173
@pimp juice IT Hi... Sorry for asking more than it's Required..... Is there an quick way/method/article to encrypt the password and the username instead of using it One command line like creat another bat file that Decode the password and the username then use them to run the Batch Script (dynamic) ..... Again sorry for asking too much.... I may start another thread if you prefer. – mina nageh – 2018-10-19T12:34:01.887
ok i am not In a hurry......take your time
thanks, – mina nageh – 2018-10-19T13:45:32.613
Yes what is it!! – mina nageh – 2018-10-20T13:33:49.233
Mina - Just submit another question and ask for that based off the below logic as what you are using, so how can you do this with this logic here or something similar, etc. – Pimp Juice IT – 2018-10-24T02:08:43.160
i did here is it https://superuser.com/questions/1369904/encrypting-password-and-email-to-send-an-email-in-a-bat-file
– mina nageh – 2018-10-25T10:53:52.897