Mail not working

I have XWiki running in a Docker container behind a reverse proxy and I have the settings shown below for my email configuration. These settings should be correct as they are the same settings I’m using successfully for SMTP mail in a couple of other applications which are also running in Docker containers behind the same reverse proxy. All my containers use HTTPS for external communications, but use HTTP on the Docker network, which is a pretty standard configuration.

xwiki_smtp_settings

I can’t get XWiki to send any emails what-so-ever. It won’t “Share by Email” and it won’t send an email when a watched page is changed. When I try to “Share by Email”, I get a popup like this:

xwiki_smtp_popup_error

Looking at the logs, I find this:

2024-03-18 21:24:46,450 [http-nio-8080-exec-17 - http://xwiki.example.com/bin/get/test/?form_token=NiG2NssJZzDXn00MMsCllg&send=1&target=XWiki.git-n-pissed&target=XWiki.bob&target=&includeDocument=link&message=I%20wanted%20to%20share%20this%20page%20with%20you.&xpage=shareinline] ERROR c.x.x.p.m.MailSenderPlugin     - sendEmailFromTemplate: XWiki.SharePage vcontext: org.xwiki.velocity.XWikiVelocityContext@42ace748
javax.mail.MessagingException: Could not connect to SMTP host: smtp.mailgun.org, port: 587
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2212)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:722)
        at javax.mail.Service.connect(Service.java:342)
        at javax.mail.Service.connect(Service.java:222)
        at javax.mail.Service.connect(Service.java:243)
        at com.xpn.xwiki.plugin.mailsender.MailSenderPlugin.sendMails(MailSenderPlugin.java:653)
        at com.xpn.xwiki.plugin.mailsender.MailSenderPlugin.sendMail(MailSenderPlugin.java:605)
        at com.xpn.xwiki.plugin.mailsender.MailSenderPlugin.sendMail(MailSenderPlugin.java:591)
        at com.xpn.xwiki.plugin.mailsender.MailSenderPlugin.sendMailFromTemplate(MailSenderPlugin.java:767)
        at com.xpn.xwiki.plugin.mailsender.MailSenderPlugin.sendMailFromTemplate(MailSenderPlugin.java:815)
        at com.xpn.xwiki.plugin.mailsender.MailSenderPluginApi.sendMessageFromTemplate(MailSenderPluginApi.java:148)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.doInvoke(UberspectImpl.java:571)
        at org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.invoke(UberspectImpl.java:554)
        at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:221)
        at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:368)
        at org.apache.velocity.runtime.parser.node.ASTReference.value(ASTReference.java:704)
        at org.apache.velocity.runtime.parser.node.ASTExpression.value(ASTExpression.java:75)
        at org.apache.velocity.runtime.parser.node.ASTSetDirective.render(ASTSetDirective.java:242)
        at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:147)
        at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:171)
        at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:147)
        at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:171)
        at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:147)
        at org.apache.velocity.runtime.directive.Foreach.renderBlock(Foreach.java:309)
        at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:279)
        at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:304)
        at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:147)
        at org.apache.velocity.runtime.directive.Foreach.renderBlock(Foreach.java:309)
        at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:279)
        at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:304)
        at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:147)
        at org.apache.velocity.runtime.parser.node.ASTElseIfStatement.render(ASTElseIfStatement.java:108)
        at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:190)
        at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:439)
        at org.apache.velocity.Template.merge(Template.java:358)
        at org.apache.velocity.Template.merge(Template.java:262)
        at org.xwiki.velocity.internal.InternalVelocityEngine.evaluate(InternalVelocityEngine.java:225)
        at com.xpn.xwiki.internal.template.VelocityTemplateEvaluator.evaluateContent(VelocityTemplateEvaluator.java:105)
        at com.xpn.xwiki.internal.template.TemplateAsyncRenderer.evaluateContent(TemplateAsyncRenderer.java:219)
        at com.xpn.xwiki.internal.template.TemplateAsyncRenderer.renderVelocity(TemplateAsyncRenderer.java:174)
        at com.xpn.xwiki.internal.template.TemplateAsyncRenderer.render(TemplateAsyncRenderer.java:135)
        at com.xpn.xwiki.internal.template.TemplateAsyncRenderer.render(TemplateAsyncRenderer.java:54)
        at org.xwiki.rendering.async.internal.DefaultAsyncRendererExecutor.lambda$syncRender$0(DefaultAsyncRendererExecutor.java:284)
        at com.xpn.xwiki.internal.security.authorization.DefaultAuthorExecutor.call(DefaultAuthorExecutor.java:98)
        at org.xwiki.rendering.async.internal.DefaultAsyncRendererExecutor.syncRender(DefaultAsyncRendererExecutor.java:284)
        at org.xwiki.rendering.async.internal.DefaultAsyncRendererExecutor.render(DefaultAsyncRendererExecutor.java:267)
        at org.xwiki.rendering.async.internal.block.DefaultBlockAsyncRendererExecutor.render(DefaultBlockAsyncRendererExecutor.java:154)
        at com.xpn.xwiki.internal.template.InternalTemplateManager.render(InternalTemplateManager.java:904)
        at com.xpn.xwiki.internal.template.InternalTemplateManager.renderFromSkin(InternalTemplateManager.java:866)
        at com.xpn.xwiki.internal.template.InternalTemplateManager.renderFromSkin(InternalTemplateManager.java:846)
        at com.xpn.xwiki.internal.template.InternalTemplateManager.render(InternalTemplateManager.java:832)
        at com.xpn.xwiki.internal.template.DefaultTemplateManager.render(DefaultTemplateManager.java:91)
        at com.xpn.xwiki.internal.template.DefaultTemplateManager.render(DefaultTemplateManager.java:85)
        at com.xpn.xwiki.XWiki.evaluateTemplate(XWiki.java:2564)
        at com.xpn.xwiki.web.Utils.parseTemplate(Utils.java:180)
        at com.xpn.xwiki.web.XWikiAction.execute(XWikiAction.java:651)
        at com.xpn.xwiki.web.XWikiAction.execute(XWikiAction.java:339)
        at com.xpn.xwiki.web.LegacyActionServlet.service(LegacyActionServlet.java:108)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at com.xpn.xwiki.web.ActionFilter.doFilter(ActionFilter.java:122)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.xwiki.wysiwyg.filter.ConversionFilter.doFilter(ConversionFilter.java:61)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter.doFilter(SetHTTPHeaderFilter.java:63)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.xwiki.resource.servlet.RoutingFilter.doFilter(RoutingFilter.java:132)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.xwiki.container.servlet.filters.internal.SavedRequestRestorerFilter.doFilter(SavedRequestRestorerFilter.java:208)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.xwiki.container.servlet.filters.internal.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:111)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:670)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
        at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:602)
        at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:376)
        at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:214)
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2160)
        ... 102 common frames omitted

