End-to-end Testing
How-tos & Guides
9 min read

Testing email workflows with Selenium

Learn how to automate an end-to-end workflow that spans both web and email using Selenium WebDriver.

Antonello Zanini
Published August 9, 2022

Many web applications have functionality that generates automated emails. These emails often represent critical parts of a user’s journey through the application, and any bugs affecting them could have serious negative implications.

One of most common workflows where automated emails are used are new user registration scenarios. Often after signing up for an account, you’ll be asked to confirm your email address via an automated email that sends a confirmation email or by entering a short verification code (which is sometimes called a one-time password or OTP for short).

In this article, you will learn how to create an automated test for such an email workflow using Selenium WebDriver. Specifically, we’ll create a Selenium test in Java that fills out a registration form, waits for an email to arrive at a given email address, extracts the confirmation URL from the email, and visits that URL in the browser to complete the registration process.

What are the common scenarios that include automated emails?

There are many potential end-to-end scenarios that could involve sending automated emails. Here are a few of the most common end-to-end scenarios that span both web and email:

Why You Should Test Your Email Workflows

There are several reasons why email workflows are important for your website, and you should test them accordingly. Let’s dive into the three most important ones.

How To Test an Email Workflow with Selenium

Let’s now learn how to test a registration email workflow with Selenium in a step-by-step tutorial based on a complete example. Thanks to Selenium, you can retrieve the URL provided to the newly subscribed user via email to see if it matches the expected one in only a few lines of code.

1. Connecting to the Registration Page

First, you have to use Selenium to connect to the registration page of the website you want to test the email workflow. You can achieve this as follows:

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

public class Main {
    public static void main(String[] args) {
        // setting the system property for the Chrome Driver
        System.setProperty("webdriver.chrome.driver", "<the_path_to_your_chrome_driver>");

        // initializing the Selenium WebDriver ChromeDriver class
        WebDriver driver = new ChromeDriver();

        // connecting to the registration page
        driver.get("http://localhost/registration-page");
    }
}

This is what http://localhost/registration-page looks like:

As you can see, it is a simple registration form based on a free Bootstrap 5 template. In a real-world test, make sure to replace http://localhost/registration-page with the URL of your registration page.

2. Filling out the registration form

Now, it is time to fill out the registration form and submit it in Selenium to trigger the email workflow.

This is what the sample HTML form looks like:

<form method="POST" class="register-form" id="register-form" action="confirmation-email-sent.php">
  <div class="form-group">
    <label for="name"><i class="zmdi zmdi-account material-icons-name"></i></label>
    <input type="text" name="name" id="name" placeholder="Your Name" />
  </div>
  <div class="form-group">
    <label for="email"><i class="zmdi zmdi-email"></i></label>
    <input type="email" name="email" id="email" placeholder="Your Email" />
  </div>
  <div class="form-group">
    <label for="pass"><i class="zmdi zmdi-lock"></i></label>
    <input type="password" name="password" id="password" placeholder="Password" />
  </div>
  <div class="form-group">
    <label for="re_pass"><i class="zmdi zmdi-lock-outline"></i></label>
    <input type="password" name="re_password" id="re_password" placeholder="Repeat your password" />
  </div>
  <div class="form-group">
    <input type="checkbox" name="agree-term" id="agree-term" class="agree-term" />
    <label for="agree-term" class="label-agree-term"
      ><span><span></span></span>I agree all statements in <a href="#" class="term-service">Terms of service</a></label
    >
  </div>
  <div class="form-group form-button">
    <input type="submit" name="signup" id="signup" class="form-submit" value="Register" />
  </div>
</form>

So, the Selenium script should implement the following logic:

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

