Integration testing guide
MailSlurp gives QA and release teams real inboxes, real phone numbers, deterministic wait methods, and message quality tooling. The goal is not just "can I receive one email" but "can I prove the whole workflow behaved correctly before we ship."

What teams use MailSlurp for
- Signup and verification flows that send email or SMS
- Password reset and magic-link journeys
- OTP and MFA checks
- Notification and transactional email assertions
- Release gates for delivery, rendering, and message quality
Core release workflow
1. Create isolated inboxes or phone numbers per run
Fresh resources keep tests deterministic and make it easy to trace failures back to one build, one suite, or one campaign.
const inbox = await mailslurp.createInbox();
// { id: '123', emailAddress: '123@mailslurp.com' }
Best practice:
- Use one inbox per test run or scenario when you can.
- Use expiring inboxes for short-lived suites.
- Keep naming and tags aligned with your CI pipeline or release identifier.
2. Wait for real messages instead of sleeping
MailSlurp wait methods let you block until a matching message arrives. This is what removes brittle sleep() calls from browser or API tests.
// wait for the latest unread sms
const [sms] = await mailslurp.waitController.waitForSms({
waitForSmsConditions: {
count: 1,
unreadOnly: true,
phoneNumberId: phoneNumber.id,
timeout: 30_000
}
});
// extract a code from body with regex
expect(sms.body).toContain('Your code: 123');
const [, code] = /.+:\s([0-9]{3})/.exec(sms.body);
expect(code).toEqual('123');
Use wait methods when you need to assert:
- a message arrived
- the recipient was correct
- the subject or sender matched expectations
- a code or link can be extracted and used in the next test step
3. Open, inspect, and validate message content
After a message lands, teams usually do one of three things:
- extract links or OTP codes
- open preview URLs for visual checks
- validate content quality such as links, images, and supported email features
const {
// load this in a browser to view teh rendered HTML and interact with it
plainHtmlBodyUrl,
// or view full SMTP message
rawSmtpMessageUrl
} = await mailslurp.emailController.getEmailPreviewURLs({
emailId: email.id!
});
const { result } =
await mailslurp.emailController.checkEmailBodyFeatureSupport({
emailId: email.id,
});
expect(result.detectedFeatures).toContain(
EmailFeatureSupportResultDetectedFeaturesEnum.html_doctype
);
expect(
result.featurePercentages.find(
(it) =>
it.status === EmailFeatureSupportStatusPercentageStatusEnum.SUPPORTED
)?.percentage
).toBeGreaterThan(50);
Then deepen the check with:
- Email audit for broken links, images, and quality review
- Device previews for client and viewport differences
- Email compatibility for feature support checks
4. Add release and post-send confidence checks
Single-message waits are useful in tests. Release teams usually add broader controls before launch:
- Deliverability tests for expectation-based pass/fail checks across inbox or phone cohorts
- Campaign Probe for live campaign capture and review
- Domain Monitor and Reputation for sender-health monitoring
Example projects
Loading examples...
Framework starting points
Practical patterns that reduce flakiness
- Set explicit wait timeouts that reflect real delivery behavior in your environment.
- Isolate inboxes or phone numbers so tests do not compete for the same messages.
- Match on concrete fields such as recipient, subject, or unread status.
- Keep message extraction helpers in shared test utilities instead of duplicating regex and parsing logic.
- Use broader delivery checks before major releases instead of relying only on one test inbox.