0
votes

I am sending an email using Jakarta Mail and my email providers (hover) smtp server. I expected to have to install the smtp servers public key, and pass it with the request in order to encrypt the traffic. However it seems to be working without that. This SO answer (https://stackoverflow.com/a/16843712) seems to indicate that might not be necessary because hover would use a certificate signed by a commercial Certificate Authority. Also the debug printout seems to indicate ssl was used.

I have 2 questions. The first is what exactly is encrypted by the code below: the login, the email, both or neither.

Here is the code:

        // to and from addresses
        String to = "[email protected]";
        String from = "[email protected]";

        final String password = "mypassword";

        String host = "mail.hover.com";
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");

        props.put("mail.smtp.ssl.enable", "true");
        
        // works same with this commented or not
        // props.put("mail.smtp.ssl.trust", "mail.hover.com");

        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", "465");
        
        // print out debug messages
        props.put("mail.debug", "true");
        
        //create the Session object
        Session session = Session.getInstance(props, new Authenticator() {
            
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(to, password);
            }
            
        });
        
        
        try {
            //create a MimeMessage object

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject("Here comes Jakarta Mail!");
            message.setContent("Just discovered that Jakarta Mail is fun and easy to use", "text/html");

            //send the email message
             Transport.send(message);
            
            // this works too
            // Transport transport = session.getTransport("smtps");
            // transport.connect("mail.hover.com", 465, username, password);
            // transport.sendMessage(message, message.getAllRecipients());

            System.out.println("Email Message Sent Successfully");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    

    }

My second question is why does google mark the sent email as unverified when it is received? I suspect it has something to do with my first question.

unverified email image

Here is my debug printout:

DEBUG: Jakarta Mail version 2.0.0 DEBUG: successfully loaded resource: /META-INF/javamail.default.providers DEBUG: Tables of loaded providers DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPTransport=jakarta.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=jakarta.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3Store=jakarta.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], com.sun.mail.smtp.SMTPSSLTransport=jakarta.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.imap.IMAPStore=jakarta.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3SSLStore=jakarta.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle]} DEBUG: Providers Listed By Protocol: {imap=jakarta.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtp=jakarta.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], pop3=jakarta.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], imaps=jakarta.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], smtps=jakarta.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3s=jakarta.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle]} DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map DEBUG: getProvider() returning jakarta.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: need username and password for authentication DEBUG SMTP: protocolConnect returning false, host=mail.hover.com, user=paul, password= DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "mail.hover.com", port 465, isSSL true 220 smtp.hostedemail.com ESMTP DEBUG SMTP: connected to host "mail.hover.com", port: 465 EHLO 192.168.0.12 250-omf04.hostedemail.com 250-PIPELINING 250-SIZE 36700160 250-ETRN 250-AUTH PLAIN LOGIN 250-AUTH=PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 CHUNKING DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "36700160" DEBUG SMTP: Found extension "ETRN", arg "" DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN" DEBUG SMTP: Found extension "AUTH=PLAIN", arg "LOGIN" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "DSN", arg "" DEBUG SMTP: Found extension "CHUNKING", arg "" DEBUG SMTP: protocolConnect login, host=mail.hover.com, [email protected], password= DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 DEBUG SMTP: Using mechanism LOGIN DEBUG SMTP: AUTH LOGIN command trace suppressed DEBUG SMTP: AUTH LOGIN succeeded DEBUG SMTP: use8bit false MAIL FROM:[email protected] 250 2.1.0 Ok RCPT TO:[email protected] 250 2.1.5 Ok DEBUG SMTP: Verified Addresses DEBUG SMTP: [email protected] DATA 354 End data with . Date: Tue, 9 Feb 2021 10:31:07 -0500 (EST) From: [email protected] To: [email protected] Message-ID: <1880587495.0.1612884672084@[192.168.0.11]> Subject: Here comes Jakarta Mail! MIME-Version: 1.0 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7bit Just discovered that Jakarta Mail is fun and easy to use 250 Ok Queued as books05_4e0c9e627608 DEBUG SMTP: message successfully delivered to mail server QUIT 221 2.0.0 Bye Email Message Sent Successfully

Thanks in advance!

1
You are connecting to mail.hover.com port 465. On that port mail.hover.com only supports SMTP over SSL (SMTPS). Therefore similar to HTTPS the complete communication is protected - not only encrypted. - Robert
Thanks @Robert, that's helpful. It seems my second question would not have anything to do with encryption then, maybe I should make it a second post? - Paul
The answer to your second question is also simple: you are using the wrong server for sending the message. Use the smtp server of my mycompany.com. Since DKIM, only those the from address is bound to the server it "belongs" to. Only those mails can get verified (signed by the sending server). - Robert
@Robert, I'm not sure I understand. Hover is the smtp server for my company.com. So my java app is acting as a client and sending the email to hover which then sends it to the recipient, same as any client would. Am I misunderstanding your point? ps. thanks for the pointer about DKIM, I'll read up on that. - Paul

1 Answers

0
votes

First I have to give credit to @Robert who answered my first question in his comment, and in his comment regarding my second question he mentioned DKIM, which put me on the path to solving my second question.

So the answer to my first question is everything is encrypted in the jakarta mail example, including the login and the message. You don't need to use the smpt servers public key because in my case it uses a certificate signed by a commercial Certificate Authority. (per @Robert and https://stackoverflow.com/a/16843712)

As for my second question, why is goole marking my emails as unverified when they are received, the answer is to sign the emails using DKIM when sending them. To do this I followed these steps:

To sign my emails I used this library: https://github.com/markenwerk/java-utils-mail-dkim. Note I had to revert to using javax mail from jakarta mail because this method in the library expects a javax.mail.internet.MimeMessage DkimMessage(mimeMessage, dkimSigner);

I then used this tool to produce the private and public keys: https://tools.socketlabs.com/dkim/generator Paste the private key into a file and name it with the .pem extension.

Now you have to add a DKIM TXT record to you websites DNS settings. Here is a link which explains how: https://blog.mailtrap.io/create-dkim-tutorial/

The library expects a .der file so convert the .pem to .der using openssl, with this command: openssl pkcs8 -topk8 -nocrypt -in myDkim.pem -out myDkim.der -outform der

I then used the following method to sign my emails, adapted from the instructions on the librarys web page.

private DkimMessage dkimSignMessage(MimeMessage message, String from, String signingDomain, String selector, File derFile) {    
    try {
        DkimSigner dkimSigner = new DkimSigner(signingDomain, selector, derFile);
        dkimSigner.setIdentity(from);
        dkimSigner.setHeaderCanonicalization(Canonicalization.SIMPLE);
        dkimSigner.setBodyCanonicalization(Canonicalization.RELAXED);
        dkimSigner.setSigningAlgorithm(SigningAlgorithm.SHA256_WITH_RSA);
        dkimSigner.setLengthParam(true);
        dkimSigner.setCopyHeaderFields(false);
        return new DkimMessage(message, dkimSigner);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

After completing these steps, google no longer marked the email as unvalidated. Here is a link with a good explanation of DKIM: https://postmarkapp.com/guides/dkim