Send a file to an email address using a bat file without exposing the email info?
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.
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.
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 = "[email protected]"
$EmailFrom = "[email protected]"
$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 = "[email protected]"
$EmailFrom = "[email protected]"
$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 = "[email protected]" >> "%PSScript%"
ECHO $EmailFrom = "[email protected]" >> "%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 = "[email protected]" >> "%PSScript%"
ECHO $EmailFrom = "[email protected]" >> "%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
- MailMessage Constructors
- Attachment Constructors
- SmtpClient Constructors
- SmtpClient.EnableSsl Property
- NetworkCredential Constructors
-
Variable Substitutions (FOR /?)
In addition, substitution of FOR variable references has been enhanced. You can now use the following optional syntax:
%~I - expands %I removing any surrounding quotes (") %~nI - expands %I to a file name only %~fI - expands %I to a fully qualified path name
Related videos on Youtube
mina nageh
Updated on September 18, 2022Comments
-
mina nageh over 1 year
I want to send a file to my Gmail account via a bat file and encrypt my email info in that bat file so that if someone opens the bat file they cannot get the email information from it.
Logic such as:
check if the internet is working properly
- if ok send the file and then remove the bat file
check if the internet is working properly
if no Schedule it to do it later or add it to the start up
when done remove it from the Schedule or the start up !
-
K7AAY over 5 yearsTo 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?
-
mina nageh over 5 years"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?!
-
fixer1234 over 5 years@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.
-
Vomit IT - Chunky Mess Style over 5 years@fixer1234 .... So much for "simple" answer now, right!!
-
fixer1234 over 5 years@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!
-
mina nageh over 5 years@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 over 5 yearsok i am not In a hurry......take your time 😁 thanks,
-
mina nageh over 5 yearsYes what is it!!
-
Vomit IT - Chunky Mess Style over 5 yearsMina - 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.
-
mina nageh over 5 yearsi did here is it superuser.com/questions/1369904/…
-
Paul Jones almost 5 yearsI'm using the Batch Script (static and self-deleting) from this answer, and I'm able to send an attachment as a CSV and also have the same CSV file be read raw as the body of the email so the user can see the content on their phone with out opening the CSV file but has the option to open the attachment in Excel. The only thing I can't figure out how to do is ADD additional recipients. I've tried using a recipients string
[string[]]$recipients =
it seems to error out with this script. I've tried just adding to the existing line. `ECHO $EmailTo = "[email protected]", "emailaddress2@domai -
Thalys almost 5 yearserf. post was too long for a comment i.stack.imgur.com/Fx4Oh.png original post with some edits for reference
-
Vomit IT - Chunky Mess Style almost 5 years@PaulJones ... I'll need to check and test to confirm but I think it is as simple as one of these two examples....
1.
....$EmailTo = "[email protected],[email protected],[email protected]"
or perhaps with a semicolon separator as2.
....$EmailTo = "[email protected];[email protected];[email protected]"
... Try one of those two and let me know. If that doesn't work, I'll have to check later on a machine I have this logic running.