Testing HTML emails is tricky because they live in a mailbox, not a browser tab. This guide shows you how to use Cypress to verify that your transactional or marketing emails render correctly, contain the right content, and include working links—all within your existing test suite.
What You’ll Need
- A Cypress project already set up (Cypress 10 or later recommended)
- An email service that exposes a testing API or a way to retrieve emails programmatically (e.g., Mailosaur, Mailtrap, or a local SMTP server like MailHog)
- Basic familiarity with Cypress commands and JavaScript
Step-by-Step
- Set up your email testing service. Sign up for a service like Mailosaur or Mailtrap, or run a local SMTP server like MailHog. You’ll need an API key and a unique inbox/namespace to receive emails.
- Install any necessary Cypress plugin or library. For Mailosaur, you can use their official Node.js library. For MailHog, you can use its REST API directly. Install with npm:
npm install mailosaurornpm install mailhog. - Configure your email sending to use the test inbox. In your application’s environment or test configuration, set the SMTP or API credentials to point to your test email service. Ensure that emails triggered during tests go to the unique inbox you created.
- Create a Cypress custom command to fetch an email. In your
cypress/support/commands.jsfile, add a command likecy.getEmail(inboxId, searchCriteria)that calls the email service’s API to retrieve the latest email matching a subject or recipient. For Mailosaur, usemailosaur.messages.get(); for MailHog, useGET /api/v2/messages. - Write a test that triggers an email. Use Cypress to perform an action in your app that sends an email—for example, submitting a contact form or clicking a “forgot password” link. Wait a few seconds for the email to arrive (Cypress waits are acceptable here, but consider using
cy.interceptto wait for the API response if your app uses one). - Fetch the email and assert its content. In your test, call your custom command to get the email. Then assert that the subject line, sender, and body contain expected text. For example:
cy.getEmail(inboxId, 'Welcome').then(email => { expect(email.subject).to.contain('Welcome'); expect(email.text).to.contain('Hello John'); }). - Test links in the email. Extract any URLs from the email body (using regex or a library like
cheerio) and visit them withcy.visit(). Then assert that the page loads correctly or that the expected content appears. For example, click the verification link and verify the user is verified. - Test HTML rendering (optional). If you need to verify the visual layout, you can load the HTML content in an iframe within Cypress and take a screenshot. Use
cy.document()to manipulate the DOM or use a visual regression tool like Percy. - Clean up after the test. Delete the email from the test inbox to avoid interference with other tests. Most services provide a delete method; call it in the test’s
afterhook or after your assertions. - Run your tests. Execute
npx cypress runand ensure your email tests pass consistently. If they are flaky, increase the wait time or use retry logic.
Common Mistakes
- Not using a dedicated test inbox: Using a personal or shared inbox can lead to unexpected emails and flaky tests. Always use a unique inbox per test run.
- Hardcoding email addresses: If your tests send to a fixed address, parallel runs may conflict. Use dynamic addresses like
test-.@example.com - Assuming emails arrive instantly: Email delivery can take a few seconds. Failing to wait will cause tests to fail. Use
cy.wait()or better, poll the API with a retry loop. - Not handling HTML entities: When asserting text, remember that HTML emails may contain encoded characters. Use
cheerioto extract text content if needed. - Forgetting to clean up: Leaving test emails in the inbox can slow down API responses and cause false matches. Always delete emails after the test.
Tips
- Use a unique subject line per test: Include a timestamp or random string in the subject so you can easily identify and fetch the correct email.
- Abstract the email fetching logic: Create a separate utility file that handles the API calls, so your tests stay clean and you can switch email services without rewriting tests.
- Test both text and HTML parts: Some clients prefer plain text; ensure both are correct. Your email service API usually returns both.
- Use environment variables for secrets: Store your API keys in
cypress.env.jsonor environment variables, never hardcode them. - Consider visual regression: For critical emails like password resets, add a screenshot test to catch layout issues.
Troubleshooting
- Email not found: Check that the email was actually sent by looking at your app’s logs or the email service dashboard. Increase the wait time or add a retry loop that polls the API every second for up to 30 seconds.
- API call fails: Verify your API key and inbox ID are correct. Ensure your test environment can reach the email service (no firewall issues).
- Test is flaky: If tests pass sometimes and fail other times, the email delivery time is likely the culprit. Use a more robust waiting mechanism, such as a custom command that polls until the email appears or a timeout is reached.
- Links in email are relative: If your email contains relative links, you’ll need to prepend the base URL before visiting them. Use
new URL(link, baseUrl)to resolve them. - Email body is base64 encoded: Some APIs return the body as base64. Decode it before asserting. For example,
Buffer.from(email.html, 'base64').toString('utf8').
Frequently Asked Questions
- Can I test emails without a third-party service? Yes, you can use a local SMTP server like MailHog or Mailpit. They run on your machine and provide an HTTP API to fetch emails. This is free and works well for local testing.
- How do I wait for an email to arrive in Cypress? Use
cy.wait()with a fixed delay (e.g., 5 seconds) or better, write a custom command that polls the email API until the email appears or a timeout is reached. The latter is more reliable. - Can I test the HTML rendering of the email? Yes, you can load the HTML content in an iframe within Cypress and take a screenshot. However, some email clients render differently, so it’s best to also test with real clients if possible.
- What if my email service doesn’t have a Cypress plugin? You don’t need a plugin. Just use the service’s REST API directly with
cy.request()or a Node.js library in a custom command. - How do I test multiple emails in one test? Fetch each email by its unique subject or recipient. Use a loop to iterate over expected emails, but be careful not to make the test too long. Consider splitting into multiple tests.
- Is it safe to use real email addresses in tests? No, always use test addresses provided by your email service. Real addresses may receive unwanted emails and cause privacy issues. Use dynamic addresses to avoid conflicts.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- Google Chrome Helper: What It Is & How to Disable
- Fix 0x80070422 on Windows Server (Step-by-Step)
- How to Troubleshoot a Malfunctioning Driver on Windows
- How to Create Folders in Microsoft Outlook
- Fix Status Range List Conflict 0xc0000282 in Windows
- Fix Software Not Uninstalling on Windows 10