CoreJava Important Tricks | Tips | Java Linux IDE | Technology Updates | Download Free CoreJava Examples | Video Tuorials | Concepts of Classes

Friday, February 6, 2009

Sending SMTP Mail With Java

Introduction : SMTP

So your Java application needs to send a notification mail? Not an uncommon scenario, but how to do it? Luckily this turns out to be pretty easy in it’s simplest form, but SMTP configuration can be the killer. You are of course dependent on being able to access a SMTP mail server and also possessing a little knowledge of the SMTP protocol.

What you need

Some years ago, Sun released the Java Mail API. It doesn’t ship along with the standard Java distribution (yet!) so you will need to download it manually. It can be found here and at the time of writing is at version 1.4.1. The Mail API depends on code from the JavaBeans Activation Framework (JAF) so you’ll need to download that package also. It can be found at this link and at the time of writing is at version 1.1.1. Make sure you add the activation.jar file from the JAF distribution to your Java classpath and you will also need both the mail.jar and smtp.jar files from the Mail API distribution to enable you to send SMTP mail.

The code

The code itself is straightforward enough, but as I said earlier, it’s the SMTP mail server configuration that can turn out to be the problem. Specially if the server is configured to not let you use it indiscriminately to avoid SPAM etc. This will depend on the company policy configuration settings of the SMTP server you are trying to connect to.

OK, here’s a simple example of how it can be done…

  1. import java.util.Date;
  2. import java.util.Properties;
  3. import javax.mail.Message;
  4. import javax.mail.MessagingException;
  5. import javax.mail.Session;
  6. import javax.mail.Transport;
  7. import javax.mail.internet.InternetAddress;
  8. import javax.mail.internet.MimeMessage;

  9. public class Main {
  10. public static void main(String[] args) {
  11. Properties props = new Properties();
  12. props.put("mail.smtp.host", "your SMTP mail server here");
  13. props.put("mail.debug", "true");

  14. Session session = Session.getInstance(props);

  15. try {
  16. Message msg = new MimeMessage(session);
  17. msg.setFrom(new InternetAddress("from@here.com"));
  18. InternetAddress[] address = {new InternetAddress("to@somewhere.com")};
  19. msg.setRecipients(Message.RecipientType.TO, address);
  20. msg.setSubject("Mail subject title");
  21. msg.setSentDate(new Date());
  22. msg.setText("Message body string");

  23. Transport.send(msg);
  24. }
  25. catch (MessagingException e) {}
  26. }
  27. }

So, to summarize, start you of by creating a Java Properties object and populating it with relevant configuration information. You need to specify the SMTP host name or IP address for the key mail.smtp.host”. The “mail.debug” property is useful for development and will give you a hint what’s going wrong should you get into trouble. Proceed on by creating a javax.mail.Session object and passing it your properties object. To create the actual mail message use a javax.mail.internet.MimeMessage object passing along the session instance you just created. Populate the javax.mail.Message object with a valid sender address and receiver address array (mail has only one sender, but can have multiple receivers). Add a mail subject, the timestamp and of course the mail message body. Then all that remains is to actually post the message to the SMTP server. That where the hard part usually begins.
So, not that difficult all in all, but remember to encapsulate the code in a try/catch block and catch the javax.mail.MessagingException exception type for it to compile. Handle errors appropriately, there is a lot that could possibly go wrong here.

SMTP server authentication

As I mentioned earlier, configuration can be the killer. These days most SMTP servers don’t let any old message pass through the system without some kind of policy checking switched on. It is likely that you will need to authenticate your application to the SMTP server when creating the session object. It is also possible that the server will attempt to validate the sender e-mail address your application is using so you need to choose it wisely since it will need to be valid in the mail domain.

To create an authenticated session object you will need to make a few minor adjustments to the code. Create a javax.mail.Authenticator subclass and override the protected method getPasswordAuthentication. By default this method returns null, so you will have to make it return an initialized javax.mail.PasswordAuthentication object containing your username and password.

You also need to tell the session object to use your new authentication class so add the property “mail.smtp.auth” to your Properties object and set its to “true”. Also change the code that creates the session object by using an overloaded version passing both your Properties object and an instance of your new Authenticator subclass. The new code should look something like this:

  1. import java.util.Date;
  2. import java.util.Properties;
  3. import javax.mail.Authenticator;
  4. import javax.mail.Message;
  5. import javax.mail.MessagingException;
  6. import javax.mail.PasswordAuthentication;
  7. import javax.mail.Session;
  8. import javax.mail.Transport;
  9. import javax.mail.internet.InternetAddress;
  10. import javax.mail.internet.MimeMessage;

  11. public class Main {
  12. public static void main(String[] args) {
  13. Properties props = new Properties();
  14. props.put("mail.smtp.host", "your SMTP mail server here");
  15. props.put("mail.smtp.auth", "true");
  16. props.put("mail.debug", "true");

  17. Session session = Session.getInstance(props, new MyAuth());

  18. try {
  19. Message msg = new MimeMessage(session);
  20. msg.setFrom(new InternetAddress("from@here.com"));
  21. InternetAddress[] address = {new InternetAddress("to@somewhere.com")};
  22. msg.setRecipients(Message.RecipientType.TO, address);
  23. msg.setSubject("");
  24. msg.setSentDate(new Date());

  25. msg.setText("Message body string");

  26. Transport.send(msg);
  27. }
  28. catch (MessagingException e) {}
  29. }
  30. }

  31. class MyAuth extends Authenticator {
  32. protected PasswordAuthentication getPasswordAuthentication() {
  33. return new PasswordAuthentication("your username","your password");
  34. }
  35. }

And that ought to do it! This code worked fine for me when testing with two separately configured Microsoft Exchange servers (ESMTP , version 6.0.3790.1830 and 6.0.3790.3959) in different mail domains as my SMTP server host, but only if clear text authentication (BASIC) was enabled on the Exchange server.

In both cases the Exchange server checked my sender address and also insisted that my application authenticate itself before allowing it to post.

No comments:

Post a Comment

Followers