Site icon Mailtrap

Email testing with Selenium WebDriver on a Cloud-Based Selenium Grid

The email marketing team has come up with an exceptional email campaign and believes that it would do wonders for the product! Kudos to their hard work! However, things might not work as they planned …

The harsh reality is that executing a picture-perfect email strategy goes far beyond eye-catching design and elegant language used in the email. Much of the success of your campaigns depends on how emails are rendered for your recipients and how fast you’re able to fix any emerging issues.

In this tutorial, we’ll talk about testing HTML emails for different combinations of clients, systems, and devices. For that purpose, we’ll use Mailtrap and the Cloud-based automated testing platform, LambdaTest.

Why you should validate your emails with cross-browser testing

Testing the emails is an important part of the customer onboarding (or signup) process, customer retention process, and email marketing campaigns. Apart from ensuring that emails have no typing mistakes, it is essential to check whether the HTML email renders properly on different clients and devices.

A comprehensive email testing process answers the following questions:

The process should also look into many other factors. After all, there’s a multitude of things that could influence email rendering for your recipients:

Email Service Providers (ESP)


Your ESP could be altering the code of your email templates. Why? They may do it to add tracking pixels, remove code that might land your email in its Spam filters, or rewrite the links in the email.

The ESP performs these steps for minimizing any deliverability issues with the email campaign. However, these positive steps could impact the way email is rendered on the recipient’s browser and machine.

The abundance of browsers and clients


Different browsers and clients render email in different ways, and the styling is not limited to iFrames. The web email client’s interface that is shared with the web browser is equipped with a lot of embedded styles, container elements, and client-side scripts that are built for displaying banner images or cropping out a portion of the email body with a message like “[Message Clipped] View the entire message”.

The look and feel of your HTML email can change depending on the email client and browser used for accessing the email. It is highly recommended to test the HTML email against the web browsers most frequently used by the target audience.

Blocked and Unblocked Images


Many web-based email clients and web browsers, when used for accessing email, block images by default. However, the email service provider provides a mechanism to change the settings so that images in the emails are loaded by default.

Many providers also provide options where the email recipient is asked before showing the images – a trick that comes in handy when emails are accessed under scenarios where the mobile network is throttling.

It is recommended that these image-related settings are tested in different browser and version combinations, so that you are doubly confident no additional settings have to be modified in the web browser.

Interactive/Dynamic Emails


As part of the overall email strategy, your team might be investing heavily on incorporating interactivity and dynamic content in the emails. This should come as no surprise, as interactivity is one of the key emerging trends in email marketing. It can be very beneficial, but requires rigorous testing before sending to the first recipients.

Email clients may alter how HTML and the CSS of HTML emails is rendered. These alterations could impact the deliverability of the emails, and have to be tested on different browser/version combinations to ensure the correct results.

Internationalization testing of the emails


Internationalization is the technique of formatting and preparation of emails, to tailor them for different languages, regions, and locales across the globe. For example, the display order of the fields in a postal address might differ from one language to another.  In the Japanese language, the default ‘address order’ is postal code, state, city, and name, whereas the order for the English language is name, city, state & postal code.

Emails sent to a diverse audience should be tested on different browser/version combinations to verify whether the font is easy to read and consistent, links are in the correct places, email content is being rendered properly on the web browser (L-R or R-L), and a CTA (Call to Action) is accessible to all.

HTML Email Testing with Online Selenium Grid


Selenium is a popular test automation framework that is widely used for cross-browser testing. It supports popular programming languages such as Java, Python, C#, PHP, and JavaScript. When it comes to testing the HTML email on different browsers and platforms, you have the choice of an ‘in-house’ or a ‘cloud-based’ Selenium Grid.

The next million dollar question is – Which Selenium Grid setup should be chosen for HTML email testing?  Well, if you had to test against a select set of browsers and versions, one should go for a local Selenium Grid. However, the IT and Infra team would have to shoulder the responsibility of keeping the infrastructure constantly up and running! Continuous maintenance of the in-house Selenium Grid infrastructure requires recursive investments, unfortunately.

All in all, investing in a local Selenium infrastructure can turn out to be a costly and non-scalable approach.

The best solution?  Performing cross-browser testing of the HTML email using a secure, scalable, and reliable cloud-based Selenium Grid, such as LambdaTest. Here are some of the major advantages of leveraging the cloud-based Selenium Grid for cross-browser testing:


Case Scenario – HTML Email Testing with Online Selenium Grid


