8

0

I am trying to connect to a mail server from Java. I have been able to successfully connect to many mail servers from Java using the same code, including Gmail, Rackspace, GoDaddy, and others, but this one does not work no matter the settings I try.

    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", this.outgoingHost);
    props.put("mail.smtp.port", 587);
    props.put("mail.smtp.ssl.trust", this.outgoingHost);
    session = Session.getInstance(props, new javax.mail.Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

This fails with, javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

I also tried,

    props.put("mail.smtp.host", this.outgoingHost);
    props.put("mail.smtp.port", 587);
    props.put("mail.smtp.socketFactory.port", 587);
    props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.ssl.trust", this.outgoingHost);
    session = Session.getInstance(props, new javax.mail.Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

This fails with, javax.mail.SendFailedException: Invalid Addresses; nested exception is: com.sun.mail.smtp.SMTPAddressFailedException: 550 SMTP AUTH is required for message submission on port 587

I also tried port 465, but it gets a timeout.

I was able to send mail using the same smtp settings from Thunderbird email client (same host/port/user/pw, but it must be doing something else).

Using Java Mail 1.51

Any ideas?

JGFMK
  • 8,425
  • 4
  • 58
  • 92
James
  • 17,965
  • 11
  • 91
  • 146
  • Never use the socket factory properties. Try using a newer JavaMail in case it might help. Post the JavaMail debug output along with the code you're using. – Bill Shannon Mar 13 '20 at 22:48
  • Is the mail server managed by you or your organisation? Or is it some mail service similar to GMail? – Eugene Khyst Mar 16 '20 at 11:33
  • Are you using Linux? Can you run `nc -zvw3 outgoingHost 587` to check the server is listening on the port 587? To check TLS run `openssl s_client -connect outgoingHost:587 -starttls smtp` – Eugene Khyst Mar 16 '20 at 11:46
  • No, the mail server belongs to a client. – James Mar 17 '20 at 13:57
  • openssl is able to connect to the server, as well I am able to connect from Thunderbird email client using same settings (host/port/tls). – James Mar 17 '20 at 13:58
  • It would be super helpful if I could try to connect to that e-mail server myself with a JavaMail client in order to debug and play around a bit. If you would contact me privately via one of the ways described in my SO profile text (scroll to the bottom), I could use a test account on that server in order to analyse the situation. But if I cannot reproduce the problem, I cannot help. – kriegaex Mar 18 '20 at 12:25
  • which mail server is used ?? – Anish B. Mar 22 '20 at 10:48

2 Answers2

21

When you use SSL (smtps), you don't use STARTTLS (msa) and vice versa. SSL defaults to port 465 and TLS to port 587. You might also have to set the SSL protocols using mail.smtp.ssl.protocols or mail.smtps.ssl.protocols to specify the SSL protocols that will be enabled for SSL/TLS connections. You better avoid overriding PasswordAuthentication for sending credentials and use SMTPTransport connect method. Also it's very important that for SSL, you have to use smtps for mail.transport.protocol and use mail.smtps props instead of mail.smtp. I'll provide examples for both SSL and TLS.

You can debug and see the whole communication in the console using session.setDebug(true) or props.put("mail.debug", "true"); that will help a lot as you'll see the whole telnet communication with the server.

Using TLS (STARTTLS) 587:

// Set debug so we see the whole communication with the server
props.put("mail.debug", "true");

props.put("mail.transport.protocol", "smtp");
props.put("mail.host", outgoingHost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "587");

// Enable STARTTLS
props.put("mail.smtp.starttls.enable", "true");

// Accept only TLS 1.1 and 1.2
props.setProperty("mail.smtp.ssl.protocols", "TLSv1.1 TLSv1.2");

Session session = Session.getInstance(props, null);
session.setDebug(true);

// Create an SMTP transport from the session
SMTPTransport t = (SMTPTransport)session.getTransport("smtp");

// Connect to the server using credentials
t.connect(outgoingHost, username, password);

// Send the message
t.sendMessage(msg, msg.getAllRecipients());

Sample debug output using STARTTLS:

Notice the TRANSPORT protocol is smtp

DEBUG: JavaMail version 1.5.1
...
DEBUG: setDebug: JavaMail version 1.5.1
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "mail.example.com", port 587, isSSL false
220-srv.example.com ESMTP Exim 4.92 #2 Wed, 18 Mar 2020 15:55:56 +0200 
220-We do not authorize the use of this system to transport unsolicited, 
220 and/or bulk e-mail.
DEBUG SMTP: connected to host "mail.example.com", port: 587

EHLO host.docker.internal
250-srv.example.com Hello ppp.home.provider.com [x.x.x.x]
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
DEBUG SMTP: Found extension "SIZE", arg "52428800"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "HELP", arg ""
STARTTLS
220 TLS go ahead
EHLO host.docker.internal
250-srv.example.com Hello ppp.home.provider.com [x.x.x.x]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN LOGIN
250 HELP
DEBUG SMTP: Found extension "SIZE", arg "52428800"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "HELP", arg ""
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
DEBUG SMTP: use8bit false
MAIL FROM:<user@example.com>
250 OK
RCPT TO:<otheruser@mail.com>
250 Accepted
DEBUG SMTP: Verified Addresses
DEBUG SMTP:   otheruser@mail.com
DATA
354 Enter message, ending with "." on a line by itself
Date: Wed, 18 Mar 2020 15:55:57 +0200 (EET)
From: user@example.com
To: otheruser@mail.com
Message-ID: <1899073220.0.1584539759931.JavaMail.user@mail.example.com>
Subject: Test from JAVA!
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: smtpsend

Message from the JAVA app STARTTLS!
.
250 OK id=1jEZAt-009Y7x-5Z
Response: 250 OK id=1jEZAt-009Y7x-5Z

QUIT
221 srv.example.com closing connection

Using SSL 465:

// Set debug so we see the whole communication with the server
props.put("mail.debug", "true");

// All mail props for protocol will be mail.smtps

// We set smtps transport protocol for SSL
props.put("mail.transport.protocol", "smtps");
props.put("mail.host", outgoingHost);
props.put("mail.smtps.auth", "true");
props.put("mail.smtps.port", "465");
props.put("mail.smtps.ssl.trust", outgoingHost);
props.put("mail.smtps.ssl.enable", "true");

// Accept only TLS 1.1 and 1.2
props.setProperty("mail.smtps.ssl.protocols", "TLSv1.1 TLSv1.2");

Session session = Session.getInstance(props, null);
session.setDebug(true);

// Create an SMTP transport from the session
SMTPTransport t = (SMTPTransport)session.getTransport("smtps");

// Connect to the server using credentials
t.connect(outgoingHost, username, password);

// Send the message
t.sendMessage(msg, msg.getAllRecipients());

Sample debug output using SSL:

Notice the TRANSPORT protocol is smtps

DEBUG: JavaMail version 1.5.1
...
DEBUG: setDebug: JavaMail version 1.5.1
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "mail.example.com", port 465, isSSL true
220-srv.example.com ESMTP Exim 4.92 #2 Wed, 18 Mar 2020 16:09:51 +0200 
220-We do not authorize the use of this system to transport unsolicited, 
220 and/or bulk e-mail.
DEBUG SMTP: connected to host "mail.example.com", port: 465

EHLO host.docker.internal
250-srv.example.com Hello ppp.home.provider.com [x.x.x.x]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN LOGIN
250 HELP
DEBUG SMTP: Found extension "SIZE", arg "52428800"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "HELP", arg ""
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
DEBUG SMTP: use8bit false
MAIL FROM:<user@example.com>
250 OK
RCPT TO:<otheruser@mail.com>
250 Accepted
DEBUG SMTP: Verified Addresses
DEBUG SMTP:   otheruser@mail.com
DATA
354 Enter message, ending with "." on a line by itself
Date: Wed, 18 Mar 2020 16:09:50 +0200 (EET)
From: user@example.com
To: otheruser@mail.com
Message-ID: <1620303253.0.1584540592904.JavaMail.user@mail.example.com>
Subject: Test from JAVA!
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: smtpsend

Message from the JAVA app SSL!
.
250 OK id=1jEZOK-009bbA-5C
Response: 250 OK id=1jEZOK-009bbA-5C

QUIT
221 srv.example.com closing connection
Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
  • SMTP is more likely STARTTLS nowadays. I just want to mention port 465 is deprecated and SHOULD NOT TO USE with any mailing related due its officially held by Cisco. – NPULSENET Mar 19 '20 at 00:50
  • @NPULSENET yes I agree, `465` is deprecated nowadays. Port `465` is `smtps` protocol and port `587` is `msa` ([What is the difference between ports 465 and 587?](https://stackoverflow.com/questions/15796530/what-is-the-difference-between-ports-465-and-587)). I add it to my answer because the OP does mention it and maybe their client has a server that supports only SSL over `465`. In fact all of my servers (*third hosting providers*) do still have support for `465` as for port `25` but `587` should always be used if supported. – Christos Lytras Mar 19 '20 at 01:03
  • thanks, I'll try the debug option. However because I have had too many failed attempts the client's mail server is now blocking me... will need to try from a different IP – James Mar 19 '20 at 15:36
  • @James yes. Most likely the server has ["ConfigServer Security & Firewall (csf)"](https://configserver.com/cp/csf.html) which add temporary blocks to IPs that have too many failed login attempts. With the default configuration, those IPs will be unblocked after 30 minutes, but you can restart your router to get a new IP and try to connect to the SMPT server again. It's hard to debug under such circumstances. – Christos Lytras Mar 19 '20 at 16:10
0

Check this link to enable permission (if the sender has a google email):

Link Permission Google

Without permission you cannot do login from an app that is not developed by google.

For Login use only domain of your mail. For example: text@gmail.com -> text