The first standard for email delivery was Simple Mail Transfer Protocol (SMTP). As its name implies, it is a very simple protocol and is still in use. However, SMTP is a fairly naive protocol, and provides no facilities to verify the user’s identity. This means, any user who has an account in the mail server can send an email to any other user without any password verification.
This basic flaw in the protocol may be exploited by viruses, worms, security frauds and spammers forging identities. This makes the system vulnerable and must be avoided. So, usually an SMTP server runs an authorization protocol (typically Secure Socket Layer (SSL), or Transport Layer Security (TLS)) over the SMTP protocol. In this case, usually users are not allowed to connect to the SMTP port directly. A user typically connects to the SSL/TLS first and provides authorization information. The SSL/TLS starts the authorization procedure and if the user passes this authorization procedure, SSL/TLS forwards the request to the actual SMTP server. Some mail servers allow users to connect to the port 25; however, users must go through the authentication procedure first before working with normal SMTP.
SMTP may be made secured using SSL or TLS and the corresponding port number used is shown in Table 15.1:
A detailed description of these two protocols may be found in Chapter 20.
In this section, we shall discuss how to send mails using SSL or TLS and Java mail API. For demonstration purpose, we have created an account in Gmail server having username usr.some and password some.usr.
First we have to specify that an authentication is required as follows:
props.put(“mail.smtp.auth”, “true”);
Then, we have to specify which protocol (SSL/TLS) we want to use for authentication.
1. Using SSL
Most of the mail servers including mail support SSL for user authentication. So, it is a good idea to use SSL to pass through the authentication procedure. The following properties are required for SSL:
props.put(“mail.smtp.port”, ”465”);
props.put(“mail.smtp.socketFactory.class”,”javax.net.ssl.SSLSocketFactory”);
The first line indicates that the port number 4 65 (i.e. SMTP/SSL) is to be used for authentication. If this standard port number is not used for SSL, find it and use it in place of 4 65. A list of port numbers used by standard email servers is given later in this chapter. During the mail delivery, the SSL handshake starts immediately when a client connects to this port, and only after the session is encrypted, the SMTP protocol begins.
The second line tells that the client will get help from javax.net.ssi.ssLSocketFactory class to talk to SSL server. Indeed, JavaMail API includes this class, which implements SSL. This second line is mandatory if the SMTP server uses SSL (port 465) for authentication, like the Gmail SMTP server does.
2. Using TLS
If TLS is used as a security layer, the following properties are required:
props.put(“mail.smtp.starttls.enable”, “true”);
Note that the above piece of code does not use any specialized class to talk to TLS server. This is because TLS uses plaintext authentication and hence no specialized authenticator is required. However, to start the authentication procedure, the above line is required.
Note that the previous mechanism uses two ports, 4 65 (for SSL) and 25 (for SMTP). Port 4 65 authenticates the user and forwards the request to 25. For plaintext authentication, only one port may be used instead of two ports. However, one additional command starttls is added to SMTP. So, clients connect to regular SMTP port (25) and issue a starttls command after which the session is encrypted. Once the session is encrypted regular SMTP starts working.
By setting mail.smtp.starttls.enable property to true, we tell the client to issue a starttls command to start authentication procedure.
However, for smooth transition from SSL to TLS, a separate port (587) for TLS is provided. So, it is possible to connect to this port as follows:
props.put(”mail.smtp.port”, ”587”);
In this case, clients connect to the port 5 8 7 where authentication starts and once it is over, regular SMTP starts. However, connecting to this port (5 8 7) it is not mandatory to use TLS.
3. Providing Authentication Information
We create two strings, one for username and the other for password:
final String user = ”usr.some”, password = ”some.usr”;
Since, SSL or TLS requires authentication information, we have to pass username and password information. There are many ways we can do this:
- Using Authenticator object
- Using send() method of Transport Class
- Using connect() method of Transport Class
Using Authenticator object
In this case, we create a subclass (usually inner) from abstract javax.maii.Authenticator class overriding its getPasswordAuthentication() method as follows:
class MyAuthenticator extends javax.maii.Authenticator {
String user, password;
MyAuthenticator(String user, String password) {
this.user = user; this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication()
{ return new PasswordAuthentication(user, password);
}
}
The getPasswordAuthentication() method returns a PasswordAuthentication instance created from a (username, password) pair. An instance of this class is then registered with the Session object during its creation.
Authenticator auth = new MyAuthenticator(user, password);
Session session = Session.getInstance(props, auth);
When authentication is required, subclass’s getPasswordAuthentication() method is called. We can also collect username and password using popup dialog as follows:
class PopupAuthenticator extends Authenticator {
protected PasswordAuthentication getPasswordAuthentication() {
String user = JOptionPane.showInputDialog(”Enter username:”);
String password = JOptionPane.showInputDialog(”Enter password:”);
return new PasswordAuthentication(user, password);
}
}
Authenticator auth = new PopupAuthenticator();
Session session = Session.getInstance(props, auth);
Alternatively, we can create and use an anonymous inner class as follows:
Authenticator auth = new Authenticator () {
public PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(user, password);
}
};
Session session = Session.getInstance(props, auth);
To summarize, we create and use anonymous class during the creation of Session object as follows:
Session session = Session.getInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
});
Using send() method of Transport Class
Alternatively, the user name and password may be specified in the send() method of transport class directly as follows:
Session session = Session.getlnstance(props);
Transport.send(msg, user, password);
Using connect() method of Transport Class
We can also send a mail using a specific instance from the session for SMTP protocol as follows:
Transport transport = session.getTransport(”smtps”);
transport.connect(host, user, password);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
The connect() method establishes a connection to the specified host and username and password, whereas sendMessage() method delivers the message. Since, connects method keeps the connection (unless the connection is not closed explicitly using ciose() method) open with the mail server, this method is useful if we want to send multiple messages. The static send() method makes a separate connection to the server for each method call and closes it once the message is delivered.
The following program (sendEmaiii.java) sends a mail from the user usr.some@gmaii.com to itself using SSL.
//SendEmaiii.java
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
public class SendEmail1 {
public static void main(String [] args) {
String mailHost = “smtp.gmail.com”;
String from = “usr.some@gmail.com”, to = “usr.some@gmail.com”;
final String user = “usr.some”, password = “some.usr”;
Properties props = new Properties();
props.setProperty(“mail.smtp.host”, mailHost);
props.put(“mail.smtp.auth”, “true”);
props.put(“mail.smtp.port”, ”465”);
props.put(nmail.smtp.socketFactory.classn,njavax.net.ssl.SSLSocketFactoryn);
//disable two lines above and enable one line below to use TLS
//props.put(“mail.smtp.starttls.enable”, “true”);
Session session = Session.getInstance(props, new javax.mail.Authenticator() {
}
});
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
session.setDebug(true);
try{
MimeMessage msg = new MimeMessage(session); msg.setFrom(from);
msg.addRecipients(Message.RecipientType.TO, to); msg.setSubject(”A test mail”); msg.setText(”test message”);
Transport.send(msg);
}catch (Exception e) { e.printStackTrace();
}
}
}
The added portion is shown with bold font. To view the debugging information and to understand how the message is sent, we have used the following line of code:
session.setDebug(true);
Compile and run the program as described before. A sample output of this program is shown in Figure 15.4:
The following program (SendEmailTransport.java) sends a mail from the user usr.some@ gmail.com to itself using SSL and Transport object.
//SendEmailTransport.java import java.util.*; import javax.mail.*; import javax.mail.internet.*; public class SendEmailTransport {
public static void main(String [] args) {
String host = “smtp.gmail.com”;
String from = “usr.some@gmail.com”, to = “usr.some@gmail.com”;
final String user = “usr.some”, password = “some.usr”;
Properties props = new Properties();
Session session = Session.getInstance(props); try{
MimeMessage msg = new MimeMessage(session);
msg.setFrom(from);
msg.addRecipients(Message.RecipientType.TO, to);
msg.setSubject(“A test mail”);
msg.setText(“test message”);
Transport transport = session.getTransport(“smtps”);
transport.connect(host, user, password);
transport.sendMessage( msg, msg.getAllRecipients());
transport.close();
}catch (Exception e) { e.printStackTrace();
}
}
}
Source: Uttam Kumar Roy (2015), Advanced Java programming, Oxford University Press.