To demonstrate the HTML email testing provided by LambdaTest, we consider two test scenarios:

The tests are conducted on the LambdaTest Selenium Grid. For using LambdaTest, we signed up for an account on the platform and generated the desired browser capabilities using the LambdaTest Capabilities Generator. For accessing the Grid, we made a note of the user name and password from the LambdaTest profile page. The automation dashboard will have the details of the tests run on the Selenium Grid.

Prerequisites


Here are the resources that we need for the project:

The web browser executables are not required to be installed on the host machine, as the tests are run on the cloud-based Selenium Grid. 

Setting Up The Project


To get started with the tests, we first create a new Java project (of type Maven) in IntelliJ IDEA IDE. Go to File 🡪 New Project to create the project in IntelliJ. Set the GroupID as org.lt.mailtrap and artifactID as lt.mailtrap.

We then create a new package named “org.lt.mailtrap” under the folder “testjava”. Under the package, create two class files – “Mailtrap_http_usecase” and “Mailtrap_send_email_usecase”. A class file named Helper is created under the same package. We will implement the method for reading the ‘confirmation key’ or OTP from the email content or URL submitted to the method.

The required project dependencies are added in pom.xml. As the TestNG framework is used for test implementation and execution, we create a file named testng.xml where we include the test methods for execution. Here is the overall project structure:

FileName – pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.lt.mailtrap</groupId>
    <artifactId>lt.mailtrap</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.9.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.0.0-alpha-7</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
            <version>4.0.0-alpha-7</version>
        </dependency>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.28</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.typesafe.play</groupId>
            <artifactId>play-mailer_2.13</artifactId>
            <version>8.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.activation</groupId>
            <artifactId>javax.activation</artifactId>
            <version>1.2.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>install</defaultGoal>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.4</version>
                <configuration>
                    <suiteXmlFiles>
                        <!-- TestNG suite XML files -->
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
                <version>3.0.0-M5</version>
            </plugin>
        </plugins>
    </build>
</project>

FileName – testng.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Mailtrap with LambdaTest" parallel="tests" thread-count="5">
    <test name="Sending HTTP email from Mailtrap to other email address [Chrome]">
        <parameter name="browser" value="Chrome"/>
        <parameter name="version" value="latest"/>
        <parameter name="platform" value="Windows 10"/>
        <parameter name="resolution" value="1600x1200"/>
        <classes>
            <class name="org.lt.mailtrap.Mailtrap_http_usecase"/>
        </classes>
    </test>

    <test name="Testing email from Mailtrap (with infra from LambdaTest)">
        <parameter name="browser" value="Chrome"/>
        <parameter name="version" value="latest"/>
        <parameter name="platform" value="Windows 10"/>
        <parameter name="resolution" value="1600x1200"/>
        <classes>
            <class name="org.lt.mailtrap.Mailtrap_send_email_usecase"/>
        </classes>
    </test>
</suite>

In both the test scenarios (i.e. testing HTTP Emails with Mailtrap and Cloud-based Selenium Grid, and testing SMTP settings of Mailtrap for HTML email testing on the cloud-based Selenium Grid), we would read the PIN (sent by LambdaTest) to our Mailtrap email address.

Now we create a Helper function named ReadOtpFromEmail that takes two input arguments – the Selenium WebDriver instance, and the URL from where the mail must be read. The helper function ReadOtpFromEmail is implemented in Helper.java.

To get started, we import the necessary packages we need for the implementation:

We will look at the core logic in the Helper.java file, which contains the implementation for reading the OTP (or confirmation key) from the Mailtrap mailbox.

FileName – Helper.java

