How-to

Cypress OTP email testing without a polling loop

Cypress cannot open a mailbox, so email steps usually mean a plugin, a task, and a retry loop. With an Inflovy inbox the test uses cy.request twice: once to create the inbox and once to wait for the email.

Last updated September 18, 2026

Who this is for

1Cypress suites covering signup, password reset, 2FA-by-email

2Teams that gave up on Gmail API plugins

3QA engineers who want the email visible after a failed run

In short

In Cypress, create an Inflovy inbox with cy.request, type inbox.emailAddress into the signup form, then cy.request the wait endpoint with timeout=30 and a Cypress timeout above it. The response carries the message and verificationCode, so the test types the code and continues. No plugin, no task, no sleep.

Why OTP steps are painful in Cypress

Cypress runs in the browser; reading a mailbox needs a Node task plus a mail client and credentials.

Gmail "+" aliases leak your real address, sites strip the "+", and Gmail silently de-duplicates identical test emails.

cy.wait(5000) hides the real problem and still flakes on a slow email.

Shared QA mailboxes mean the wrong test reads the wrong code.

The Inflovy way

cy.request to POST /v1/inboxes gives the test a private address.

cy.request to the wait endpoint returns the message as soon as it lands; set the Cypress timeout above the wait timeout.

verificationCode is on the response; type it and move on.

Every message is kept in the dashboard for the plan’s retention, so a red run can be inspected.

Step by step

How to do it

  1. 1

    Store the key

    Add INFLOVY_API_KEY to cypress.env.json or CI secrets (Pro or Team workspace).

  2. 2

    Create the inbox

    cy.request({ method: "POST", url: api + "/inboxes", headers }) and keep body.id and body.emailAddress.

  3. 3

    Run the flow

    cy.visit("/signup"), type the address, submit.

  4. 4

    Wait and type the code

    cy.request the wait endpoint with timeout=30 and { timeout: 40000 }; type res.body.message.verificationCode.

Cypress sample
const api = 'https://api.inflovy.com/v1';
const auth = { Authorization: `Bearer ${Cypress.env('INFLOVY_API_KEY')}` };

cy.request({ method: 'POST', url: `${api}/inboxes`, headers: auth }).then(({ body: inbox }) => {
  cy.visit('/signup');
  cy.get('#email').type(inbox.emailAddress);
  cy.contains('Sign up').click();

  cy.request({ url: `${api}/inboxes/${inbox.id}/messages/wait?timeout=30`, headers: auth, timeout: 40000 })
    .its('body').then((res) => {
      expect(res.status).to.eq('received');
      cy.get('#code').type(res.message.verificationCode);
      cy.contains('Verify').click();
    });
});

Needs an API key from Settings → API on a Pro or Team workspace. Full reference at /docs/api.

Comparison

Gmail plugin versus an Inflovy inbox.

The moving parts each approach adds to a Cypress project.

NeedGmail / IMAP pluginInflovy
Setupcypress.config task, OAuth client, refresh token, a plugin to maintain.One environment variable with the API key.
WaitingA recursive task that polls every few seconds.One request that returns when the email arrives (1–60 s).
Extracting the codeRegex over the HTML body in the task.res.body.message.verificationCode.
IsolationOne mailbox for the whole suite.One inbox per test, deleted in afterEach.
FAQ

Questions people ask before switching.

Short answers. Inflovy is a receive-only test inbox for developers and QA teams; it does not replace your mailbox or send anything.

Why set a Cypress timeout above the wait timeout?

cy.request defaults to 30 seconds. wait?timeout=30 can legitimately take 30 seconds, so give cy.request a larger timeout (for example 40000 ms) or the test fails before the endpoint answers.

Does this work with magic links instead of codes?

Yes. message.links[] lists every link in the email; cy.visit the one you need. verificationCode is null when there is no code.

Can teammates see the emails my tests received?

Yes. Inboxes created through the API belong to the workspace and appear in the dashboard for every member, for the plan’s retention period.

Related guides

Nearby workflows and comparisons, so you can evaluate the right one without guessing.

Two cy.request calls. No plugin.

Copy the sample above into a spec, add an API key, and the OTP step stops flaking.