Using MailFlat with Cypress
Read real verification emails from a Cypress test by moving the API calls into a Node task, where network access belongs.
How it fits together
Cypress specs run in the browser, so calling an external API straight from a test is awkward and CORS-bound. The supported way is a Node task: register the MailFlat calls in setupNodeEvents once, then use cy.task from any spec.
Install
npm i -D @mailflat/sdk
Register the tasks
setupNodeEvents runs in Node, so the API key never reaches the browser.
// cypress.config.js
const { defineConfig } = require("cypress");
const { MailFlat } = require("@mailflat/sdk");
const mf = new MailFlat({ apiKey: process.env.MAILFLAT_API_KEY });
module.exports = defineConfig({
e2e: {
setupNodeEvents(on) {
on("task", {
async createInbox() {
const inbox = await mf.create({
prefix: `cy-${Date.now().toString(36)}`,
retentionHours: 2,
});
return inbox.address;
},
async waitForOtp(address) {
return mf.inbox(address).waitForOtp({ timeout: 60000 });
},
async deleteInbox(address) {
await mf.inbox(address).delete();
return null;
},
});
},
},
});
The spec
cy.task returns a Cypress chainable, so it slots into the normal command chain.
// cypress/e2e/signup.cy.js
describe("signup", () => {
let address;
beforeEach(() => {
cy.task("createInbox").then((a) => { address = a; });
});
afterEach(() => cy.task("deleteInbox", address));
it("accepts a real verification code", () => {
cy.visit("/signup");
cy.get("#email").type(address);
cy.get("#submit").click();
cy.task("waitForOtp", address).then((otp) => {
cy.get("#code").type(otp);
});
cy.url().should("include", "/dashboard");
});
});
Worth knowing
A task must return a value or null — returning undefined makes Cypress fail with a confusing error.
Cypress default command timeout is 4 seconds; waiting happens inside the task, so it is not affected.
See also
JavaScript
Zero dependencies, built on the runtime's own fetch. Drop it into Jest, Vitest, Playwright, Cypress or a Node script.
One-time codesMailFlat pulls the verification code out of the message for you and hands it over as a field, so your test never runs a regex against an email body.
Testing & CIGive every CI run its own real inbox: the four API calls, parallel shards, teardown, and how to keep an end-to-end suite fast and honest.