Monday, January 2, 2012

Sending E-Mail From an ADF Application Deployed on WebLogic Server.

In this post, I list the steps to send e-mails (using SMTP) from an ADF application deployed on Weblogic server. I have used JavaMail API to send e-mail on the click of a button. The steps needed to send e-mail using Java Mail API are:

1. Download JavaMail API zip, and add the mail.jar as a library to your project.
2. Create a new Mail Session, and set its JNDI Name.
3. Set appropriate properties in your mail session.
4. Access the mail session using JNDI.
5. Fetch the properties set in the mail session in your code, like from-user, from-user-password etc to send the e-mail.

The following image shows the UI page used for this post to send e-mails:



After entering the To Email ID, Subject, and Mail Text, when the Send E-Mail button is clicked, the email is send from its action listener.

To create the above UI, I created a Custom Application:




And selected ADF Faces technology in the project features section of the wizard, as shown below:



Click Finish to create the Custom App with ADF Faces compatible project with default settings.
After that, add the mail.jar to the list of project libraries as shown below:



Now, create a new page, as shown below:



In the above figure, BasePageBean is the managed bean that contains the code for the "Send E-Mail" button's action listener.
Here is the code of BasePageBean class:

package project1;

import com.sun.mail.smtp.SMTPTransport;

import java.util.Date;
import java.util.Properties;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ActionEvent;

import javax.mail.Message;
import javax.mail.Session;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import oracle.adf.view.rich.component.rich.input.RichInputText;

import javax.naming.InitialContext;

public class BasePageBean {
    private RichInputText emailIdInputText;
    private RichInputText emailSubjectInputText;
    private RichInputText mailText;
   
    String emailID = null;
    String emailSubject = null;
    String emailText = null;

    public BasePageBean() {
    }

    public void setEmailIdInputText(RichInputText emailIdInputText) {
        this.emailIdInputText = emailIdInputText;
    }

    public RichInputText getEmailIdInputText() {
        return emailIdInputText;
    }

    public void setEmailSubjectInputText(RichInputText emailSubjectInputText) {
        this.emailSubjectInputText = emailSubjectInputText;
    }

    public RichInputText getEmailSubjectInputText() {
        return emailSubjectInputText;
    }

    public void sendMail(ActionEvent actionEvent) throws Exception{
        // Add event code here...
        String emailID = getEmailID();
        String subject = getEmailSubject();
        String text = getEmailText();
       
        InitialContext ic = new InitialContext();
        Session session = (Session) ic.lookup("mail/NewMailSession");

        Properties props = session.getProperties();
        System.out.println("LKAPOOR: PROPERTIES LIST: ");
        props.list(System.out);

        String  to = emailID;
        if(to==null || to.equals(""))
            to = "lalitkapoor.mailid@gmail.com";
       
        if(subject==null || subject.equals(""))
            subject = "Test Mail";

        String mailhost = props.getProperty("mail.smtp.host");
        System.out.println("LKAPOOR:: mailhost = " + mailhost);
        String user = props.getProperty("mail.smtp.user");
        System.out.println("LKAPOOR:: user = " + user);
        String password = props.getProperty("mail.smtp.password");
        System.out.println("LKAPOOR:: password = " + password);
        String protocol = props.getProperty("mail.transport.protocol");
        System.out.println("LKAPOOR:: protocol = " + protocol);
       
        String authorization = props.getProperty("mail.smtps.auth");
        String mailDisabled = props.getProperty("mail.disable");
        String verboseProp = props.getProperty("mail.verbose");
        String debugProp = props.getProperty("mail.debug");
       
        boolean sentDisabled = false;
        if(mailDisabled.equals("true"))
            sentDisabled = true;
       
        if(!sentDisabled){
           
            boolean auth = false;
            if(authorization.equals("true"))
                auth = true;
           
            boolean verbose = false;
            if(verboseProp.equals("true"))
                verbose = true;
   
            String mailer = "smtpsend";
           
            if(debugProp.equals("true"))
                session.setDebug(true);
            else
                session.setDebug(false);
   
            System.out.println("LKAPOOR: session initialized.");
                 
            Message msg = new MimeMessage(session);
           
            msg.setFrom();      
           
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false));
           
            System.out.println("LKAPOOR: recipient set.");
           
            msg.setSubject(subject);
            msg.setText(text);
   
            msg.setHeader("X-Mailer", mailer);
            msg.setSentDate(new Date());
   
            System.out.println("LKAPOOR: Metadata set.");
   
            SMTPTransport t = (SMTPTransport)session.getTransport(protocol);
   
            System.out.println("LKAPOOR: Gettting Transport.");
   
            try {
                System.out.println("LKAPOOR: Before connect via authorization.");
                t.connect(mailhost, user, password);
                t.sendMessage(msg, msg.getAllRecipients());
                System.out.println("LKAPOOR: message sent.");
            } finally {
                    if (verbose)
                        System.out.println("Response: " + t.getLastServerResponse());
                    t.close();
            }
           
