End-to-end tests for user registration, password resets and two-factor authentication (2FA) often fail because email delivery is awkward to test. TestFly ships mailbox clients for Mailhog, Mailtrap, Outlook Graph and generic IMAP. In one automated test you can fetch incoming email, pull an OTP code out with a regex and follow the verification link.
Why email verification gets in the way of E2E tests
Almost every SaaS platform asks for email validation at signup or before sensitive operations. Automation suites usually have trouble with it:
- Public inboxes such as Gmail enforce rate limits, CAPTCHAs and bot detection.
- Developers often turn email verification off in test environments, so regressions in that flow reach production unnoticed.
- Third-party email libraries need MIME parsing, socket handling and hand-written wait loops.
TestFly puts an email() helper on BaseTest. It hides the protocol details and runs its asynchronous polling through the central WaitEngine.
Connecting to a mailbox
Local mail catchers and enterprise cloud providers are both configured in testfly.yml:
```yaml title="testfly.yml"
email:
provider: mailhog # options: mailhog, mailtrap, outlook, imap
host: localhost
port: 8025
pollIntervalSeconds: 2
timeoutSeconds: 30
## Testing signup with 2FA / OTP in Java
The example below signs up through the web UI, waits for the verification email, extracts the 6-digit OTP code and completes the login:
```java
package io.testfly.examples.email;
import io.testfly.email.EmailMessage;
import io.testfly.test.BaseTest;
import org.testng.annotations.Test;
public class EmailVerificationTest extends BaseTest {
@Test
public void testUserRegistrationWithEmailConfirmation() {
String testEmail = "user_" + System.currentTimeMillis() + "@testfly.local";
// 1. Fill registration form on WebUI
open("/register");
find("#email-input").type(testEmail);
find("#submit-btn").click();
// 2. Wait for confirmation email to arrive
EmailMessage message = email().waitForMessage(query ->
query.to(testEmail).subjectContains("Welcome to TestFly")
);
// 3. Extract OTP code or activation link via Regex
String otpCode = message.extractRegex("Your verification code is: (\\d{6})");
// 4. Enter OTP in browser and confirm
find("#otp-input").type(otpCode);
find("#verify-btn").click();
assertThat(find("#welcome-banner")).isVisible();
}
}
Supported mail providers
| Provider | Protocol | Typical Use Case |
|---|---|---|
| Mailhog | HTTP REST API | Local Docker environments, CI/CD runners |
| Mailtrap | REST API & SMTP | Staging environments, shared team sandboxes |
| Outlook Graph | Microsoft Graph API | Enterprise Office 365 test mailboxes |
| Generic IMAP | SSL/TLS IMAP | Custom corporate email servers |
FAQ
Does TestFly poll the mailbox asynchronously?
Yes. It checks the inbox at a configurable interval until a message matching your criteria arrives or the timeout runs out.
Can I extract HTML links and click them directly?
Yes. message.extractLink("Confirm Email") returns the verification URL, and you can go to it right away with open(url).
Does this work with temporary throwaway email addresses?
Yes. Generate dynamic inbox aliases (for example user+123@domain.com) and filter for them with query.to(...).
Originally published on hakangul.lovable.app.
Top comments (0)