How to send E-mail notification in Java using Gmail SMTP Server and JavaMail API


Few days back, for my personal project I wanted to send email notifications through my Java Application, then when I searched over net for SMTP server setup, I found out we can use gmail's SMTP server for free, we just need to have a gmail account and that's it. So worked out the code, initially I faced few issues, which I will briefly mention and how to solve them as well.


Pre-requisites for using JavaMail API :-
You need to have following files placed in your jdk/jre/lib directory, e.g. C:/Program Files/Java/jdk1.6.2/jre/lib.
Note - Create plain text files and rename them (their extensions too) with following 4 file names.




1) javamail.address.map - 
rfc822=smtp
news=nntp


2) javamail.default.address.map - 
rfc822=smtp


3) javamail.default.providers - 
# JavaMail IMAP provider Sun Microsystems, Inc
protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Sun Microsystems, Inc;
protocol=imaps; type=store; class=com.sun.mail.imap.IMAPSSLStore; vendor=Sun Microsystems, Inc;
# JavaMail SMTP provider Sun Microsystems, Inc
protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Sun Microsystems, Inc;
protocol=smtps; type=transport; class=com.sun.mail.smtp.SMTPSSLTransport; vendor=Sun Microsystems, Inc;
# JavaMail POP3 provider Sun Microsystems, Inc
protocol=pop3; type=store; class=com.sun.mail.pop3.POP3Store; vendor=Sun Microsystems, Inc;
protocol=pop3s; type=store; class=com.sun.mail.pop3.POP3SSLStore; vendor=Sun Microsystems, Inc;


4) javamail.providers - 
# JavaMail IMAP provider Sun Microsystems, Inc
protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Sun Microsystems, Inc;
protocol=imaps; type=store; class=com.sun.mail.imap.IMAPSSLStore; vendor=Sun Microsystems, Inc;
# JavaMail SMTP provider Sun Microsystems, Inc
protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Sun Microsystems, Inc;
protocol=smtps; type=transport; class=com.sun.mail.smtp.SMTPSSLTransport; vendor=Sun Microsystems, Inc;
# JavaMail POP3 provider Sun Microsystems, Inc
protocol=pop3; type=store; class=com.sun.mail.pop3.POP3Store; vendor=Sun Microsystems, Inc;
protocol=pop3s; type=store; class=com.sun.mail.pop3.POP3SSLStore; vendor=Sun Microsystems, Inc;


Then, download JavaMail API jars from Oracle's Official website -
1) http://www.oracle.com/technetwork/java/javamail/index-138643.html
2) http://java.sun.com/products/javabeans/jaf/index.jsp
3) http://mirrors.ibiblio.org/pub/mirrors/maven2/javax/activation/activation/1.1/activation-1.1.jar




You need to have - mail.jar (which is contained in javamail1_4_4.zip) and activation.jarjavamail-smtp-1.4.2.jar OR j2ee.jar then include them in your project classpath.




Here is screen-shot of my project -


Here is Java Source-Code - (Make sure you put valid Gmail username and password before you run this code.)
package logicPro.email;

/**
 By Pramod Khare
 Purpose - To send email using javamail API with gmail smtp server. 
 Code is taken as is from one the below websites. and its a generic one.
 can be modified as per one's need.
 Helpful Links - 
 http://www.javaworkspace.com/javaMail.do
 http://stackoverflow.com/questions/6081270/mail-sending-problem
 http://stackoverflow.com/questions/8672963/get-errors-with-javamail

*/
import java.security.Security;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class HowToSendEmailJAVA {
 private static final String SMTP_HOST_NAME = "smtp.gmail.com";
 private static final String SMTP_PORT = "465";
 private static final String emailMsgTxt = "Test Message Contents";
 private static final String emailSubjectTxt = "A test from gmail";
 private static final String emailFromAddress = "abc@gmail.com";
 private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
 private static final String[] sendTo = {"abc@gmail.com"};

 public static void main(String args[]) throws Exception {

  Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

  new HowToSendEmailJAVA().sendSSLMessage(sendTo, emailSubjectTxt, emailMsgTxt,emailFromAddress);
  System.out.println("Sucessfully Sent mail to All Users");
 }

 public void sendSSLMessage(String recipients[], String subject, String message, String from) throws MessagingException {
  //boolean debug = true;

  Properties props = new Properties();
  props.put("mail.smtp.host", SMTP_HOST_NAME);
  props.put("mail.smtp.auth", "true");
  props.put("mail.debug", "true");
  props.put("mail.smtp.port", SMTP_PORT);
  props.put("mail.smtp.socketFactory.port", SMTP_PORT);
  props.put("mail.smtp.socketFactory.class", SSL_FACTORY);
  props.put("mail.smtp.socketFactory.fallback", "false");

  Session session = Session.getDefaultInstance(props,
    new javax.mail.Authenticator() {
     protected PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication("abc@gmail.com", "password");
     }
    });

  session.setDebug(debug);

  Message msg = new MimeMessage(session);
  InternetAddress addressFrom = new InternetAddress(from);
  msg.setFrom(addressFrom);

  InternetAddress[] addressTo = new InternetAddress[recipients.length];
  for (int i = 0; i < recipients.length; i++) {
   addressTo[i] = new InternetAddress(recipients[i]);
  }
  msg.setRecipients(Message.RecipientType.TO, addressTo);

  // Setting the Subject and Content Type
  msg.setSubject(subject);
  msg.setContent(message, "text/plain");
  Transport.send(msg);
 }
}


Now here are few exception/ difficulties which I faced while working out above example - 