public class Main {
    public static void main(String[] args) {
        // setting the system property for the Chrome Driver
        System.setProperty("webdriver.chrome.driver", "<the_path_to_your_chrome_driver>");

        // initializing the Selenium WebDriver ChromeDriver class
        // for the 10-minute email service
        WebDriver tenMinuteEmailDriver = new ChromeDriver();

        // connecting to the https://www.minuteinbox.com/ page
        tenMinuteEmailDriver.get("https://www.minuteinbox.com/");

        // retrieving the 10-minute email address
        WebElement tenMinuteEmailInput = tenMinuteEmailDriver.findElement(By.id("email"));
        String emailAddress = tenMinuteEmailInput.getAttribute("value");

        // initializing the Selenium WebDriver ChromeDriver class
        // for the registration page
        WebDriver registrationDriver = new ChromeDriver();

        // connecting to the registration page
        registrationDriver.get("http://localhost/reflect/selenium-emails/");

        // filling out the registration form
        WebElement nameInput = registrationDriver.findElement(By.id("name"));
        nameInput.sendKeys("Maria Williams");

        WebElement emailInput = registrationDriver.findElement(By.id("email"));
        emailInput.sendKeys(emailAddress);

        // a random password to fill out the registration form
        String password = "J#Vq6KB9#dCstNQ5ZChz";

        WebElement passwordInput = registrationDriver.findElement(By.id("password"));
        passwordInput.sendKeys(password);

        WebElement repeatPasswordInput = registrationDriver.findElement(By.id("re_password"));
        repeatPasswordInput.sendKeys(password);

        WebElement submitButton = registrationDriver.findElement(By.id("signup"));
        // submitting the form
        submitButton.click();
    }
}

Keep in mind that you have to adapt this logic according to the layout of your registration page. Also, note that the email provided to the registration form via Selenium is a 10-minute email address. You can retrieve this from the email input by minuteinbox.com. This is what the minuteinbox.com page looks like:

A 10-minute mail is a disposable email address that self-destructs after 10 minutes. A 10-minute email provider offers everything you need to receive emails. Since the email containing the confirmation link will be received here, you have to keep this window open. This is why the Selenium script initializes two different WebDriver instances.

Using a 10-minute email is a good way to test an email workflow. This is because most popular email providers such as Gmail have logic that detects and block automated scripts such as Selenium. On the other hand, minuteinbox.com is a simple service, does not require authentication, and is Selenium-friendly.

3. Retrieving the Confirmation Email

You now have to use Selenium to interact with the 10-minute email provider page, find the confirmation email, and open it.

To do so, you have to click on <tr class='hidden-xs hidden-sm klikaciRadek newMail``" data-href=``"``2>, wait for the iframeMail <iframe> element in the new page to load, and extract the text of the email from its body. You can achieve this as follows:

    By confirmationEmailTrBy = By.cssSelector("tr\[class='hidden-xs hidden-sm klikaciRadek newMail'\][data-href='2']");
    // waiting up to 5 minutes until the confirmationEmailTr HTML element can be clicked
    WebDriverWait wait = new WebDriverWait(tenMinuteEmailDriver, Duration.ofMinutes(5));
    wait.until(ExpectedConditions.elementToBeClickable(confirmationEmailTrBy));

    WebElement confirmationEmailTr = tenMinuteEmailDriver.findElement(confirmationEmailTrBy);
    confirmationEmailTr.click();

    tenMinuteEmailDriver.switchTo().frame("iframeMail");
    By iframeEmailBodyBy = By.tagName("body");
    // waiting up to 20 seconds until the iframe containing the email loads
    new WebDriverWait(tenMinuteEmailDriver, Duration.ofSeconds(20))
            .until(ExpectedConditions.presenceOfElementLocated(iframeEmailBodyBy));
    WebElement iframeEmailBody = tenMinuteEmailDriver.findElement(iframeEmailBodyBy);

The confirmation email might need minutes to arrive at your 10-minute email address. If you want to avoid a NoSuchElementException, you can wait a few minutes for the email with WebDriverWait. Note that we have a separate article with tips for avoiding NoSuchElementException errors in Selenium.

This is what the confirmation email looks like:

To retrieve the URL of the confirmation link, you have to extract it from the HTML text node of the iframe’s body previously selected. Achieve this as follows:

String mailText = iframeEmailBody.getText();
String confirmationURL = mailText.substring(mailText.lastIndexOf("the link below:"), mailText.indexOf("Thank you")).trim();

The URL can be retrieved by extracting the text contained between “the link below:” and “Thank you” with the substring(int beginIndex, int endIndex) method.

Putting It All Together

This is what the entire Selenium script looks like:

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;

