Versions: Lucee 7.1.0.204, Mail Extension 1.1.0.7 (also 1.1.0.6), Java 21.0.11 (Docker lucee/lucee:7.0-nginx) and 21.0.6 (Tomcat 11, Windows)
Description Since 7.1, cfmail comes from the Mail Extension (jakarta.mail 2.0.2). Lucee still ships the bundle org.lucee.commons-email-all-1.6.0 (javax.mail). Both contain com.sun.mail.imap.IMAPProvider under the same name.
jakarta.mail.Session.loadProviders() uses ServiceLoader with the thread context classloader, which is lucee.runtime.osgi.EnvClassLoader. That loader resolves the class name to whichever variant was requested first. So once any code has created a javax.mail.Session, every cfmail in the JVM fails until restart. It also works the other way round: after cfmail, javax.mail.Session.getInstance() fails with javax.mail.Provider: … not a subtype.
Steps to reproduce (fresh JVM):
<cfset createObject("java", "javax.mail.Session").getInstance(createObject("java", "java.util.Properties").init()) />
<cfmail to="a@b.c" from="a@b.c" subject="x" server="127.0.0.1" port="1" spoolenable="false">x</cfmail>
Expected: connection error. Actual: java.util.ServiceConfigurationError: jakarta.mail.Provider: com.sun.mail.imap.IMAPProvider not a subtype
Stack (excerpt)
at java.util.ServiceLoader.fail
at jakarta.mail.Session.loadProviders(Session.java:964)
at jakarta.mail.Session.getInstance(Session.java:281)
at org.lucee.extension.mail.smtp.SMTPConnectionPool.createSession(SMTPConnectionPool.java:148)
at org.lucee.extension.mail.smtp.SMTPClient.createMimeMessage(SMTPClient.java:492)
at org.lucee.extension.mail.tag.Mail.doEndTag(Mail.java:651)
Suggested fix In SMTPConnectionPool.createSession (and wherever the extension creates a Session or Transport), set the thread context classloader to the extension’s own classloader (e.g. jakarta.mail.Session.class.getClassLoader()) and restore it in finally.
Workaround we applied on the CFML side: create javax.mail.Session and call getStore() with the context classloader set to javax.mail.Session’s classloader. After that, both sides work side by side.
Impact: On our production server no mail was sent for 15 days. A scheduled IMAP check using javax.mail always ran before the first cfmail after a restart.