ome/omero-server

Sending mail to encrypted SMTP seems to be broken

Closed this issue · 7 comments

see:

Investigations into the above forum threads seems to point to some combination of current Java version, mail providers (minimally gmail), and the current server version (5.6.1) not being able to send mail over SSL/TCP. (Examples in Dundee work when sending to unencrypted servers)

Configuration used for testing:

grep -A30 omeroserver: docker-compose.yml
  omeroserver:
    image: "openmicroscopy/omero-server:5.6"
    environment:
      CONFIG_omero_db_host: database
      CONFIG_omero_db_user: omero
      CONFIG_omero_db_pass: omero
      CONFIG_omero_db_name: omero
      CONFIG_omero_mail_bean: "localMailSender"
      CONFIG_omero_mail_auth: "true"
      CONFIG_omero_mail_config: "true"
      CONFIG_omero_mail_from: "${EMAIL}"
      CONFIG_omero_mail_host: smtp.gmail.com
      CONFIG_omero_mail_port: 465
      CONFIG_omero_mail_username: "${EMAIL}"
      CONFIG_omero_mail_password: "${PASSWORD}"
      CONFIG_omero_mail_smtp_debug: "true"
      CONFIG_omero_mail_smtp_starttls_enable: "true"
      CONFIG_omero_mail_transport_protocol: "smtps"
      CONFIG_omero_mail_smtp_socketFactory_class: javax.net.ssl.SSLSocketFactory
      CONFIG_omero_mail_smtp_socketFactory.port: 465
      ROOTPASS: omero
    networks:
      - omero
    ports:
      - "4063:4063"
      - "4064:4064"
    volumes:
      - "omero:/OMERO"
      - "./files/ome:/opt/omero/server/OMERO.server/etc/ome"
      - "./files:/opt/omero/server/OMERO.server/etc/blitz"
$ cat files/services.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--
  Mail resources
  =======================================================================
-->

  <bean id="localMailSender" class="org.springframework.aop.framework.ProxyFactoryBean">
      <description>
          Default mail sender uses a swappable target source so that for
          testing we can replace it with a no-op version.
      </description>
      <property name="targetSource" ref="local-mailSenderTargetSource"/>
  </bean>

  <bean id="local-mailSenderTargetSource"
      class="org.springframework.aop.target.HotSwappableTargetSource">
      <constructor-arg ref="local-javaMailSenderImpl"/>
  </bean>

  <!-- configure the MailSender with the authenticated session -->
  <bean id="local-javaMailSenderImpl"
      class="org.springframework.mail.javamail.JavaMailSenderImpl">
      <property name="host" value="${omero.mail.host}" />
      <property name="port" value="${omero.mail.port}" />
      <property name="protocol" value="${omero.mail.transport.protocol}" />
      <property name="session" ref="local-mailSession" />
      <property name="javaMailProperties">
          <props>
              <prop key="mail.smtp.sendpartial">true</prop>
          </props>
      </property>
  </bean>

  <!-- setup an authenticated session -->
  <bean id="local-mailSession" class="javax.mail.Session" factory-method="getInstance">
      <constructor-arg>
          <props>
              <prop key="mail.smtp.ssl">true</prop>
              <prop key="mail.smtp.ssl.enable">true</prop>
              <prop key="mail.smtp.ssl.trust">true</prop>
              <!-- existing -->
              <prop key="mail.smtps.auth">${omero.mail.smtp.auth}</prop>
              <prop key="mail.smtps.debug">${omero.mail.smtp.debug}</prop>
              <prop key="mail.smtps.connectiontimeout">${omero.mail.smtp.connectiontimeout}</prop>
              <prop key="mail.smtps.sendpartial">true</prop>
              <prop key="mail.smtps.starttls.enable">${omero.mail.smtp.starttls.enable}</prop>
              <prop key="mail.smtps.socketFactory.port">${omero.mail.smtp.socketFactory.port}</prop>
              <prop key="mail.smtps.socketFactory.class">${omero.mail.smtp.socketFactory.class}</prop>
              <prop key="mail.smtps.socketFactory.fallback">${omero.mail.smtp.socketFactory.fallback}</prop>
              <prop key="mail.smtps.timeout">${omero.mail.smtp.timeout}</prop>
          </props>
      </constructor-arg>
      <constructor-arg ref="local-smtpAuthenticator" />
  </bean>

  <!-- Authenticator implementation -->
  <bean id="local-smtpAuthenticator" class="ome.security.SmtpAuthenticator">
      <constructor-arg value="${omero.mail.username}" />
      <constructor-arg value="${omero.mail.password}" />
  </bean>

</beans>

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/password-reset-email-config/35701/7

mtbc commented

So far I am failing to get a TLS session going properly with a mail server that is under my control. On javax.mail.Session I set both mail.smtp.starttls.enable and mail.smtp.starttls.required to true then try sending but my MTA logs,

... received invalid command: "MAIL FROM:<mark@ixod.org>"

which is indeed my value for omero.mail.from. OMERO's SendEmailRequestI logs an SMTPSendFailedException that notes,

530 5.5.1 Invalid command: Must issue a STARTTLS command first

