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
How to pass credentials to the Send-MailMessage command for sending emails
Send-MailMessage: Sending Emails from PowerShell
How to Send an Email Using Windows PowerShell
No comments:
Post a Comment