How can I fix this?

Making some progress. This guide shows port 465 being used. Switching to that port does result in “Share by Email” to start working, but there are still no emails are being sent when watched pages are modified. I suspect this is some other configuration problem, and not caused by the primary email configuration. I say this because there are no error logs indicating that an attempt to send an email was ever made due to a watched page being changed.

Side note to devs, port 465 is legacy and was never standard. Port 587 is the port that should be used for encrypted SMTP communications. Here is a nice write up on it:

Port 465: The TLS port

The Internet Assigned Numbers Authority (IANA) has reassigned a new service to this port, and it should no longer be used for SMTP communications.

Because port 465 was once recognized by IANA as valid, there may be legacy systems that are only capable of using this connection method. Typically, you will use this port only if your application demands it. A quick Google search, and you’ll find many consumer Inbox Service Providers’ (ISPs) articles that suggest port 465 as the recommended setup. However, we do not recommend it, as it is not RFC compliant.

Interestingly, port 465 was never published as an official SMTP transmission or submission channel by the IETF. Instead, the Internet Assigned Numbers Authority (IANA), which maintains much of the core internet infrastructure, registered port 465 for SMTPS. The purpose was to establish a port for SMTP to operate using Secure Sockets Layer (SSL). SSL is commonly used for encrypting communications over the internet.

The port was assigned for about one year before it was revoked in support of securing SMTP communications using Transport Layer Security (TLS). The nail in the coffin was a new protocol command “STARTTLS,” introduced in RFC 2487. This command allows SMTP servers to communicate over existing ports by advertising whether the destination server supports TLS encryption. If so, the sending server can upgrade the connection using the “STARTTLS” SMTP command.

Update 1:
I had set Global Administration: Notifications > Email Preferences > EMAIL FREQUENCY to Live, wasn’t getting emails immediately when page changes were made. I stumbled onto this and realize now that behavior is a feature. By default, there is a grace time for changes so if a user is making a lot of small changes within the grace period, all the users watching the page aren’t getting their inboxes blown up. The default grace period is 10 minutes, and it resets every time the user editing a page makes a change. This setting is described in detail here, but the short of it is that you can edit your xwiki.properties file and change notifications.emails.live.graceTime = 10 to the value you want.

Actually it shows using 587. It’s just that the screenshot has not been updated but if you read the text below, it does suggest using port 587.

Thanks!