In sending successfully from my own MUA, rather than OMERO, my MTA logs the "connection from" and, next, the "TLS started" stuff.

mtbc commented

omero-server/build.gradle depends on com.sun.mail:javax.mail:1.6.1 but when I run OMERO.server and ask for javax.mail.Session.class.getPackage().getImplementationVersion() it tells me 1.4.4.

mtbc commented

I wonder if this could possibly have been broken even back in OMERO 5.5.

I tried https://github.com/manics/_java-gmail-sender/tree/75c3c802ad814c82a97de7c579d3d1764e8dbb24 inside the openmicroscopy/omero-server:5.6.2 Docker image:

docker run -it --rm -v /src/java-gmail-sender:/java-gmail-sender --entrypoint bash openmicroscopy/omero-server:5.6.2
cd 
wget https://services.gradle.org/distributions/gradle-6.6.1-bin.zip
unzip gradle-6.6.1-bin.zip

cd /java-gmail-sender
git diff
diff --git a/src/main/java/foo/SpringEmailTest.java b/src/main/java/foo/SpringEmailTest.java
index e1da081..01774ac 100644
--- a/src/main/java/foo/SpringEmailTest.java
+++ b/src/main/java/foo/SpringEmailTest.java
@@ -15,6 +15,6 @@ public class SpringEmailTest
         EmailService mailer = (EmailService) context.getBean("emailService");

         //Send a composed mail
-        mailer.sendMail("REPLACETHIS@example.org", "Test Subject", "Testing body");
+        mailer.sendMail("<DESTINATION>@dundee.ac.uk", "Test Subject", "Testing body");
     }
 }
\ No newline at end of file
diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml
index e98cd85..8fd17b3 100644
--- a/src/main/resources/applicationContext.xml
+++ b/src/main/resources/applicationContext.xml
@@ -13,8 +13,8 @@
         <property name="host" value="smtp.gmail.com"/>
         <property name="port" value="587"/>
         <!-- <property name="port" value="465"/> -->
-        <property name="username" value="admin@gmail.com"/>
-        <property name="password" value="password"/>
+        <property name="username" value="<SENDER-GMAIL>@gmail.com"/>
+        <property name="password" value="<PASSWORD>"/>
         <property name="javaMailProperties">
             <props>
                 <prop key="mail.debug">true</prop>

This successfully sends an email from a GMail account to a dundee.ac.uk account:

JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.8.10-0.el7_8.x86_64 ~/gradle-6.6.1/bin/gradle run

I also tried with smtps port 465, successfully:

diff --git a/src/main/java/foo/SpringEmailTest.java b/src/main/java/foo/SpringEmailTest.java
index e1da081..01774ac 100644
--- a/src/main/java/foo/SpringEmailTest.java
+++ b/src/main/java/foo/SpringEmailTest.java
@@ -15,6 +15,6 @@ public class SpringEmailTest
         EmailService mailer = (EmailService) context.getBean("emailService");

         //Send a composed mail
-        mailer.sendMail("REPLACETHIS@example.org", "Test Subject", "Testing body");
+        mailer.sendMail("<DESTINATION>@dundee.ac.uk", "Test Subject", "Testing body");
     }
 }
\ No newline at end of file
diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml
index 9feb477..73239a4 100644
--- a/src/main/resources/applicationContext.xml
+++ b/src/main/resources/applicationContext.xml
@@ -11,14 +11,14 @@
     <!-- SET default mail properties -->
     <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
         <property name="host" value="smtp.gmail.com"/>
-        <property name="port" value="587"/>
-        <!-- <property name="port" value="465"/> -->
-        <property name="username" value="admin@gmail.com"/>
-        <property name="password" value="password"/>
+        <!-- <property name="port" value="587"/> -->
+        <property name="port" value="465"/>
+        <property name="username" value="<SENDER-GMAIL>@gmail.com"/>
+        <property name="password" value="<PASSWORD>"/>
         <property name="javaMailProperties">
             <props>
                 <prop key="mail.debug">true</prop>
-                <prop key="mail.transport.protocol">smtp</prop>
+                <prop key="mail.transport.protocol">smtps</prop>

                 <prop key="mail.smtp.auth">true</prop>
                 <prop key="mail.smtp.starttls.enable">true</prop>

Changing the dependencies to match

implementation("org.springframework:spring-context-support:4.3.14.RELEASE")

implementation("com.sun.mail:javax.mail:1.6.1")

also works:

diff --git a/build.gradle b/build.gradle
index 4e9f758..cb90769 100644
--- a/build.gradle
+++ b/build.gradle
@@ -15,8 +15,10 @@ repositories {
 }

 dependencies {
-    implementation 'org.springframework:spring-context-support:5.2.9.RELEASE'
-    implementation 'javax.mail:mail:1.4.7'
+    // implementation 'org.springframework:spring-context-support:5.2.9.RELEASE'
+    implementation 'org.springframework:spring-context-support:4.3.14.RELEASE'
+    // implementation 'javax.mail:javax.mail-api:1.4.7'
+    implementation 'com.sun.mail:javax.mail:1.6.1'
 }

 group = 'org.openmicroscopy'