SMTP send mail is not working for office365

Check your JRE version on the server and compare it to the version of your local computer.

This is an environment related issue as the same code behaves differently on different machines. Without the full picture, I cannot answer with certainty. But I hope providing some insight for further investigation. My analysis follows:

  • First, I don't think it's a SSL certificate issue, the root cause error is clear:
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
...
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
...

this means the socket has been established, but the handshake phase of converting the socket to TLS has failed. If the certificate is not valid, it will be reported after the handshake, let's look at the code from the SocketFetcher.java class:

    /*
     * Force the handshake to be done now so that we can report any
     * errors (e.g., certificate errors) to the caller of the startTLS
     * method.
     */
    sslsocket.startHandshake();

    /*
     * Check server identity and trust.
     */
    boolean idCheck = PropUtil.getBooleanProperty(props,
                prefix + ".ssl.checkserveridentity", false);
    if (idCheck)
        checkServerIdentity(host, sslsocket);
    if (sf instanceof MailSSLSocketFactory) {
        MailSSLSocketFactory msf = (MailSSLSocketFactory)sf;
        if (!msf.isServerTrusted(host, sslsocket)) {
        throw cleanupAndThrow(sslsocket,
            new IOException("Server is not trusted: " + host));
        }
    }
    }

the socket encountered the timeout at this line: sslsocket.startHandshake(), which is before the certificate validation.

  • Second, you have already mentioned that firewalls are disabled, and we can see that the previous socket is correctly established so is the telnet command, so I don't think it's a firewall issue neither.

  • It seems like a protocol issue, mostly because this happened during the handshake phase, otherwise we should see different and more explicit error, such as certificate error, connection timeout, etc. This is a socketRead timeout, which indicates the client (your server) is expecting some information from the server (office365), but the server doesn't respond, it's like they are not talking together.

  • The compiled code is not the issue here, but some part of this process is environment related: the SSLSocketImpl.class class is from the JRE not from the compilation. And this is the exact code (decompiled) where the protocol is implemented:

private void performInitialHandshake() throws IOException {
        Object var1 = this.handshakeLock;
        synchronized(this.handshakeLock) {
            if (this.getConnectionState() == 1) {
                this.kickstartHandshake();
                if (this.inrec == null) {
                    this.inrec = new InputRecord();
                    this.inrec.setHandshakeHash(this.input.r.getHandshakeHash());
                    this.inrec.setHelloVersion(this.input.r.getHelloVersion());
                    this.inrec.enableFormatChecks();
                }

                this.readRecord(this.inrec, false);
                this.inrec = null;
            }

        }
    }

The above code is from JRE_1.8.0_181, your code or the code from your server may be different. This is way it's necessary to check your server's JRE version.

  • Using the same code you provided at the beginning, I could correctly connect to office365

Check whether the server has the same set of certificates as your local computer.

The 220 response from the server does not mean that the TLS session is already established, it just means that the client may start negotiating it:

After receiving a 220 response to a STARTTLS command, the client MUST start the TLS negotiation before giving any other SMTP commands. If, after having issued the STARTTLS command, the client finds out that some failure prevents it from actually starting a TLS handshake, then it SHOULD abort the connection. (from RFC 3207)

At this point, a missing certificate is the most likely problem.