Ricardo Almeida
Ricardo Almeida

Reputation: 61

How to configure Jakarta Mail/Angus Mail in Tomcat 10 using JNDI?

I downloaded jakarta.mail-api-2.1.3.jar, jakarta.activation-api-2.1.3.jar and angus-mail-2.0.3.jar into tomcat lib folder.

I created a EmailService class, where the Session object is initialized by itself:

    package fiscalREST.service;

    import jakarta.mail.*;
    import jakarta.mail.internet.InternetAddress;
    import jakarta.mail.internet.MimeMessage;

    import java.util.Properties;

    public class EmailService {
        private Session session;

        public EmailService() {
            Properties props = new Properties();
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.host", "smtp.email.eu-frankfurt-1.oci.oraclecloud.com");
            props.put("mail.smtp.port", "587");
            props.put("mail.from", "[email protected]");
            props.put("mail.smtp.auth", "true");
            String username = "ocid1.user.oc1...com";
            String password = "password";

            session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
        }

        public void sendEmail(String to, String subject, String body) {
            try {
                Message message = new MimeMessage(session);
                message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(to)});
                message.setSubject(subject);
                message.setContent("content", "text/plain");

                Transport.send(message);
            } catch (Exception e) {
                throw new IllegalStateException("Error sending email", e);
            }
        }
    }

And it sends the email successfully. Next, I tried to configure JNDI.

I edited tomcat conf/server.xml and added inside the <GlobalNamingResources>

    <Resource
        global="mail/Session"
        name="mail/Session"
        auth="Container"
        type="jakarta.mail.Session"
    />
    <ResourceParams name="mail/Session">
        <parameter>
            <name>mail.smtp.starttls.enable</name><value>true</value>
        </parameter>
        <parameter>
            <name>mail.smtp.host</name><value>smtp.email.eu-frankfurt-1.oci.oraclecloud.com</value>
        </parameter>
        <parameter>
          <name>mail.smtp.port</name><value>587</value>
        </parameter>
        <parameter>
          <name>mail.from</name><value>[email protected]</value>
        </parameter>
        <parameter>
          <name>mail.smtp.auth</name><value>true</value>
        </parameter>
        <parameter>
          <name>mail.smtp.user</name><value>ocid1.user.oc1...com</value>
        </parameter>
        <parameter>
          <name>password</name><value>password</value>
        </parameter>
    </ResourceParams>

I edited tomcat conf/context.xml and added inside the <Context>

    <ResourceLink
        global="mail/Session"
        name="mail/Session"
        auth="Container"
        type="jakarta.mail.Session"
    />

The application WEB-INF/web.xml:

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">
  <description>Test App</description>
  <resource-ref>
    <description>Mail Session</description>
    <res-ref-name>mail/Session</res-ref-name>
    <res-type>jakarta.mail.Session</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

and changed the EmailService constructor to grab it.

    public EmailService() {
        try {
            Context initContext = new InitialContext();
            Context envContext = (Context) initContext.lookup("java:/comp/env");
            session = (Session) envContext.lookup("mail/Session");
        } catch (Exception e) {
            throw new IllegalStateException("Error getting email session", e);
        }
    }

but when sending the email I get an Exception with the following (clipped as was too long) stacktrace:

java.lang.IllegalStateException: Error sending email
    at fiscalREST.service.EmailService.sendEmail(EmailService.java:50) ~[service.jar:?]
...
Caused by: org.eclipse.angus.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1
    at org.eclipse.angus.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2243) ~[angus-mail-2.0.3.jar:?]
    at org.eclipse.angus.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:729) ~[angus-mail-2.0.3.jar:?]
    at jakarta.mail.Service.connect(Service.java:345) ~[jakarta.mail-api-2.1.3.jar:?]
...
Caused by: java.net.ConnectException: Connection refused
...

Seems it's not picking up the ResourceParams values as it's trying to connect to localhost in port 25 instead of what I attempted to configure. What am I doing wrong? What's the correct way to configure it?

Upvotes: 0

Views: 207

Answers (1)

Ricardo Almeida
Ricardo Almeida

Reputation: 61

Got the answer in Tomcat Users Mailing List. Putting it here for future reference.

Seems I was looking at old documentation as Tomcat doesn't support ResourceParams just over 20 years! (removed in this commit)

Must add the properties directly to the <Resource .../> element as attributes and values, like:

    <Resource
        global="mail/Session"
        name="mail/Session"
        auth="Container"
        type="jakarta.mail.Session"
        mail.smtp.starttls.enable="true"
        mail.smtp.host="smtp.email.eu-frankfurt-1.oci.oraclecloud.com"
        mail.smtp.port="587"
        mail.from="[email protected]"
        mail.smtp.auth="true"
        mail.smtp.user="ocid1.user.oc1...com"
        password="password"
    />

Upvotes: 0

Related Questions