This article provides an overview of various strategies for testing email-dependent flows in automated end-to-end tests. It examines practical approaches – from simple workarounds to dedicated tools – detailing their implementation, benefits, limitations, and best practices for integration into development pipelines. These strategies complement other testing methods like integration tests and system testing to ensure complete coverage.
In software development, email communication is a fundamental requirement for many applications. Some examples of features that depend on email are account activation, password resets, magic links (passwordless login), and one-time passwords (OTP). These features present unique testing challenges compared to more straightforward components of the application.
Unlike typical user flows, email-based functionality crosses system boundaries and involves integration with external infrastructure and third-party services. Automated tests need to confirm not only that emails are generated, but also that they are delivered, readable, and actionable for recipients.
An email is an external channel, so it introduces technical complications in testing. Real email providers enforce strict security and anti-abuse mechanisms that often conflict with testing frameworks. Simultaneously, using less reliable alternatives or workarounds introduces additional forms of risk. As a result, choosing the right approach for verifying email flows requires balancing realism, maintainability, and coverage while considering all technical constraints.
One way to test email-related flows is by using real email providers (e.g., Gmail, Outlook). In this case, the test uses a real email address and then opens its inbox to fetch email content. The last step requires UI interaction with the email app. This method validates the entire delivery pipeline: from message generation to receipt in a real inbox. While this offers a high level of realism, it comes with significant drawbacks that make it a poor fit for automated tests.
Common issues include:
These security measures make real email services unsuitable for automated tests.
Besides the most popular email providers, there are many services that offer temporary email addresses without registration. An example of such a service is 10-minute mail, but there are many more similarly named domains. Using those email services may seem attractive due to their simplicity and ease of use.
However, they present several challenges:
These drawbacks make them unreliable for automated testing, though they might suffice for quick manual testing or PoCs.
One way to approach testing flows that depend on email is to add workarounds for testing purposes. It is still better than having no tests for these flows. While these workarounds can automate some aspects of testing, they may not provide complete coverage or replace comprehensive test cases.
An example of such a workaround is generating a static OTP code that will always work and will not actually be a single-use. In this case, the email pipeline is entirely skipped. Tests will always use a predefined value. This should only be done in test environments and, ideally, on selected accounts for security reasons. The same approach can be used for account confirmation links, redirect links, QR codes for 2FA (two-factor authentication), and many more.
If you are okay with skipping email dependency entirely, you can fetch the content of an email (e.g., a confirmation link or OTP). The most stable approach is to expose a test-only API endpoint that returns the content normally sent via email.
This enables your tests to:
This avoids dependency on external email infrastructure, improving test reliability and reducing setup complexity. However, this approach bypasses the actual email delivery layer, so it won’t catch issues like misconfigured email settings or provider downtime.
The Holy Grail of email testing is using a dedicated tool created for the sole purpose of testing email delivery. Selecting the right testing tool can streamline test automation, improve test coverage, and save time for both developers and testers. These tools help identify and fix bugs early, improving overall project outcomes. They also offer integrations with other systems and can be used across multiple projects to ensure consistent quality.
You can achieve this in two ways: by using existing solutions or by implementing your own testing inbox.
An easier option is to use a SaaS that serves as a mailbox accessible via API. This includes such solutions as Mailinator and MailSlurp.
All you need to do is:
…and you can adopt your registration tests with real inbox usage!
When considering SaaS solutions, look for automation testing features that can save time and effort, especially for large projects. In summary, careful analysis is important when choosing a testing tool to ensure it meets the needs of your team and project.
You can also set up an internal inbox using your own infrastructure with Mailpit — the natural successor to the now-discontinued MailHog. Mailpit provides a simple web UI and API for fetching email content in tests. It gives you full control and avoids vendor lock-in.
However, if you want to receive emails from external services (like SendGrid or Spotler), you’ll need to make Mailpit accessible from the internet and update your domain settings. If that’s not an option, your app must send emails directly to Mailpit — which only works if you're in charge of how emails are sent. Integrating a custom mailbox into your application's workflow ensures end-to-end validation of email processes, covering all systems and components involved.
In short, you need to:
Future<String> getAccountConfirmationUrl({
required String mailbox,
}) async {
const recoveryMailSubject = 'Your email confirmation link';
// Authenticate and fetch the latest email summary
final someApiService = SomeApiService();
final httpClient = await someApiService.authorizeUser(
'https://mailpit.my.domain/api/v1/messages',
queryParameters: {'limit': 1},
);
final response = (await httpClient.get<Map<String, dynamic>>(
'/api/v1/messages',
queryParameters: {'limit': 1},
));
// Parse the email summary
final items = response.data['messages'].first;
final id = items['ID'];
final subject = items['Subject'];
final to = items['To'].first['Address'];
// Verify this is the expected confirmation email
if (to != mailbox || subject != recoveryMailSubject) {
throw Exception();
}
// Fetch the full message to get the body
final fullResponse = (await httpClient.get<Map<String, dynamic>>(
'/api/v1/message/$id',
));
final mail = fullResponse.data['Text'];
// Use a regular expression to find the confirmation URL in the email body.
final matcher =
RegExp(r'confirm your account by clicking this link:\s*(http://\S+)');
final link = matcher.firstMatch(mail)!.group(1)!;
return link;
}
When testing features that rely on email interactions, prioritize stability and control. Avoid using live inboxes or temporary email providers in automated test suites. Instead, expose internal endpoints for test use or integrate dedicated testing tools designed for this purpose. This ensures reliable and maintainable test flows, while still validating core application behavior related to email delivery.
Approach | Main drawbacks |
---|---|
Real Email Provider | Blocks automation |
Temporary Email Service | Unreliable |
Static OTP / link on test environment | Doesn’t test dynamic content generation or delivery |
Fetch content from backend | Tests only email content generation |
SaaS | Paid plans often required |
Self-hosted inbox | High setup effort |
Approach | Main drawbacks |
---|---|
Real Email Provider | Blocks automation |
Temporary Email Service | Unreliable |
Static OTP / link on test environment | Doesn’t test dynamic content generation or delivery |
Fetch content from backend | Tests only email content generation |
SaaS | Paid plans often required |
Self-hosted inbox | High setup effort |
If you’re facing the challenges described in this article, like testing account activation, OTPs, or magic links in automated flows, you know how complex it can get. From dealing with flaky temporary email services to setting up your own testing inbox, maintaining reliable test coverage for email-based features is no small task.
At LeanCode, we can help you integrate stable and scalable email testing solutions into your Flutter app's QA pipeline. Learn more about our Flutter UI Automated Testing.