1) First make sure your ISP has not blocked access to smtp.gmail.com, try to ping to "smtp.gmail.com" e.g. run command - "ping smtp.gmail.com"


In case there is no response, make sure your firewall isn't blocking it.
For proper situation, your ping will be successful - 


***************************************************************************** 

2) While executing the above code if you get - 



DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at javax.mail.Session.getService(Session.java:607)
at javax.mail.Session.getTransport(Session.java:541)
at javax.mail.Session.getTransport(Session.java:484)
at javax.mail.Session.getTransport(Session.java:464)
at javax.mail.Session.getTransport(Session.java:519)
at javax.mail.Transport.send0(Transport.java:155)
at javax.mail.Transport.send(Transport.java:81)
at logicPro.email.HowToSendEmailJAVA.sendSSLMessage(HowToSendEmailJAVA.java:75)
at logicPro.email.HowToSendEmailJAVA.main(HowToSendEmailJAVA.java:38)
Caused by: java.lang.NoSuchMethodError: javax.mail.Session.getDebugOut()Ljava/io/PrintStream;
at com.sun.mail.smtp.SMTPTransport.<init>(SMTPTransport.java:93)
at com.sun.mail.smtp.SMTPTransport.<init>(SMTPTransport.java:78)
... 13 more


Solution - Possible reason duplicate classes in included jars. 
If you have included j2ee.jar then it already contains, JavaMail API Classes, you donot need to have javamail-smtp-1.4.2.jar. (Include either of them), And make sure their order is last in included jars.


***************************************************************************** 

3) If you get any warnings regarding unable to read files javamail.providers, javamail.default.address.map like ...



DEBUG: JavaMail version 1.3.3
DEBUG: java.io.FileNotFoundException: C:\Program Files\Java\jdk1.6.0\jre\lib\javamail.providers (The system cannot find the file specified)
DEBUG: !anyLoaded
DEBUG: not loading resource: /META-INF/javamail.providers
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: !anyLoaded
DEBUG: not loading resource: /META-INF/javamail.address.map
DEBUG: java.io.FileNotFoundException: C:\Program Files\Java\jdk1.6.0\jre\lib\javamail.address.map (The system cannot find the file specified)
DEBUG: setDebug: JavaMail version 1.3.3
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
DEBUG SMTP: useEhlo true, useAuth true



Solution - You have not included javamail.providers, javamail.address.map, javamail.default.address.map, javamail.default.providers, in jdk/jre/lib directory.
Please find above screen-shot about these files and where they should be included.


***************************************************************************** 

4) Exception - 

com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first.


at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1333)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:906)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:535)
at javax.mail.Transport.send0(Transport.java:151)
at javax.mail.Transport.send(Transport.java:80)
at logicPro.email.HowToSendEmailJAVA.sendSSLMessage(HowToSendEmailJAVA.java:75)
at logicPro.email.HowToSendEmailJAVA.main(HowToSendEmailJAVA.java:38)
QUIT
Exception in thread "main" com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first.


at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1333)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:906)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:535)
at javax.mail.Transport.send0(Transport.java:151)
at javax.mail.Transport.send(Transport.java:80)
at logicPro.email.HowToSendEmailJAVA.sendSSLMessage(HowToSendEmailJAVA.java:75)
at logicPro.email.HowToSendEmailJAVA.main(HowToSendEmailJAVA.java:38)...



Solution - Make sure you are setting following config values -

                props.put("mail.smtp.port", SMTP_PORT);
                props.put("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.port", SMTP_PORT);
props.put("mail.smtp.socketFactory.class", SSL_FACTORY);
props.put("mail.smtp.socketFactory.fallback", "false");



*****************************************************************************
5) Exception - 



DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 25, isSSL false
DEBUG SMTP: exception reading response: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
Exception in thread "main" javax.mail.MessagingException: Exception reading response;
  nested exception is:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:1407)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1205)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:322)
at javax.mail.Service.connect(Service.java:258)
at javax.mail.Service.connect(Service.java:137)
at javax.mail.Service.connect(Service.java:86)
at javax.mail.Transport.send0(Transport.java:150)
at javax.mail.Transport.send(Transport.java:80)



Solution - Make sure you have set following values - 

       props.put("mail.smtp.port", SMTP_PORT);
       props.put("mail.smtp.socketFactory.port", SMTP_PORT);



*****************************************************************************
6) Exception - 

535-5.7.1 Application-specific password required. Learn more at
535 5.7.1 http://support.google.com/accounts/bin/answer.py?answer=185833 r9sm11984511pbi.53
Exception in thread "main" javax.mail.AuthenticationFailedException
at javax.mail.Service.connect(Service.java:267)
at javax.mail.Service.connect(Service.java:137)
at javax.mail.Service.connect(Service.java:86)
at javax.mail.Transport.send0(Transport.java:150)
at javax.mail.Transport.send(Transport.java:80)



Solution - Probably you have set 2-step verification ON, then in that case you need to generate Application specific password from given link - http://support.google.com/accounts/bin/answer.py?answer=185833 and it will be your second password put through application.


OR disable 2-step verification and try, will work.
*****************************************************************************
I had many problems initially but finally it started working...Hard-work always thrives... 


Reference Links -
http://www.javaworkspace.com/javaMail.do
http://stackoverflow.com/questions/6081270/mail-sending-problem
http://stackoverflow.com/questions/8672963/get-errors-with-javamail

Comments

Popular posts from this blog

How to install / Configure Mantis For Apache-PHP-PostgreSQL combination

Modified ExtJS LOVCombo (List of Values) ux plugin - with select all, deselect all, text filter, bubble up and bubble down of selection

TriggerField with two triggers, TwinTriggerField with tooltips