10h. Advanced WebDriver – Sending email with attachments

Hiya champs! Now that we have our JUnit report in PDF format let us attach it with an email and send it across to various project stakeholders. So, today we are mostly going to work with just Java. Grab a cup of coffee (Java) you all!

We will be looking at two classes.

  1. SendMail.java – This class has all the code for sending out an email.
  2. InvokeMail.java – Invokes SendMail.java by providing from address, to address, subject line and some text.

Code

SendMail.java

package com.blog.utility;

import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/*
 * This class has the main code for sending mail
 */
public class SendMail {

  public static void send(String from, String tos[], String subject,
      String text) throws MessagingException {
    // Get the session object
    Properties props = new Properties();
    props.put("mail.smtp.host", "smtp.gmail.com");
    props.put("mail.smtp.socketFactory.port", "465");
    props.put("mail.smtp.socketFactory.class",
        "javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.port", "465");

    Session session = Session.getDefaultInstance(props,
        new javax.mail.Authenticator() {
          protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(
            "[email protected]",
            "pass1234");// change accordingly
          }
        });

    // compose message
    try {
      MimeMessage message = new MimeMessage(session);
      message.setFrom(new InternetAddress(from));// change accordingly
      for (String to : tos) {
        message.addRecipient(Message.RecipientType.TO,
            new InternetAddress(to));
      }
      /*
       * for (String cc : ccs)
       * message.addRecipient(Message.RecipientType.CC,new
       * InternetAddress(cc));
       */
      message.setSubject(subject);
      // Option 1: To send normal text message
      // message.setText(text);
      // Option 2: Send the actual HTML message, as big as you like
      // message.setContent("<h1>This is actual message</h1></br></hr>" +
      // text, "text/html");

      // Set the attachment path
      String filename = "E:\\Selenium\\junit.pdf";

      BodyPart objMessageBodyPart = new MimeBodyPart();
      // Option 3: Send text along with attachment
      objMessageBodyPart.setContent(
          "<h1>Mail from Selenium Project!</h1></br>" + text, "text/html");
      Multipart multipart = new MimeMultipart();
      multipart.addBodyPart(objMessageBodyPart);

      objMessageBodyPart = new MimeBodyPart();
      DataSource source = new FileDataSource(filename);
      objMessageBodyPart.setDataHandler(new DataHandler(source));
      objMessageBodyPart.setFileName(filename);
      multipart.addBodyPart(objMessageBodyPart);
      message.setContent(multipart);

      // send message
      Transport.send(message);

      System.out.println("message sent successfully");

    } catch (MessagingException e) {
      throw new RuntimeException(e);
    }
  }// End of SEND method
}

InvokeMail.java

package com.blog.junitTests;

import javax.mail.MessagingException;
import com.blog.utility.SendMail;

/*
 * Invokes SendMail.java 
 */
public class InvokeMail {
  public static void main(String[] args) throws MessagingException {
    
    //String to[] = {"[email protected]","[email protected]"};
    String to[] = {"[email protected]"};
    
    SendMail.send("[email protected]", to, "JUnit Report", "Check the PDF attachment.");		

  }
}

Explanation

Looking directly at the code makes us feel as if it is tough to wrap our heads around. Let us understand one snippet at a time.

As always, our first step is to download a couple of JARs.

  1. activation.jar
  2. javax.mail-1.6.1.jar

I have placed both these in our GitHub repo as well, along with all other code files dealt as part of this post.

Add these JARs to our project build path. We have seen this procedure numerous times before and hence I am not re-iterating it (Refer to Step 3 of this article for a detailed explanation).

Understanding SendMail.java,

1.The method inside which all the code is written so that we can invoke it easily from any class.

public static void send(String from, String tos[], String subject,
      String text) throws MessagingException {}

2. Given properties will work only for Gmail. In case you are using Outlook or any other service as per your project requirements, then these should be changed accordingly.

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class",
  "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");

3. Get the session object and pass your email account’s credentials (for the one which you mention in from address).

Session session = Session.getDefaultInstance(props,
        new javax.mail.Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
  return new PasswordAuthentication("[email protected]","pass1234");// change accordingly
    }
});

4. Now is the interesting part. We will specify the “from” and “to” address.

message.setFrom(new InternetAddress(from));
for (String to : tos) {
    message.addRecipient(Message.RecipientType.TO,
    new InternetAddress(to));
  }

If you wish to send this email to just one person, then change the code as below,

message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
    new InternetAddress(to));

If you wish to send it to some people in cc (carbon copy), then change the code as below,

message.addRecipient(Message.RecipientType.CC,new InternetAddress(cc));

5. Set the subject line as,  message.setSubject(subject);

6. To send,

  • A normal text message, message.setText(text);
  • The actual HTML message, as big as you like,  message.setContent("<h1>This is actual message</h1></br></hr>" + text, "text/html");
  • The text and an attachment (that’s what we are looking for),
// Set the attachment path
String filename = "E:\\Selenium\\junit.pdf";
BodyPart objMessageBodyPart = new MimeBodyPart();
objMessageBodyPart.setContent("<h1>Mail from Selenium Project!</h1></br>" + text, "text/html");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(objMessageBodyPart);
objMessageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
objMessageBodyPart.setDataHandler(new DataHandler(source));
objMessageBodyPart.setFileName(filename);
multipart.addBodyPart(objMessageBodyPart);
message.setContent(multipart);

7. Send the email with one simple line,

Transport.send(message);

Understanding InvokeMail.java,

This class is very simple to understand as we are just calling the ‘send’ method from SendMail.java by providing all required arguments.

String to[] = {"[email protected]"};
SendMail.send("[email protected]", to, "JUnit Report", "Check the PDF attachment.");

When “Run as -> Java application”, Eclipse IDE console output is as below,

Email eclipse console output

The email will be received in the recipient’s inbox.

Email received in Inbox

Generated email with attachment is shown for your reference.

Generated email

Sticky Note: Beware! You might bump into “javax.mail.AuthenticationFailedException”. This exception mostly occurs due to the security and protection features provided by Google. An easy workaround is to Turn ON the access to “Allow less secure apps” for testing purposes by clicking on the link, “https://www.google.com/settings/security/lesssecureapps”.

Give this a shot and let me know if you face any issues in shooting your emails.

Happy experimenting! Have a nice day!

2 Comments 10h. Advanced WebDriver – Sending email with attachments

  1. viky

    Any workaround possible for multi-layer Authentication in outlook ? after login we get a OTP to be used for login.

    Reply
    1. Chandana Chaitanya

      Hi Viky,

      That’s a very good question. To be a 100% honest, I am not really sure if Selenium can help you here. You might have to think of other workarounds.
      1. Try using Twilio to register the mobile number that is connected to the Outlook account and get the OTP from there or,
      2. Check if you can use “messages for web
      3. Check out this link and see if anything works out for you.

      Once you are able to retrieve the OTP either using Twilio API or the messages API etc., it will be very easy to enter the same using Selenium’s sendKeys() method and continue with the login process automation from there.

      Thanks.

      Reply

Leave A Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.