This post covers sending and receiving emails from test email accounts in PHP integration tests. We will use PHPUnit and the free library MailSlurp to read and write email in code without SMTP mail servers. PHPUnit is a popular PHP test library. It is used with many popular PHP frameworks such as Laravel. When used with the free MailSlurp PHP SDK you can create test email accounts then send and receive emails in code.

How does email integrate with PHP

Many modern web applications rely on email: for user sign-up, password reset, newsletters, contact forms and more. To test these end to end you need programmable email accounts. MailSlurp is a free API that lets you create these on demand.

Necessity of Email Reading in PHP Code and Tests

In PHP applications, reading emails programmatically is essential for validating workflows involving email communication. This is particularly relevant in scenarios like user registration, password resets, and two-factor authentication (2FA) processes. Automated tests that can read and verify email contents ensure that these critical features function correctly, enhancing the reliability of the application.

Using MailSlurp to Receive and Extract Codes

MailSlurp offers a convenient solution for PHP applications to receive and interact with emails without the need for direct SMTP server connections. It provides a PHP client that enables developers to easily integrate email functionalities into their applications and tests. MailSlurp works by polling email endpoints, allowing it to wait for and retrieve emails as soon as they arrive. This method is efficient for extracting OTPs or verification codes from emails, which is crucial in automated testing scenarios.

Getting started

You can install the official PHP library from packagist using composer:

First create a composer.json in your project root like so:

{
  "repositories": [
    {
      "type": "git",
      "url": "https://github.com/mailslurp/swagger-sdk-php.git"
    }
  ],
  "require": {
    "mailslurp/mailslurp-client-php": "dev-master",
    "phpunit/phpunit": "^8"
  }
}

Next run:

composer install

Write a test using real email addresses

Next, to demonstrate how to send and receive email in PHP using MailSlurp let's write a test that create two email addresses on demand and then sends an email between them. We will also use MailSlurp to extract email contents for a make-believe confirmation code.

<?php
require_once(__DIR__ . '/vendor/autoload.php');

use PHPUnit\Framework\TestCase;

/**
 * This testsuite demonstrates how to use MailSlurp Email API Client in PHP
 *
 * MailSlurp lets you create real email addresses in PHP. You can then send and receive emails
 * and attachments in PHP applications and tests.
 *
 * See https://docs.mailslurp.com/ for more information.
 *
 */
final class EmailTest extends TestCase
{
    private function getConfig()
    {
        // create a mailslurp configuration with API_KEY environment variable
        // get your own free API KEY at https://app.mailslurp.com/sign-up/
        return MailSlurp\Configuration::getDefaultConfiguration()
            ->setApiKey('x-api-key', getenv("API_KEY"));
    }

    public function test_CanCreateAnInbox_ThenSendAndReceiveEmails()
    {
        // create an inbox controller
        $inboxController = new MailSlurp\Apis\InboxControllerApi(null, $this->getConfig());

        // create an inbox
        $inbox = $inboxController->createInbox();

        // verify inbox has an email address ending in @mailslurp.com
        $this->assertStringContainsString(
            "mailslurp.com",
            $inbox->getEmailAddress()
        );
    }

    public function test_CanSendAndReceiveEmail_BetweenTwoInboxes()
    {
        // create inbox and waitFor controllers
        $inbox_controller = new MailSlurp\Apis\InboxControllerApi(null, $this->getConfig());
        $wait_for_controller = new MailSlurp\Apis\WaitForControllerApi(null, $this->getConfig());

        // create two inboxes
        $inbox_1 = $inbox_controller->createInbox();
        $inbox_2 = $inbox_controller->createInbox();

        // send a confirmation code from inbox1 to inbox2 (sends an actual email)
        $send_options = new MailSlurp\Models\SendEmailOptions();
        $send_options->setTo([$inbox_2->getEmailAddress()]);
        $send_options->setSubject("Test");
        $send_options->setBody("Confirmation code = abc123");
        $inbox_controller->sendEmail($inbox_1->getId(), $send_options);

        // receive email for inbox2
        $timeout_ms = 30000;
        $unread_only = true;
        $email = $wait_for_controller->waitForLatestEmail($inbox_2->getId(), $timeout_ms, $unread_only);

        // verify emails content
        $this->assertEquals($inbox_1->getEmailAddress(), $email->getFrom());
        $this->assertEquals($inbox_2->getEmailAddress(), $email->getTo()[0]);
        $this->assertEquals("Test", $email->getSubject());
        $this->assertStringContainsString("Confirmation code = ", $email->getBody());

        // extract part of an email using regex (could be used in further test steps)
        $matches = array();
        preg_match('/.+code = (.+)/', $email->getBody(), $matches);
        $confirmation_code = $matches[1];
        $this->assertEquals($confirmation_code, "abc123");
    }

}

That is a big code block. Let us explain how it works.

How the tests work

The PHP code snippet above demonstrates the use of the MailSlurp Email API Client in a PHPUnit test suite for a PHP application. The code is structured as a PHPUnit test class, EmailTest, which contains methods to test various email functionalities provided by MailSlurp.

Configuration and Setup

  • Configuration Method: The getConfig() private method is responsible for setting up the MailSlurp configuration. It uses an API key, which is retrieved from an environment variable API_KEY. This configuration is essential for authenticating and interacting with the MailSlurp API.

Test Methods

  • Test for Creating and Receiving Emails:

    • The test_CanCreateAnInbox_ThenSendAndReceiveEmails method tests the ability to create a new email inbox using MailSlurp. It initializes the InboxControllerApi object with the configuration.
    • An inbox is created using createInbox(), and the test asserts that the inbox's email address ends with "@mailslurp.com", verifying the creation of a valid MailSlurp email address.
  • Test for Sending and Receiving Emails Between Two Inboxes:

    • The test_CanSendAndReceiveEmail_BetweenTwoInboxes method performs a more complex test. It involves creating two separate inboxes and sending an email from one inbox to the other.
    • Two inboxes are created using InboxControllerApi, and a WaitForControllerApi instance is also initialized.
    • An email is sent from the first inbox (inbox_1) to the second inbox (inbox_2). The email contains a specific subject ("Test") and a body with a confirmation code ("Confirmation code = abc123").
    • The test then waits for an email to arrive in inbox_2 using waitForLatestEmail from WaitForControllerApi. This method waits for a specified timeout period (30 seconds in this case) for a new unread email to arrive.
    • Several assertions are performed to verify the email's sender, recipient, subject, and body. The test checks if the received email is indeed from inbox_1, is addressed to inbox_2, has the correct subject, and contains the expected confirmation code in the body.
    • Additionally, the test uses a regular expression to extract the confirmation code from the email body. This extracted code is then asserted to match the expected code ("abc123"). This demonstrates how MailSlurp can be used to extract specific information from emails, which is a common requirement in automated testing of applications involving email-based verification or communication.

Importance of Testing OTP Verification in Web Applications

Testing OTP verification is critical in modern web applications to ensure the security and integrity of user authentication processes. By automating OTP extraction and verification through tools like MailSlurp, developers can rigorously test the security layers of their applications. This ensures that the OTP systems work as intended, providing an extra layer of security against unauthorized access and improving the overall trustworthiness of the application.