package org.lt.mailtrap;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import static org.openqa.selenium.support.locators.RelativeLocator.withTagName;
import java.net.MalformedURLException;
public class Helper {
    public String ReadOtpFromEmail (WebDriver driver, String new_url) throws InterruptedException {
        /* Opens a new window and switches to new window */
        driver.switchTo().newWindow(WindowType.WINDOW);
        driver.navigate().to(new_url);
        driver.manage().window().maximize();
        WebElement elem_mailtrap_email = driver.findElement(By.xpath("//input[@id='user_email']"));
        elem_mailtrap_email.sendKeys("himanshu.sheth@gmail.com");
        WebElement elem_mailtrap_password = driver.findElement(By.cssSelector("#user_password"));
        elem_mailtrap_password.sendKeys("Password");
        WebElement elem_commit_button = driver.findElement(By.xpath("//input[@name='commit']"));
        elem_commit_button.click();
        Thread.sleep(2000);
        /* Click on the demo inbox */
        driver.findElement(By.xpath("//strong[@class='inbox_name']")).click();
        Thread.sleep(1000);
        /* Since we clean up the mailbox after every test, it is expected that the mail box will have only one email */
        WebElement elem_email_message = driver.findElement(By.xpath("//*[contains(text(), 'Verify your Email Address - LambdaTest')]"));
        elem_email_message.click();
        Thread.sleep(2000);
        /* Switch to the iFrame that contains the email message */
        driver.switchTo().frame(driver.findElement(By.className("i6jjn6")));
        System.out.println("***** Switched to the iFrame *****");
        WebElement elem_vemail_address = driver.findElement(By.xpath("//a[.='Verify Email Address']"));
        /* Print the PIN Number */
        WebElement elem_pin_number = driver.findElement(withTagName("p").above(elem_vemail_address));
        String str_pin_number = elem_pin_number.getText();
        System.out.println("The Pin sentence is " + str_pin_number);
        /* Extract the PIN number from the complete string */
        String str_extracted_pin_number = str_pin_number.substring(13);
        System.out.println(str_extracted_pin_number);
        /* Clean the mailbox since all the operations are complete */
        driver.switchTo().parentFrame();
        Thread.sleep(1000);
        WebElement elem_clean = driver.findElement(By.cssSelector(".i4w4pc3--clear-inbox > use"));
        Actions actions = new Actions(driver);
        /* Use the new actions API in Selenium 4 */
        actions.click(elem_clean).build().perform();
        Thread.sleep(2000);
        driver.switchTo().alert().accept();
        driver.close();
        /* This will return the PIN Number */
        /* Hence forth we perfom actions on the parent window */
        return str_extracted_pin_number;
    }
}

Code Walkthrough


After importing the necessary packages, we create an instance of Remote WebDriver with the desired browser and OS combination on which the test needs to be performed.

In Helper.java, we open a new window in which we perform the following operations:

When the ReadOtpFromEmail method is called with the input URL and instance of Selenium WebDriver, one browser window will already be open. Hence, we open a new Window and switch to the newly opened window using switchTo().newWindow(WindowType.WINDOW) method. newWindow() is only available in Selenium 4 for Java.

driver.switchTo().newWindow(WindowType.WINDOW);
driver.navigate().to(new_url);
driver.manage().window().maximize();

The new_url argument that is passed to the method is /signin where we would sign in to Mailtrap inbox using the username and password combination.

The findElement method in Selenium is used for locating the element where we need to enter the username. The email address we will sign in to Mailtrap with is sent to the searched element using the sendKeys method.

WebElement elem_mailtrap_email = driver.findElement(By.xpath("//input[@id='user_email']"));
elem_mailtrap_email.sendKeys("email@gmail.com");

