firefly
firefly

Reputation: 183

Send mail using socket in Java

I want to code a simple program in java that can send mail via socket(not java.mail); I got some examples,but it doesn't work(following is the basic problems):

  1. Should I send the mail to sender's smtp server first?(this may have to provide real username and password).

  2. I got an example that sends to the receiver's smtp sever directly. I use gmail to test, but it failed, giving info:

    530 5.7.0 Must issue a STARTTLS command first.
    

    I think it is because gmail needs SSL socket. Then I got a simple SSL implementation to exchange "new Socket", it failed again with error info:

    javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    

Maybe the SSL usage is wrong? This is the SSL code:

class Java2000TrustManager implements X509TrustManager {

Java2000TrustManager() {
}

public void checkClientTrusted(X509Certificate chain[], String authType)
        throws CertificateException {
    System.out.println("checkClientTrusted...");
}

public void checkServerTrusted(X509Certificate chain[], String authType)
        throws CertificateException {
    System.out.println("checkServerTrusted");
}

public X509Certificate[] getAcceptedIssuers() {
    System.out.println("getAcceptedIssuers...");
    return null;
}
}

Please give me a way to implement this successfully.

Upvotes: 1

Views: 3212

Answers (2)

Bruno
Bruno

Reputation: 122739

What you're doing in your TrustManager effectively disables an essential check (the verification of the server certificate) that makes the SSL/TLS connection secure. I'd be very surprised if GMail didn't have a certificate issued by a CA that's in the default trust store. You shouldn't need to change any trust settings.

The problem you're having seems to do the usage of STARTTLS, which is an SMTP command (so you might need to read more about it in the SMTP specification).

There are two ways of enabling SSL/TLS in SMTP connections, as described here, although they're often badly labelled (some call "TLS" what really is "using STARTTLS"):

  • One of them is "on connection" or "up front" (I'm not sure whether there's a standard terminology on this). In this case you establish the SSL or TLS connection before exchanging any SMTP message. This tends to be on port 465 for SMTP.

  • The other is a switch to TLS (although it actually works with SSLv3 too, sometimes) during an SMTP exchange, using the STARTTLS command. Here, the client starts talking to the server in plain text using SMTP commands, but then sends a STARTTLS command and initiates a TLS handshake to turn the plain socket into an SSL/TLS one. This can be on ports 25 or 587 for SMTP.

As far as I know, Gmail supports both.

If you're not too familiar with TLS handshakes and turning a plain socket into an SSL/TLS socket (you could do with with Channels and an SSLEngine for example), it's probably easier to use the first method: SSL/TLS upon connection. In this case, just use an SSLSocket and an SSLSocketFactory to intiate the connection. You don't need to use STARTTLS (as part of the SMTP protocol) after that, since you'll already be using SSL/TLS.

Upvotes: 2

Vineet Reynolds
Vineet Reynolds

Reputation: 76719

The code implements a X509TrustManager interface. On it's own it is useless, and serves a purpose that is different from the one that you have. If you need to initialize a socket that employs SSL/TLS you'll need to

  1. create a SSLSocketFactory,
  2. create a Socket from the SSLSocketFactory that connects to the required server at a particular port
  3. Write data to and read data from the socket, just like with any other socket (not encumbered by SSL/TLS).

Related information:

Upvotes: 0

Related Questions