#!/usr/bin/env rexx /** Utility to send messages via SSL/TLS using either Java EE 8 or lower, or Jakarta EE 9 or higher. (c) 2021 Rony G. Flatscher, Apache License 2.0 */ /* load/import and save the classes we use in this package (Rexx program) each entry in an environment directory can be fetched via its environment symbol (just prepend a dot to the name) */ namespace=determineNameSpace() -- test which mail package we have, javax. or jakarta. if namespace~isNil then raise syntax 40.900 additional("Cannot find the mail package for Java EE 8 or lower, nor for Jakarta EE 9 or higher") pkgLocal=.context~package~local -- get this package local object pkgLocal~namespace=namespace -- save namespace -- Java-Klassen laden und speichern pkgLocal~Session =bsf.loadClass(namespace".mail.Session") pkgLocal~Message.RecipientType=bsf.loadClass(namespace".mail.Message$RecipientType") pkgLocal~Transport =bsf.loadClass(namespace".mail.Transport") pkgLocal~Authenticator =bsf.loadClass(namespace".mail.Authenticator") -- imported classes can be used as if they were ooRexx classes, they understand the "new" message pkgLocal~PasswordAuthentication=bsf.importClass(namespace".mail.PasswordAuthentication") -- the following classes are from the JRE (Java runtime environment) pkgLocal~MimeMessage =bsf.importClass(namespace".mail.internet.MimeMessage") pkgLocal~InternetAddress =bsf.importClass(namespace".mail.internet.InternetAddress") -- from EE -- create a proxy class which will reroute Java invocations of "getPasswordAuthentication" to the RexxProxy pkgLocal~proxiedAuthenticator=bsf.createProxyClass(.Authenticator, , "getPasswordAuthentication") ::requires BSF.CLS -- get Java bridge /* ======================================================================== */ ::routine determineNameSpace public signal on syntax name no_javax clz=bsf.loadClass("javax.mail.Session") return "javax" -- we were able to load that class! no_javax: signal on syntax name no_jakarta clz=bsf.loadClass("jakarta.mail.Session") return "jakarta" -- we were able to load that class! no_jakarta: return .nil -- indicate whe have no access to the mail package /* ======================================================================== */ ::routine sendMailSSL public use strict arg fromAddress, password, toAddress, subject, text props=.bsf~new("java.util.Properties") props~put("mail.smtp.host", "smtp.gmail.com") props~put("mail.smtp.socketFactory.port", "465") props~put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory") props~put("mail.smtp.auth", "true") props~put("mail.smtp.port", "465") -- create the RexxProxy that handles the "getPasswordAuthentication" message jRxAuth=BsfCreateRexxProxy(.RexxAuthenticator~new(fromAddress, password)) jAuth=.proxiedAuthenticator~new(jRxAuth) -- create Java object and supply RexxProxy session=.Session~getDefaultInstance(props, jAuth) msg=.MimeMessage~new(session) msg~addRecipient(.Message.RecipientType~to, .InternetAddress~new(toAddress)) msg~setSubject(subject) -- alternative: msg~subject=subject msg~setText(text) -- alternative: msg~text =text .Transport~bsf.invoke("send",msg) /* ======================================================================== */ -- {jakarta|javax}.mail.Authenticator maintains "from" address and "password" ::class RexxAuthenticator -- implements "getPasswordAuthentication" from abstract "javax.mail.Authenticator" class ::method init -- ooRexx constructor expose passwordAuthentication use strict arg from, password -- create the password authentication object passwordAuthentication=.bsf~new("javax.mail.PasswordAuthentication", from, password) ::method getPasswordAuthentication -- returns the password authentication object expose passwordAuthentication return passwordAuthentication /* ======================================================================== */ ::routine sendMailSSL.getPackageLocal public -- for debugging purposes, return this package local object return .context~package~local