We enter the password in the element, which is located using the CSS Selector property (#user_password).

WebElement elem_mailtrap_password = driver.findElement(By.cssSelector("#user_password"));
elem_mailtrap_password.sendKeys("Password");

Now that we have entered the username and password, a click operation is performed on the login button, which is located using the XPath property.


WebElement elem_commit_button = driver.findElement(By.xpath("//input[@name='commit']"));
elem_commit_button.click();

Once the login is successful, we open the “Demo Inbox” by clicking on the element with XPath “//strong[@class=’inbox_name’]”.

/* Click on the demo inbox */
driver.findElement(By.xpath("//strong[@class='inbox_name']")).click();
Thread.sleep(1000);


There should be only one mail in the mailbox since we clean the mailbox after every test. We locate the email that contains the PIN number sent by LambdaTest using the XPath locator.
Once the message is located, we open the email using the click() method in Selenium.

WebElement elem_email_message = driver.findElement(By.xpath("//*[contains(text(), 'Verify your Email Address - LambdaTest')]"));
elem_email_message.click();

As the email body is located in a different iFrame, we find the desired iFrame using the className property. Once the iFrame is located, we switch to that iFrame using the switchTo().frame(frame-name) method.

/* Switch to the iFrame that contains the email message */
driver.switchTo().frame(driver.findElement(By.className("i6jjn6")));

Inside the iFrame, we locate the WebElement, which is a “Verify Email Address” button using the XPath property.

WebElement elem_vemail_address = driver.findElement(By.xpath("//a[.='Verify Email Address']"));

The withTagName method (with Tag ‘p’) and relative locator ‘above’, which is only available in Selenium 4, is used for locating the ‘string sentence that contains the PIN number’ relative to the WebElement elem_vemail_address that was located in the previous step.


WebElement elem_pin_number = driver.findElement(withTagName("p").above(elem_vemail_address));
String str_pin_number = elem_pin_number.getText();
System.out.println("The Pin sentence is " + str_pin_number);

Now that we have the entire string that contains the PIN number, we extract a substring of the String to get the PIN Number. At the completion of this step, we will have the PIN number from the email that was sent by LambdaTest.

/* Extract the PIN number from the complete string */
String str_extracted_pin_number = str_pin_number.substring(13);
System.out.println(str_extracted_pin_number);

Using the switchTo().parentFrame() method, we switch back to the Parent frame.

driver.switchTo().parentFrame();

In the Parent frame, we locate the ‘Clean MailBox’ icon using the cssSelector property.


WebElement elem_clean = driver.findElement(By.cssSelector(".i4w4pc3--clear-inbox > use"));

Using the ActionChains API in Selenium, we execute the click() and perform() actions on the WebElement located in Step 13.

Actions actions = new Actions(driver);
/* Use the new actions API in Selenium 4 */
actions.click(elem_clean).build().perform();

When the Element is clicked, an Alert box appears where we switch to the alert and then accept the alert using the alert.accept() method. At the end, we close the Selenium WebDriver instance using the driver.close() method.

Thread.sleep(2000);
driver.switchTo().alert().accept();
driver.close();

Now that the PIN number is extracted from the email and the mailbox is empty, the method returns the PIN number that was read from the email in Step 10.

Test HTTP Emails with Mailtrap and Cloud-Based Selenium Grid


In this section, we demonstrate how you can use Selenium for verifying a user that has created an account on LambdaTest. The test is performed on Chrome (latest version) and Windows 10 browser-platform combination.

We create an account on LambdaTest using the email address provided by Mailtrap (i.e. himanshu.sheth-a2ee5a@inbox.mailtrap.io). On the creation of the account, LambdaTest sends an email with the subject “Verify your Email Address – LambdaTest”. The email from LambdaTest contains the PIN number that has to be entered in the confirmation screen of LambdaTest.

When the right PIN is entered on the confirmation screen, you are all set to use LambdaTest.

FileName – Mailtrap_http_usecase.java 

package org.lt.mailtrap;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
public class Mailtrap_http_usecase extends Helper{
    String Mailtrap_URL = "/signin";
    WebDriver driver = null;
    public static String status = "passed";
    public static String username = "user-name";
    public static String access_key = "access-key";
    @BeforeTest
    @Parameters(value={"browser","version","platform", "resolution"})
    public void testSetUp(String browser, String version, String platform, String resolution) throws Exception
    {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("build", "Account Creation on LambdaTest with email support from Mailtrap");
        capabilities.setCapability("name", "Account Creation on LambdaTest with email support from Mailtrap");
        capabilities.setCapability("platformName", platform);
        capabilities.setCapability("browserName", browser);
        capabilities.setCapability("browserVersion",version);
        capabilities.setCapability("tunnel",false);
        capabilities.setCapability("network",true);
        capabilities.setCapability("console",true);
        capabilities.setCapability("visual",true);
        try
        {
            driver = new RemoteWebDriver(new URL("http://" + username + ":" + access_key + "@hub.lambdatest.com/wd/hub"), capabilities);
        }
        catch (MalformedURLException e)
        {
            System.out.println("Invalid grid URL");
        }
        System.out.println("Started session");
    }
    @Test(enabled=true, priority = 1)
    public void test_LambdaTest_AccCreation() throws InterruptedException
    {
        String test_url = "https://accounts.lambdatest.com/login";
        driver.navigate().to(test_url);
        driver.manage().window().maximize();
        try
        {
            /* Enter the necessary details for account creation */
            WebElement elem_first_name = driver.findElement(By.cssSelector("[name='email']"));
            elem_first_name.sendKeys("himanshu.sheth-a2ee5a@inbox.mailtrap.io");
            WebElement elem_user_password = driver.findElement(By.xpath("//input[@id='userpassword']"));
            elem_user_password.sendKeys("Password");
            WebElement elem_login = driver.findElement(By.cssSelector(".btn"));
            elem_login.click();
            String originalWindow = driver.getWindowHandle();
            System.out.println("Thw original window handle is " + originalWindow);
            System.out.println(driver.getWindowHandles().size());
            /* Now that the email is sent we extract the OTP from the same */
            String str_extracted_pin_number = ReadOtpFromEmail(driver, Mailtrap_URL);
            System.out.println("OTP from the email is " + str_extracted_pin_number);
            Integer int_extracted_pin_number = Integer.parseInt(str_extracted_pin_number);
            Integer int_backup_extracted_pin_number = int_extracted_pin_number;
            Integer elem_count = 7;
            driver.switchTo().window(originalWindow);
            System.out.println(driver.getTitle());
            String last_elem_value = null;
            WebElement elem_curr_box;
            while (int_backup_extracted_pin_number != 0)
            {
                Integer int_extracted_digit = int_backup_extracted_pin_number % 10;
                int_backup_extracted_pin_number = int_backup_extracted_pin_number / 10;
                String final_xpath = "//input[" + elem_count + "]";
                System.out.println(final_xpath);
                elem_curr_box = driver.findElement(By.xpath(final_xpath));
                if (elem_count != 7)
                {
                    elem_curr_box.sendKeys(Integer.toString(int_extracted_digit));
                }
                else
                {
                    /* After entering the last digit, the OTP is submitted */
                    /* Hence, we enter the last digit in the end */
                    last_elem_value = Integer.toString(int_extracted_digit);
                }
                Thread.sleep(1000);
                elem_count--;
            }
            elem_curr_box = driver.findElement(By.xpath("//input[7]"));
            elem_curr_box.sendKeys(last_elem_value);
            Thread.sleep(5000);
            System.out.println("Test is completed\n");
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
    @AfterTest
    public void tearDown()
    {
        if (driver != null)
        {
            ((JavascriptExecutor) driver).executeScript("lambda-status=" + status);
            driver.quit();
        }
    }
}

Code Walkthrough

In the testSetUp method that is implemented under the @BeforeTest annotation, we instantiate the Remote Selenium WebDriver using the browser and platform combination that are passed as parameters to the method.


Along with the Desired Capabilities, the combination of username and access key used for accessing the LambdaTest Selenium Grid are passed to the RemoteWebDriver method. On success, we get an instance of Selenium WebDriver against which the Selenium automation tests are conducted.

@BeforeTest
    @Parameters(value={"browser","version","platform", "resolution"})
    public void testSetUp(String browser, String version, String platform, String resolution) throws Exception
    {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("build", "Account Creation on LambdaTest with email support from Mailtrap");
   ......................
        ......................
        capabilities.setCapability("browserName", browser);
        capabilities.setCapability("browserVersion",version);
        driver = new RemoteWebDriver(new URL("http://" + username + ":" + access_key + "@hub.lambdatest.com/wd/hub"), capabilities);

In the test scenario test_LambdaTest_AccCreation(), the URL under test is set to https://accounts.lambdatest.com/login.

String test_url = "https://accounts.lambdatest.com/login";

To confirm the account on LambdaTest that was created using the email address from Mailtrap, we first locate the WebElement where we need to enter the email address.

WebElement elem_first_name = driver.findElement(By.cssSelector("[name='email']"));
elem_first_name.sendKeys("himanshu.sheth-a2ee5a@inbox.mailtrap.io");

We enter the password used during account creation in the Element with XPath “//input[@id=’userpassword’]”. The sendKeys method in Selenium is used for entering the password in the located element.


WebElement elem_user_password = driver.findElement(By.xpath("//input[@id='userpassword']"));
elem_user_password.sendKeys("Password");

We perform a click operation on the login button, which is located using the findElement method in Selenium.


WebElement elem_login = driver.findElement(By.cssSelector(".btn"));
elem_login.click();

As we will be opening the Mailtrap mailbox in a new Window, we save the current window handle that is obtained using the getWindowHandle() method in Selenium.

String originalWindow = driver.getWindowHandle();

To read the PIN Number from the Mailtrap mailbox, we call the ReadOtpFromEmail method that is implemented in Helper.java. The Selenium WebDriver and Mailtrap sign-in URL (i.e. /signin) is passed to the method. On success, the PIN number will be available in the str_extracted_pin_number String variable.

String str_extracted_pin_number = ReadOtpFromEmail(driver, Mailtrap_URL);

Using Integer.parseInt method, we convert the PIN number from String to Integer.

Integer int_extracted_pin_number = Integer.parseInt(str_extracted_pin_number);

The next step is extracting each digit from the PIN number and entering them in the designated boxes of the PIN verification page. At each stage, the Division and Mod operator is used for extracting the Digit and updating the PIN Number (once the digit is read) for the next read.


The extracted digit is entered in the designated input text box, which is located using the XPath property. The sendKeys method is used for entering the extracted digit in the right text box.


while (int_backup_extracted_pin_number != 0)
{
 Integer int_extracted_digit = int_backup_extracted_pin_number % 10;
 int_backup_extracted_pin_number = int_backup_extracted_pin_number / 10;
 String final_xpath = "//input[" + elem_count + "]";
 System.out.println(final_xpath);
 elem_curr_box = driver.findElement(By.xpath(final_xpath));

Once the final digit is entered in the box with XPath “//input[7]”, the request for account creation is submitted. If the entered PIN number is correct, account creation on LambdaTest is successful.

if (elem_count != 7)
{
 elem_curr_box.sendKeys(Integer.toString(int_extracted_digit));
}
else
{
 /* After entering the last digit, the OTP is submitted */
 /* Hence, we enter the last digit in the end */
      last_elem_value = Integer.toString(int_extracted_digit);
}
elem_curr_box = driver.findElement(By.xpath("//input[7]"));
elem_curr_box.sendKeys(last_elem_value);

Execution


Shown below are the execution snapshots obtained from the Automation Dashboard on LambdaTest:

The Mailtrap mailbox is opened in a new Window.

The PIN number is read from the email and the window is closed. In the Parent window, the PIN number is entered in the confirmation box.

As seen below, the account on LambdaTest is successfully created using the Mailtrap email address.

Test SMTP-Based Emails with Mailtrap and Cloud-Based Selenium Grid


In this particular test scenario, we use the SMTP settings of Mailtrap to send the email that contains the PIN number sent by LambdaTest. The purpose of this test is not to confirm the account creation on LambdaTest, but to showcase the use of SMTP settings (of Mailtrap) to test HTML emails on different browser and OS combinations.

FileName – Mailtrap_send_email_usecase.java

package org.lt.mailtrap;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.IExecutionListener;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class Mailtrap_send_email_usecase extends Helper implements IExecutionListener {
    WebDriver driver = null;
    public static String status = "passed";
    public static String username = "user-name";
    public static String access_key = "access-key";
    String Mailtrap_URL = "/signin";
    @BeforeTest
    @Parameters(value={"browser","version","platform", "resolution"})
    public void testSetUp(String browser, String version, String platform, String resolution) throws Exception
    {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("name", "Testing email from Mailtrap (with infra from LambdaTest)");
        capabilities.setCapability("build", "Testing email from Mailtrap (with infra from LambdaTest)");
        capabilities.setCapability("platformName", platform);
        capabilities.setCapability("browserName", browser);
        capabilities.setCapability("browserVersion",version);
        capabilities.setCapability("tunnel",false);
        capabilities.setCapability("network",true);
        capabilities.setCapability("console",true);
        capabilities.setCapability("visual",true);
        try
        {
            driver = new RemoteWebDriver(new URL("http://" + username + ":" + access_key + "@hub.lambdatest.com/wd/hub"), capabilities);
        }
        catch (MalformedURLException e)
        {
            System.out.println("Invalid grid URL");
        }
        System.out.println("Started session");
    }
    @Test(enabled=true, priority = 1)
    public void test_LambdaTest_sendemail() throws MalformedURLException, InterruptedException
    {
        String to = "himanshu.sheth-a2ee5a@inbox.mailtrap.io";
        String from = "himanshu.sheth-a2ee5a@inbox.mailtrap.io";
        final String username = "5931e2";
        final String password = "176831";
        String host = "smtp.mailtrap.io";
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", "2525");
        /* Ceate the Session object */
        Session session = Session.getInstance(props, new javax.mail.Authenticator()
        {
            protected PasswordAuthentication getPasswordAuthentication()
            {
                return new PasswordAuthentication(username, password);
            }
        });
        try
        {
            /* Create a MimeMessage object */
            Message message = new MimeMessage(session);
            /* Set From email field */
            message.setFrom(new InternetAddress(from));
            /* Set To email field */
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse(to));
            /* Set email subject field */
            message.setSubject("Verify your Email Address - LambdaTest");
            /* The actual message that contains the OTP */
            message.setContent("<div dir=\"ltr\"><div class=\"gmail_default\" style=\"font-family:arial,helvetica,sans-serif\"><br></div><div class=\"gmail_quote\"><div class=\"gmail_quote\"><br><u></u>\n" +
                    "\n" +
                    "\n" +
                    "\n" +
                    "\n" +
                    "\n" +
                    "<div style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:#ffffff;color:#718096;height:100%;line-height:1.4;margin:0;padding:0;width:100%!important\">\n" +
                    "\n" +
                    "\n" +
                    "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:#edf2f7;margin:0;padding:0;width:100%\">\n" +
                    "<tbody><tr>\n" +
                    "<td align=\"center\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';margin:0;padding:0;width:100%\">\n" +
                    "<tbody><tr>\n" +
                    "<td style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';padding:25px 0;text-align:center\">\n" +
                    "<a href=\"https://accounts.lambdatest.com\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';color:#3d4852;font-size:19px;font-weight:bold;text-decoration:none;display:inline-block\" rel=\"noreferrer\" target=\"_blank\">\n" +
                    "LambdaTest\n" +
                    "</a>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "\n" +
                    "\n" +
                    "<tr>\n" +
                    "<td width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:#edf2f7;border-bottom:1px solid #edf2f7;border-top:1px solid #edf2f7;margin:0;padding:0;width:100%\">\n" +
                    "<table align=\"center\" width=\"570\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:#ffffff;border-color:#e8e5ef;border-radius:2px;border-width:1px;margin:0 auto;padding:0;width:570px\">\n" +
                    "\n" +
                    "<tbody><tr>\n" +
                    "<td style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';max-width:100vw;padding:32px\">\n" +
                    "<h1 style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';color:#3d4852;font-size:18px;font-weight:bold;margin-top:0;text-align:left\">Hello!</h1>\n" +
                    "<p style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:1.5em;margin-top:0;text-align:left\">Your PIN is: 24318</p>\n" +
                    "<p style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:1.5em;margin-top:0;text-align:left\">You can also click the button below to verify email address.</p>\n" +
                    "<table align=\"center\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';margin:30px auto;padding:0;text-align:center;width:100%\">\n" +
                    "<tbody><tr>\n" +
                    "<td align=\"center\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<tbody><tr>\n" +
                    "<td align=\"center\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<tbody><tr>\n" +
                    "<td style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<a href=\"https://accounts.lambdatest.com/email/verify/340857/da8df8ebcf52a57cb1eb14738619104ea1f61e6a?expires=1606637431&amp;signature=4a0471d51a9dd8e89b3462bee03e5dc7df503efb05a52ef60349cc7064102317\" rel=\"noopener noreferrer\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';border-radius:4px;color:#fff;display:inline-block;overflow:hidden;text-decoration:none;background-color:#2d3748;border-bottom:8px solid #2d3748;border-left:18px solid #2d3748;border-right:18px solid #2d3748;border-top:8px solid #2d3748\" target=\"_blank\">Verify Email Address</a>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "<p style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:1.5em;margin-top:0;text-align:left\">If you did not create an account, no further action is required.</p>\n" +
                    "<p style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:1.5em;margin-top:0;text-align:left\">Regards,<br>LambdaTest</p>\n" +
                    "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';border-top:1px solid #e8e5ef;margin-top:25px;padding-top:25px\">\n" +
                    "<tbody><tr>\n" +
                    "<td style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<p style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';line-height:1.5em;margin-top:0;text-align:left;font-size:14px\">If you’re having trouble clicking the &quot;Verify Email Address&quot; button, copy and paste the URL below\n" +
                    "into your web browser: <a href=\"https://accounts.lambdatest.com/email/verify/340857/da8df8ebcf52a57cb1eb14738619104ea1f61e6a?expires=1606637431&amp;signature=4a0471d51a9dd8e89b3462bee03e5dc7df503efb05a52ef60349cc7064102317\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';color:#3869d4\" rel=\"noreferrer\" target=\"_blank\">https://accounts.lambdatest.com/email/verify/340857/da8df8ebcf52a57cb1eb14738619104ea1f61e6a?expires=1606637431&amp;signature=4a0471d51a9dd8e89b3462bee03e5dc7df503efb05a52ef60349cc7064102317</a></p>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "\n" +
                    "\n" +
                    "\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "\n" +
                    "<tr>\n" +
                    "<td style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'\">\n" +
                    "<table align=\"center\" width=\"570\" cellpadding=\"0\" cellspacing=\"0\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';margin:0 auto;padding:0;text-align:center;width:570px\">\n" +
                    "<tbody><tr>\n" +
                    "<td align=\"center\" style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';max-width:100vw;padding:32px\">\n" +
                    "<p style=\"box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';line-height:1.5em;margin-top:0;color:#b0adc5;font-size:12px;text-align:center\">© 2020 LambdaTest. All rights reserved.</p>\n" +
                    "\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "</td>\n" +
                    "</tr>\n" +
                    "</tbody></table>\n" +
                    "</div>\n" +
                    "\n" +
                    "</div>\n" +
                    "</div></div>", "text/html");
            /* Finally, send the composed message */
            Transport.send(message);
            System.out.println("Email Message Sent Successfully");
        }
        catch (MessagingException e)
        {
            throw new RuntimeException(e);
        }
        /* Now that the email is sent we extract the OTP from the same */
        String str_extracted_pin_number = ReadOtpFromEmail(driver, Mailtrap_URL);
        System.out.println("OTP from the email is " + str_extracted_pin_number);
    }
    @AfterTest
    public void tearDown()
    {
        if (driver != null)
        {
            ((JavascriptExecutor) driver).executeScript("lambda-status=" + status);
            driver.quit();
        }
    }
    @Override
    public void onExecutionStart()
    {
        System.out.println("onExecutionStart");
    }
    @Override
    public void onExecutionFinish()
    {
        System.out.println("onExecutionFinish");
    }
}

Code Walkthrough

The implementation under the @BeforeTest annotation is kept unchanged. However, we have used the browser and OS combination similar to the one used in the HTTP based test (which we demonstrated earlier).

In the test_LambdaTest_sendemail() test method, we set the necessary variables for setting the username, password, host URL, and from and to email address. The from and to email address is set to the Mailtrap address (i.e. himanshu.sheth-a2ee5a@inbox.mailtrap.io).

String to = "himanshu.sheth-a2ee5a@inbox.mailtrap.io";
String from = "himanshu.sheth-a2ee5a@inbox.mailtrap.io";
final String username = "5931ef1";
final String password = "17683";
String host = "smtp.mailtrap.io";

We have taken the required settings from the SMTP settings section of Mailtrap.

An instance of class Properties is created for storing the SMTP-related properties (i.e. “mail.smtp.auth”, “mail.smtp.starttls.enable”, “mail.smtp.port”, etc.) that are used for sending the email.

Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", "2525");

The javax.mail.Authenticator class represents an object that knows how to obtain authentication for a network condition. The getInstance method of the Session class is used for creating a Session object.

Session session = Session.getInstance(props, new javax.mail.Authenticator()

Create a MimeMessage object with session as the input argument.

Message message = new MimeMessage(session);

The InternetAddress class represents an email address using the syntax of RFC822. We set the from email field in the object of class Message.

message.setFrom(new InternetAddress(from));

The email recipient is set using the setRecipients method.

message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(to));

Using the setSubject method, the message subject is set to “Verify your Email Address – LambdaTest”.

message.setSubject("Verify your Email Address - LambdaTest");

The final step before sending the email is setting the email content in the HTML format. We pass the HTML email to the message using the setContent method.


message.setContent("<div dir=\"ltr\"><div class=\"gmail_default\"
.................................................................
.................................................................
.................................................................

The send method of the Transport class is invoked for sending the email message that we composed in Step 8. The message is sent to all the recipient addresses in the message. It calls the saveChanges method on the message before the message is sent.

Transport.send(message);

The ReadOtpFromEmail method is called with Selenium WebDriver and Mailtrap sign-in URL as the arguments.

String str_extracted_pin_number = ReadOtpFromEmail(driver, Mailtrap_URL);

Execution


We were able to read the PIN number from the HTML email that was sent using the SMTP settings of Mailtrap.

Conclusion


HTML emails play a pivotal role in reducing churn, onboarding new customers, converting leads, and more. Since different browsers and email clients render HTML emails differently, there is a high probability that the look and feel of the email may be off on some web browsers. To improve the email campaign’s deliverability, it becomes essential to test the HTML email on different browser and OS combinations.

Instead of investing in a non-scalable and non-reliable in-house Selenium Grid infrastructure, it is viable to perform Selenium automation testing on a cloud-based Selenium Grid. The combination of Mailtrap and cloud-based Selenium Grid (like LambdaTest) can be instrumental in improving the test coverage and email deliverability, which has a positive impact on the customer experience. ☺

Exit mobile version