blog
How to test that an email is received using Cypress JS.
Learn to automate email testing with Cypress JS and MailSlurp's free email testing platform. Improve your web app's email functionality!
A Cypress test can click "Send email" successfully without proving that the message reached the right person. To check receipt, give the test its own inbox, trigger the send, then wait for the message belonging to that action.
MailSlurp provides private email addresses and message-wait APIs. The browser continues testing your application while MailSlurp returns the delivered email, including its recipient, subject and body. Use those fields to prove that the notification belongs to this test.
Set up the email command
Install the official Cypress plugin and follow its configuration steps for cy.mailslurp(). It returns the MailSlurp client through Cypress's command queue. Keep API keys in your test configuration or CI secrets rather than in committed spec files.
npm install --save-dev cypress cypress-mailslurp
Import cypress-mailslurp from cypress/support/e2e.js. The plugin documentation covers current environment-variable options and a connection test before you add application assertions.
Wait for the email caused by this test
This example uses a notification form in your application. Replace the URL, email field, button label and subject with its actual values. The message must include the unique order reference created by your test. A fixed sample reference can be used while adapting the page, but independent test runs should create their own order.
describe("order notification email", () => {
let inbox;
beforeEach(() => {
inbox = undefined;
cy.mailslurp()
.then(mail => mail.createInboxWithOptions({ expiresIn: 600_000 }))
.then(value => { inbox = value; });
});
afterEach(() => {
if (inbox) {
cy.mailslurp().then(mail => mail.inboxController.deleteInbox({ inboxId: inbox.id }));
}
});
it("receives the current order notification", () => {
const orderReference = "order-under-test"; // Replace with this test's order ID.
cy.visit("/orders/notify");
cy.get('input[name="email"]').type(inbox.emailAddress, { log: false });
cy.then(() => {
const since = new Date();
cy.contains("button", "Send notification").click();
return cy.mailslurp().then({ timeout: 75_000 }, mail =>
mail.waitController.waitForMatchingFirstEmail({
inboxId: inbox.id, since, timeout: 60_000, unreadOnly: false,
matchOptions: {
matches: [{ field: "SUBJECT", should: "CONTAIN", value: orderReference }],
},
}),
);
}).then(email => {
expect(email.to).to.include(inbox.emailAddress);
expect(email.subject).to.include(orderReference);
expect(email.body).to.include(orderReference);
});
});
});
The wait returns the full email. Keep that object for later assertions instead of making a second unread-only wait: opening a message can change its read state. A fresh inbox, send timestamp and order reference identify this request; unread status alone does not.
Continue when the email contains a code or link
For signup, receipt is the halfway point. Extract the verification code or intended application link, submit it in the same test and check the verified account. The complete Cypress email guide includes OTP, magic-link and password-reset workflows with cleanup.
Keep the 60-second email wait inside a longer Cypress command budget. A fixed cy.wait(5000) only delays the runner; it does not tell you whether the message arrived. If the wait fails, check the recipient address, subject reference and send time before increasing timeouts. The wait documentation separates delivery delays, mismatched filters and API authentication failures.