After finally releasing FoxyPreviewer3, I started receiving several requests for sending e-mails. FP3 currently supports the use of CDOSYS - the good and old way Windows used to allow us to send e-mails. The usage was really simple, but it's not compatible with TLS - evolved from the good and old SSL protocol, providing more security to the process.
Unfortunately, there is no simple way for Foxers to send messages using TLS, unless if we use some bridges to access other platforms. So, this was the right time to make tests, inspired by Doug Hennig's session on the last VFF - Virtual Fox Fest - the new online VFP conference, when he presented the amazing session Windows PowerShell: Batch Files on Steroids. The organizers of VFF were very kind offering a recorded version of all sessions for free for the community in YouTube. At the end of this post you'll find the link to his presentation on YouTube. By the way, the next release of VirtualFoxFest will be soon, on October 13, 19 and 25 2022.
So, first of all I just googled about sending e-mails with PowerScript, and found tons of posts all over, in all languages. And here is my first script to send e-mails. This is raw code, no error handling, very few parameter checking. Needs development, but looks promising, and very effective!
- create a script in Powershell, and test it
- since we can't send parameters directly, we need to change the script to adapt it to our needs. One easy way is to store the Script in a "TEXT / ENDTEXT", and using TEXTMERGE make the needed replacements
- Save the script using the ".PS1" file extension
- Use the WScript.Shell.Run to run the PS1 file script in invisible mode. Powershell allows us to save the outputs in a text file. This file will be used for us to store the returning values we need
- Delete the temporary PS1 and Output files
Before you go:
HOW TO RUN POWERSHELL SCRIPT FILE ON WINDOWS 10
On Windows 10, to run a script file with the PowerShell console, you have to change the execution policy.
To change the execution policy to run PowerShell scripts on Windows 10, use these steps:
- Open Start.
- Search for PowerShell, right-click the top result, and select the Run as administrator option.
- Type the following command to allow scripts to run and press Enter: Set-ExecutionPolicy RemoteSigned
- Type A and press Enter (if applicable).
Save the script below as SENDPSEMAIL.PRG
* FILE : SENDPSEMAIL.PRG
* AUTHOR: VFPIMAGING http://vfpimaging.blogspot.com 2022-09-08
* Send e-mails using PowerShell
FUNCTION SendPSEmail(tcDest, tcSubject, tcBody, tcAttachment, tcServer, tcUser, tcPwd, tcPort)
LOCAL lcBodyAsHtml, lcCredentials, lcPSScript, lcSender
m.lcSender = m.tcUser
IF "<" $ m.tcUser
m.tcUser = STREXTRACT(m.tcUser, "<", ">")
ENDIF
m.tcPort = TRANSFORM(m.tcPort)
m.tcDest = [@('] + STRTRAN(m.tcDest, [,], [';']) + [')] && Adjust for multiple recipients
IF EMPTY(m.tcAttachment)
m.tcAttachment = ""
ELSE
m.tcAttachment = [Attachment = ] + [@('] + STRTRAN(m.tcAttachment, [,], [', ']) + [')]
ENDIF
IF "<html>" $ LOWER(m.tcBody)
m.lcBodyAsHtml = "BodyAsHtml = $true"
ELSE
m.lcBodyAsHtml = ""
ENDIF
IF EMPTY(m.tcPwd)
m.lcCredentials = "$cred = Get-Credential"
ELSE
m.lcCredentials = "$pass = ConvertTo-SecureString -String $pass -AsPlainText -Force" + CHR(13) + ;
"$cred = New-Object System.Management.Automation.PSCredential $user, $pass"
ENDIF
* Here starts the Powershell script
TEXT TO m.lcPSScript NOSHOW TEXTMERGE
$to = <<tcDest>>
$user = '<<tcUser>>'
$pass = '<<tcPwd>>'
<<lcCredentials>>
$mailParam = @{
To = $to.Split(';')
From = '<<lcSender>>'
Subject = '<<tcSubject>>'
Body = '<<tcBody>>'
SmtpServer = '<<tcServer>>'
Port = <<tcPort>> #587 or 465
Credential = $cred
UseSsl = $true
<<tcAttachment>>
<<lcBodyAsHtml>>
}
try
{
# Send Email
Send-MailMessage @mailParam
}
catch
{
$_.Exception.Message
# $_.Exception.Message | out-file C:\Temp\error.log && #=Comment
Write-Output 'Message send failed.'
}
ENDTEXT
* End of script
lcReturn = RunPowerShell(m.lcPSScript)
IF EMPTY(ALLTRIM(m.lcReturn))
m.lcReturn = "Message Sent successfully"
ENDIF
RETURN m.lcReturn
*************************************************************
* Run PowerShell script hidden
* by VFPImaging - Adapted from Antonio Lopez FUNCTION PS_ExecScript(tcScript)
FUNCTION RunPowerShell(tcScript)
*************************************************************
LOCAL loWShell AS "WScript.Shell"
LOCAL lcCmd, lcEcho, lcFile, lcSetEscape, lcText, loPS
IF EMPTY(m.tcScript)
RETURN .F.
ENDIF
m.lcFile = ADDBS(SYS(2023)) + SYS(2015) + ".ps1"
m.lcEcho = FORCEEXT(m.lcFile, "log")
STRTOFILE(m.tcScript, m.lcFile)
m.lcCmd = "cmd /c powershell.exe -ExecutionPolicy RemoteSigned " + ;
"-File " + IIF(" " $ m.lcFile, '"' + m.lcFile + '"', m.lcFile) + ;
" > " + IIF(" "$ m.lcEcho, '"' + m.lcEcho + '"', m.lcEcho)
m.lcSetEscape = SET("Escape")
SET ESCAPE ON
m.loWShell = CREATEOBJECT("WScript.Shell")
m.lcCmd = "cmd /c powershell -ExecutionPolicy RemoteSigned " + ;
"-File " + IIF(" " $ m.lcFile, '"' + m.lcFile + '"', m.lcFile) + ;
" > " + IIF(" "$ m.lcEcho, '"' + m.lcEcho + '"', m.lcEcho)
m.loPS = m.loWShell.RUN(m.lcCmd, .F., .T.)
DOEVENTS
SET ESCAPE &lcSetEscape.
TRY
m.lcText = FILETOSTR(m.lcEcho)
CATCH
m.lcText = ""
ENDTRY
ERASE (m.lcFile)
TRY
ERASE (m.lcEcho)
CATCH
ENDTRY
RETURN m.lcText
ENDFUNC
Adapt the codes below according to your SMTP server and run!
CLEAR
* Here is our HTML body
TEXT TO lcHTML NOSHOW
<!DOCTYPE html>
<html><body><font size="3" face="Verdana">
<h1>CONGRATULATIONS!</h1>
<br/><br/><br/>
<p>You successfully managed to send an e-mail using PowerShell and VFP</p>
<br/><br/><br/>
<table><tbody><tr>
<td><img height="65" src="http://www.files.foxypreviewer.com/Logo1.png" width="65" /></td>
<td><table><tbody style="font-family: "Calibri">
<tr><td>CESAR<br/><a href="https://www.FoxyPreviewer.com">FoxyPreviewer</a></td></tr>
<tr><td>+55-44.98765.4321<br/>
<img height="16" src="http://www.files.foxypreviewer.com/Mail.bmp" width="16" /> <a href="mailto:vfpimaging@hotmail.com">vfpimaging@hotmail.com</a></td></tr></tbody></table>
</td></tr></tbody></table>
</body></html>
ENDTEXT
lcReturn = SendPSEmail("yourdestination@hotmail.com", ;
"PowerShell E-mail " + TRANSFORM(DATETIME()), ;
lcHTML, ; && Message body (plain text or HTML)
GETFILE(), ; && attachment (comma separated)
"smtp.office365.com", ; && SMTP Server
"VfpImaging <vfpimaging@hotmail.com>", ; && User
"yourpassword", ; && pwd
587) && SMTP port 25, 465, 587
? lcReturn
RETURN
Running the script above, if you omit the password it will ask you for the credentials:
Below is the video session from Doug Hennig
Related links:
POP, IMAP, and SMTP settings for Outlook.com
Send-MailMessage
How to pass credentials to the Send-MailMessage command for sending emails
Powershell tutorials
Send-MailMessage: Sending Emails from PowerShell
How to Send an Email Using Windows PowerShell