1

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.

bluish
  • 26,356
  • 27
  • 122
  • 180
firefly
  • 183
  • 1
  • 2
  • 7
  • 2
    is this homework? or is there any specific reason for not using java.mail? – Harry Joy May 30 '11 at 04:45
  • 2
    If you wanted to do this without SSL, it's pretty easy. If you want to do it by hand with TLS, though, forget it. WHy bother? – Ernest Friedman-Hill May 30 '11 at 04:46
  • @Ernest, I think the problem is that GMail requires the authentication to be performed on an SSL/TLS connection. If you connect in plain text first (port 587), it will force the client to use `STARTTLS` and upgrade to a TLS connection on that port before doing anything else. – Bruno May 30 '11 at 05:10
  • Well, don't use GMail's SMTP server -- use another one, and let it relay the mail to GMail. – Ernest Friedman-Hill May 30 '11 at 12:23
  • @Ernest, the OP didn't specify the environment in which this application is meant to run. Most non password-protected SMTP servers only work within their LAN, so if you move your laptop to other networks, you have to reconfigure it every time. If you always use the same SMTP server from any network, it will be likely to be password-protected for your account (otherwise, anyone could use it to send spam); in this case, it's actually quite useful to turn on SSL/TLS (via either mechanism), since it's sometimes hard to assess who may be listening on that network (especially on public Wifi). – Bruno May 30 '11 at 17:51

2 Answers2

2

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.

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
0

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:

Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174