Skip to main content

Waiting for matching entities

How to wait and search for matching emails, TXT messages, and events.

info

Email and SMS delivery is asynchronous. In tests and production workflows use sufficient wait timeouts and, when needed, retry wrappers so short delivery delays do not cause flaky failures.

Waiting for messages

MailSlurp provides convenient methods for waiting for emails, SMS, and events to arrive. You can use these methods to wait for messages to arrive in tests or to wait for messages to arrive in production applications. You can also match based on the message content or metadata.

Examples

Here are examples of how to fetch emails in code.

Creating a client

First install a MailSlurp SDK for your language. Then create a client instance using your API key. You can find your API key on the MailSlurp dashboard.

const {MailSlurp} = await import("mailslurp-client");
const mailslurp = new MailSlurp({
apiKey: YOUR_API_KEY
});
const inbox = await mailslurp.createInboxWithOptions({
// expires in 5 minutes
expiresIn: 300_000
});
expect(inbox.emailAddress).toContain("@mailslurp");

Wait for latest email

The default wait method is to wait for the latest email. This means the first email matching the conditions. The client will hold a connection until the conditions are met.

// send an email
await mailslurp.inboxController.sendEmailAndConfirm({
inboxId: inbox.id,
sendEmailOptions: {
to: [inbox.emailAddress],
subject: "First email",
}
})
// wait for the first unread email to arrive
const email = await mailslurp.waitController.waitForLatestEmail({
timeout: 120_000,
inboxId: inbox.id,
unreadOnly: true
})
expect(email.subject).toContain('First email')

In this example we create an inbox and then send an email from it to itself. Next we wait for the email to arrive and make assertions about its subject.

Wait for matching emails

A more complex example is to wait for messages that match particular criteria, such as subject line.

// send two emails
for (const i of [1, 2]) {
await mailslurp.inboxController.sendEmailAndConfirm({
inboxId: inbox.id,
sendEmailOptions: {
to: [inbox.emailAddress],
// send a different message each time
subject: `Match subject test-${i}`,
}
})
}
// wait for 2 emails matching the subject with a pattern
const emails = await mailslurp.waitController.waitForMatchingEmails({
inboxId: inbox.id,
timeout: 120_000,
unreadOnly: true,
count: 2,
matchOptions: {
matches: [
{
// expect subject to contain "Match subject"
value: "Match subject",
field: MatchOptionFieldEnum.SUBJECT,
should: MatchOptionShouldEnum.CONTAIN
}
]
}
})
// assert we received two emails matching the subject
expect(emails.length).toEqual(2)
// the subjects contain the test number from the loop
expect(emails.filter(it => it.subject.includes("Match subject test-1")).length).toEqual(1)

Wait for plus-addressed emails

If you route multiple workflows through one inbox using plus aliases, match on the full recipient address in the TO field. This lets you wait for one alias deterministically without scanning large inbox result sets.

BASE_URL="https://api.mailslurp.com"
API_KEY="REPLACE_WITH_API_KEY"
INBOX_ID="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
FULL_PLUS_ADDRESS="app-user+signup-9f3a@example.test"

curl -sS -X POST "$BASE_URL/waitFor" \
-H "x-api-key: $API_KEY" \
-H "content-type: application/json" \
-H "accept: application/json" \
--data "{
\"inboxId\": \"$INBOX_ID\",
\"count\": 1,
\"countType\": \"EXACTLY\",
\"timeout\": 180000,
\"delayTimeout\": 500,
\"unreadOnly\": true,
\"sortDirection\": \"DESC\",
\"matches\": [
{
\"field\": \"TO\",
\"should\": \"CONTAIN\",
\"value\": \"$FULL_PLUS_ADDRESS\"
}
]
}"

For a full plus-address lifecycle (get/create alias, wait, then list by alias ID) see plus addressing.

Wait for email number

We can also wait for the "nth" email, an email at a particular index. This is useful for testing pagination or other scenarios where you want to wait for a particular email.

Wait for SMS

You can also wait for inbound SMS messages on phone numbers using wait-for methods.

const sms = await mailslurp.waitController.waitForLatestSms({
waitForSingleSmsOptions: {
phoneNumberId: phone.id,
timeout: 30_000,
unreadOnly: true,
},
});
expect(sms.body).toContain('Here is your code');
expect(sms.fromNumber).toEqual('+13252527014');

Waiting longer

If network latency or provider delivery varies, wrap wait calls in a small retry utility that retries up to three times until no exception is thrown.

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

async function retryWait<T>(fn: () => Promise<T>, attempts = 3, delayMs = 1500): Promise<T> {
let lastError: unknown;
for (let attempt = 1; attempt <= attempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt < attempts) await sleep(delayMs);
}
}
throw lastError;
}

const email = await retryWait(() =>
mailslurp.waitController.waitForLatestEmail({
inboxId,
timeout: 120000, // 2 minutes
unreadOnly: true,
})
);