public class Main {
    public static void main(String[] args) {
        // setting the system property for the Chrome Driver
        System.setProperty("webdriver.chrome.driver", "<the_path_to_your_chrome_driver>");

        // initializing the Selenium WebDriver ChromeDriver class
        // for the 10-minute email service
        WebDriver tenMinuteEmailDriver = new ChromeDriver();
        tenMinuteEmailDriver.manage().window().maximize();
        // connecting to the https://www.minuteinbox.com/ page
        tenMinuteEmailDriver.get("https://www.minuteinbox.com/");

        // retrieving the 10-minute email address
        WebElement tenMinuteEmailSpan = tenMinuteEmailDriver.findElement(By.id("email"));
        String emailAddress = tenMinuteEmailSpan.getText();

        // initializing the Selenium WebDriver ChromeDriver class
        // for the registration page
        WebDriver registrationDriver = new ChromeDriver();

        // connecting to the registration page
        registrationDriver.get("http://localhost/reflect/selenium-emails/");

        // filling out the registration form
        WebElement nameInput = registrationDriver.findElement(By.id("name"));
        nameInput.sendKeys("Maria Williams");

        WebElement emailInput = registrationDriver.findElement(By.id("email"));
        emailInput.sendKeys(emailAddress);

        // a random password to fill out the registration form
        String password = "J#Vq6KB9#dCstNQ5ZChz";

        WebElement passwordInput = registrationDriver.findElement(By.id("password"));
        passwordInput.sendKeys(password);

        WebElement repeatPasswordInput = registrationDriver.findElement(By.id("re_password"));
        repeatPasswordInput.sendKeys(password);

        WebElement submitButton = registrationDriver.findElement(By.id("signup"));
        // submitting the form
        submitButton.click();

        By confirmationEmailTrBy = By.cssSelector("tr\[class='hidden-xs hidden-sm klikaciRadek newMail'\][data-href='2']");
        // waiting up to 5 minutes until the confirmationEmailTr HTML element can be clicked
        WebDriverWait wait = new WebDriverWait(tenMinuteEmailDriver, Duration.ofMinutes(5));
        wait.until(ExpectedConditions.elementToBeClickable(confirmationEmailTrBy));

        WebElement confirmationEmailTr = tenMinuteEmailDriver.findElement(confirmationEmailTrBy);
        confirmationEmailTr.click();

        tenMinuteEmailDriver.switchTo().frame("iframeMail");
        By iframeEmailBodyBy = By.tagName("body");
        // waiting up to 20 seconds until the iframe containing the email loads
        new WebDriverWait(tenMinuteEmailDriver, Duration.ofSeconds(20))
                .until(ExpectedConditions.presenceOfElementLocated(iframeEmailBodyBy));
        WebElement iframeEmailBody = tenMinuteEmailDriver.findElement(iframeEmailBodyBy);

        // extracting the confirmation URL
        String mailText = iframeEmailBody.getText();
        String confirmationURL = mailText.substring(mailText.lastIndexOf("the link below:"), mailText.indexOf("Thank you")).trim();

        System.out.println(confirmationURL);
    }
}

With the confirmation email seen before, this script would return:

https://sendy.colorlib.com/confirm?e=TTm892BMc18892NhvF4gx6JL892Q&amp;l=I5sajNONQFFffS0E0wRLYA

Et voilà! You just retrieved the URL to visit to confirm the email address of the user. For information how to achieve test coverage for SMS, check out our article on testing SMS workflows using Selenium WebDriver.

Conclusion

In this article, you learned what e-mail workflows are, why testing them is so important, and why the URLs contained in these e-mails are what matter most when it comes to testing them. Considering how common e-mail workflows are, being able to test them is critical. Here, you learned how to implement a Selenium WebDriver test that triggers the e-mail workflow after a user registers with a website. Then, you saw how to use Selenium to retrieve the URL of the confirmation email sent to the user’s inbox and test whether it matches the expected URL.

Reflect: A testing tool with built-in support for testing email workflows

Reflect is a no-code testing tool that can test virtually any action you can take on a browser. Creating a test in Reflect is easy: the tool records your actions as you use your site and automatically translates those actions into a repeatable test that you can run any time. And with its email testing feature, you can create end-to-end tests that span web and email in a matter of minutes.

Get automated test coverage for your app today — try it for free.

Get started with Reflect today

Create your first test in 2 minutes, no installation or setup required. Accelerate your testing efforts with fast and maintainable test suites without writing a line of code.

Copyright © 2022 Reflect Software Inc. All Rights Reserved.