            System.out.println("\nMail was sent successfully.");
        }else{
            System.out.println("Mail Sending is disabled.");
        }
       
    }

    public void setMailText(RichInputText mailText) {
        this.mailText = mailText;
    }

    public RichInputText getMailText() {
        return mailText;
    }

    public void setEmailID(String emailID) {
        this.emailID = emailID;
    }

    public String getEmailID() {
        return emailID;
    }

    public void setEmailSubject(String emailSubject) {
        this.emailSubject = emailSubject;
    }

    public String getEmailSubject() {
        return emailSubject;
    }

    public void setEmailText(String emailText) {
        this.emailText = emailText;
    }

    public String getEmailText() {
        return emailText;
    }
}

The sendMail() action listener accesses the Mail Session using the JNDI URL "mail/NewMailSession".
To access this session, we need to configure a Mail Session on our WebLogic server.
To configure the Mail Session, open the WLS Home page, and click the Mail Session link:



The "Summary of Mail Sessions" page comes up. Click New to create a new Mail Session, and enter the following details:



As shown above, the action listener using the same string as JNDI URL which is entered as JNDI Name for the mail session.
Using this Mail Session, we can access the properties entered in the JavaMail Properties section in our action listener. I have entered the following properties to send an email using SMTP protocol:

mail.smtp.auth=true
mail.debug=true
mail.smtp.host=smtp.gmail.com
mail.smtp.user=lalitkapoor.mailid@gmail.com
mail.smtp.password=XXXXXXX ;)
mail.transport.protocol=smtp
mail.smtp.port=465
mail.disable=false
mail.verbose=true
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

So, basically, I am sending an email to myself in this example.
Click Save to deploy the changes, and run the application.
After entering the details, when you click the 'Send E-Mail' button, the e-mail is send, and here is how that mail looks like:



That's it.
When the provider doesn't support SSL for SMTP connections, like in my case, then we will hit the following error:

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?

To avoid this, remove "mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory" property from mail session and it will work fine.

Reference:
http://www.coderanch.com/t/443237/java/java/JavaMail-security

17 comments:

  1. Thank you very much for your precious blog
    How to I configure as well as sent to multiple email receiver.

    usermail.smtp.user=lalitkapoor.mailid@gmail.com

    Regards
    KT

    ReplyDelete
  2. You can try to pass multiple email ids as string using the property specified above in the mail session, and break them into tokens and add them in the TO list.

    ReplyDelete
  3. I have tried these tutorial well, but It doesn't work.
    I made action listener sendMail()for button send E-Mail(cb1).

    This is the error:
    Received 'java.lang.NullPointerException' when invoking action listener '#{backingBeanScope.backing_index.sendMail}' for component 'cb1'
    java.lang.NullPointerException

    Do you have any solution?

    ReplyDelete
    Replies
    1. String authorization = props.getProperty("mail.smtps.auth"); in the bean should match with mail.smtp.auth=true in the properties list

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Hi Lalit,

    Thanks alot for your post ... i have tried it, but still get problem with the following error :

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    do you have any ideas to fix it ?

    ReplyDelete
  6. For multiple receivers, we can create a mailing list and use that list in the To list. That mailing list can have as many IDs as you want

    ReplyDelete
  7. I get the error: Unreported exception javax.naming.NamingException; must be caught or declared to be thrown for "InitialContext ic = new InitialContext()".

    Please advice.

    ReplyDelete
  8. I'm getting an error when hitting the send email button,
    here's what i get:
    javax.el.ELException: //C:/Users/WSI-Trainee17_2/AppData/Roaming/JDeveloper/system11.1.2.3.39.62.76.1/o.j2ee/drs/JavaMailv2/ViewControllerWebApp.war/mailGUI.jsf @38,94 actionListener="#{beanMail.sendMail}": java.lang.NullPointerException

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. Hi
    Can any one Please send the step by step procedure for this Email application. I am new to ADF.

    ReplyDelete
  11. Is there a way to provide a hyper link in that email ? On click of it the Application should capture back the acknowledgement ?

    ReplyDelete
  12. HI,

    I followed evertyhinh in thi8s tutorial. I am getting following error:

    DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
    Response: null

    <_logUnhandledException>
    javax.faces.el.EvaluationException: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 587; timeout -1;
    nested exception is:
    java.net.ConnectException: Connection refused: connect

    Someone please suggest solution.

    ReplyDelete
    Replies
    1. I also tried with port : 465

      when connected as 465 also it is throwing the same error.

      Delete
  13. Hi
    i followed the all toturial steps
    and i get this error ?

    While trying to lookup 'mail.NewMailSession' didn't find subcontext 'mail'. Resolved ''; remaining name 'mail/NewMailSession'


    ?

    ReplyDelete