---
title: "Test email verification and login codes in Cypress · Proxy Mail QA"
description: "A Cypress test that signs up with a fresh inbox and opens the verification link or enters the code, using the proxymail-qa package in Cypress tasks."
url: https://proxymail.qa/solve/cypress-email-tests
---

1. [Home](https://proxymail.qa/)
2. [What we solve](https://proxymail.qa/solve)

# Test sign-up emails in Cypress

To test email verification in Cypress, register a few tasks that create a fresh address and wait for its email, then call them from your spec: sign up, wait for the link or code, finish the flow. Tasks run in Node, so the proxymail-qa package works there as it does anywhere. It runs on the Free plan, locally and in CI.

Updated October 17, 2026

## Set up

Install the [proxymail-qa](https://www.npmjs.com/package/proxymail-qa) package and put an [API key](https://proxymail.qa/docs/api-keys) in `PROXYMAIL_QA_API_KEY` in the environment Cypress runs in. The Free plan is enough.

Terminal

```bash
npm install --save-dev proxymail-qa

```

## Register the tasks

cypress.config.ts

```ts
import { defineConfig } from 'cypress';
import { ProxyMailQA } from 'proxymail-qa';

export default defineConfig({
  e2e: {
    setupNodeEvents(on) {
      const qa = new ProxyMailQA(); // reads PROXYMAIL_QA_API_KEY
      on('task', {
        createAddress: () => qa.createAddress({ persona: true }),
        waitForLink: ({ address, since }: { address: string; since: string }) => qa.waitForLink(address, { type: 'verify', since }),
        waitForCode: ({ address, since }: { address: string; since: string }) => qa.waitForCode(address, { since }),
        deleteAddress: (address: string) => qa.deleteAddress(address).then(() => null),
      });
    },
  },
});

```

## The test

cypress/e2e/signup.cy.js

```js
it('verifies the email', () => {
  cy.task('createAddress').then(({ address }) => {
    const since = new Date().toISOString();
    cy.visit('/signup');
    cy.get('[name=email]').type(address);
    cy.contains('Sign up').click();
    cy.task('waitForLink', { address, since }, { timeout: 35000 }).then(({ value }) => cy.visit(value));
    cy.task('deleteAddress', address);
  });
});

```

For a code, call the `waitForCode` task the same way and type its `value` into the form. `since` makes the wait ignore anything sent before the form was submitted, so a retried test never reads an old email. Match the selectors and routes to your app.

## Check the email, not just the link

Add tasks for the checks you want, such as one verification email rather than two, or the link going to staging:

TypeScript

```ts
countEmails: ({ address, since }: { address: string; since: string }) => qa.countEmails(address, { since, type: 'link' }),
checkEmail: ({ address, since }: { address: string; since: string }) => qa.checkEmail(address, { since, type: 'link', expectHost: 'staging.example.com' }),

```

`checkEmail` returns verdicts on SPF, DKIM and DMARC, links to localhost or plain http, where the link goes and more, never the email itself; assert that its `failed` list is empty.

## Run it in CI

Store the key as a CI secret named `PROXYMAIL_QA_API_KEY`. In GitHub Actions, the [Proxy Mail QA action](https://proxymail.qa/docs/ci#a-report-on-the-pull-request) also posts a report of the run’s emails on the pull request: which arrived, how fast, and which never came.

.github/workflows/e2e.yml

```yaml
      - uses: aaquib90/proxymail-qa-action@v1
        with:
          api-key: ${{ secrets.PROXYMAIL_QA_API_KEY }}
      - run: npx cypress run
        env:
          PROXYMAIL_QA_API_KEY: ${{ secrets.PROXYMAIL_QA_API_KEY }}

```

More in the [Cypress docs](https://proxymail.qa/docs/cypress), [Node.js client](https://proxymail.qa/docs/node) and [Running in CI](https://proxymail.qa/docs/ci).

## Try it on your next sign-up test

Free plan, no credit card. Create an address and watch the code or link arrive.

[Create a free account](https://app.proxymail.qa/?mode=signup)

## Questions

### Why use cy.task instead of cy.request?

A wait can hold for up to 30 seconds while the email arrives, and the package handles retries, time filters and clear errors. In a task it runs in Node with your API key, which never reaches the browser. cy.request works too, against the REST API.

### How long does a wait take?

Usually a few seconds: it returns as soon as the email arrives, and gives up after 30\. Cypress allows a task 60 seconds by default; the example sets 35, so a missing email fails the test sooner.

### What if the email never arrives?

The task fails with a message saying why as far as Proxy Mail QA can tell: most often the app's email provider is in sandbox or test mode and only sends to verified addresses. Fix the sending side rather than waiting longer.

## Related guides

- [Test sign-up and email verificationA fresh, private address for every sign-up test, with the verification link or code ready the moment it lands.](https://proxymail.qa/solve/email-verification-testing)
- [Test OTP and one-time login codesCodes pulled out of the email with a Copy button and a countdown when the email says how long they last.](https://proxymail.qa/solve/otp-code-testing)
- [Test magic links and passwordless sign-inSingle-use links that are never opened or prefetched on our side, so they still work when you click them.](https://proxymail.qa/solve/magic-link-testing)
- [Test password reset emailsRequest, receive and use reset links, and keep the new password saved next to the test account.](https://proxymail.qa/solve/password-reset-testing)
- [Stop sharing one Gmail inbox for QAPrivate, disposable addresses for every tester instead of one shared mailbox and a pile of plus-addresses.](https://proxymail.qa/solve/shared-test-inbox)
- [Take QA notes by voice with Wispr FlowDictate what each test account is for, its state and what you found, straight into its notes, in seconds.](https://proxymail.qa/solve/voice-notes-wispr-flow)
- [Verification link points to localhost:3000Why emails from staging link to localhost, how to fix it in Supabase, Firebase and other stacks, and how we flag it.](https://proxymail.qa/solve/localhost-links)
- [Test sign-up emails in PlaywrightA complete Playwright test for sign-up codes and links, from a fresh inbox to the report on the pull request.](https://proxymail.qa/solve/playwright-email-tests)
- [Test sign-up emails with pytestA complete pytest test for sign-up codes and links, with Playwright for Python or Selenium and a one-file helper.](https://proxymail.qa/solve/pytest-email-tests)

[Built your app with an AI tool? Pick yours](https://proxymail.qa/built-with)
