Email & Notification Testing
Email confirmation broken in production. Password reset never arrived. Promotion was sent twice. Test email delivery, content rendering, and notification flows systematically to catch these before customers do.
The Hook — Email Failure in Production
An Auckland SaaS company released a new sign-up flow and deployed to production on Friday. By Monday, 200 users complained they never received their welcome email. The feature had passed QA but nobody had verified that the SMTP settings in production matched the test environment. Worse, the password reset token in the email worked only in the test environment, not production. Users were locked out.
Another retailer sent a discount email to 50,000 customers. The email client was Gmail. The link in the email was tracked with a redirect that Gmail flagged as unsafe. The link was hidden in the inbox as a warning. Click-through rate dropped 60%. The designer had never tested how different email clients render links.
Email is asynchronous, silent, and invisible to manual testing. You click "send," assume it works, and move on. It doesn't work. It's one of the most common failure points in testing and one of the easiest to fix.
The Rule
Email and notification testing verifies that:
- Messages are sent: The email/SMS/notification is actually delivered to the correct recipient.
- Content is correct: Subject, body, sender name, and formatting are accurate.
- Links work: All URLs in the email/notification are clickable and route to the correct page.
- Dynamic content works: Personalization (username, order number, link tokens) is correctly inserted.
- Rendering is consistent: Email looks correct in the client where it's most likely to be opened (Gmail, Outlook, Apple Mail).
- Timing is correct: Email arrives within the expected window (minutes, not hours).
Email & Notification Basics
SMTP Protocol Overview
Email is sent via SMTP (Simple Mail Transfer Protocol). Your application connects to an SMTP server (e.g., SendGrid, Mailgun, AWS SES) and hands off the message. The server delivers it to the recipient's mail server. You need to verify:
- From address: Is the sender address real and verified with your SMTP provider?
- Authentication: Does your app provide the correct API key or username/password?
- Headers: SPF, DKIM, DMARC records are configured so ISPs recognize the email as legitimate (not spam).
Email Anatomy
An email has layers:
- Headers: From, To, Subject, Date, Message-ID, MIME-Version. Headers tell the mail server and client what to do.
- Body (plain text): Fallback content for old clients or screen readers. Often ignored by testers.
- Body (HTML): Formatted, styled version. What most users see.
- Attachments: Files embedded in the email.
The problem: HTML email is constrained. You can't use modern CSS (no flexbox, no grid, no media queries). Font support is limited. Inline styles are required. Testing on multiple clients is mandatory because each interprets HTML differently.
Email Rendering Differences
Gmail strips CSS from the <head> and only respects inline styles. Outlook uses Word's HTML rendering engine (broken in many ways). Apple Mail is webkit-based. Thunderbird follows standards but few marketers test it. A button styled in CSS looks fine on Apple Mail but invisible on Outlook. Always verify in the actual clients your users prefer.
Testing Approaches
Manual Testing: Check Your Inbox
Sign up on your app, trigger the welcome email, go to your email inbox, open the email, click the link. Basic but essential.
Manual Email Verification Checklist
- ☐ Email arrives in inbox (not spam folder)
- ☐ Sender name and address are correct
- ☐ Subject line matches what you expect (check for typos, variable replacement)
- ☐ Body text is complete and renders correctly
- ☐ All links are clickable and point to the right URL
- ☐ Dynamic content (name, order number, token) is inserted correctly
- ☐ Images load (if included)
- ☐ Footer and branding look professional
- ☐ Unsubscribe link is present (legal requirement)
Tools: MailHog, Mailtrap, Temporary Email Services
MailHog: A local SMTP server that captures all outgoing email. Emails don't leave your machine. Useful during development. Run locally, point your app to localhost:1025, and check the MailHog web UI at localhost:8025. You see every email sent, including headers and raw content.
# Start MailHog
mailhog
# Then send a test email from your app
# Check http://localhost:8025 in your browser
Mailtrap: A cloud-based inbox for testing. Sign up, get SMTP credentials, point your app to Mailtrap's server. All emails sent during testing are captured and stored. You inspect them in the web UI. Cheap or free for light usage.
Temporary Email Services: Services like Mailinator or 10minutemail give you a throwaway inbox. Send an email there, view it in the service. Good for quick ad-hoc testing but not for automation.
Production Testing: Use a real email account (personal Gmail, staging domain inbox) to see how the actual email clients render your message. Test in Gmail, Outlook, and Apple Mail. This catches rendering bugs that no sandbox environment will show.
Verifying Dynamic Content
Email often includes variables: Hi {username}, Your order #{order_id}, Reset your password: {reset_token}. Test multiple scenarios:
- Variable is correctly replaced with the right value (sign up as "Alice," verify email says "Hi Alice")
- Variable is present and not blank (sign up with no name, verify email doesn't say "Hi ")
- Special characters don't break rendering (name with accents, apostrophes, symbols)
- Long values are handled (20-character username, very long email address)
Common Email Scenarios
Scenario 1: Password Reset Workflow
Steps:
- Go to login page, click "Forgot password"
- Enter email address
- Check email for reset link
- Click link (verify it's a valid, secure token)
- Set new password
- Log in with new password
What to verify:
- Email arrives within 1–5 minutes
- Reset token is unique per request (two reset emails have different tokens)
- Token expires after a set time (usually 24 hours)
- Token works only once (use it, try again, should be rejected)
- Email subject is clear ("Reset Your Password," not "RESET_PASSWORD")
Scenario 2: Transactional Email (Order Confirmation)
What to verify:
- Email sent immediately after purchase (< 1 minute)
- Order number in email matches order in dashboard
- Item list, quantities, prices are correct
- Total amount matches invoice
- Shipping address is correct (not billing address)
- Email footer has support contact information
- Order tracking link (if available) works
Scenario 3: Account Verification Email
What to verify:
- Email sent immediately after sign-up
- Verification link is correct and unique
- Clicking link marks account as verified
- Resend link functionality works (request new code)
- Old code is invalidated after new code is sent (prevent brute force)
- User is blocked from certain actions until verified (if required)
Push Notifications & SMS Testing
Push Notifications on Mobile
Push notifications appear on iOS and Android devices even when the app is closed. Testing requires real or emulated devices.
- iOS: Build the app with a development certificate, deploy to an iPhone via Xcode, trigger notification from your backend
- Android: Run the app in an Android emulator (Android Studio), use Firebase Cloud Messaging console to send a test notification
- What to verify: Notification appears in the notification center, title and body are correct, deep link (if present) routes to the right screen, notification can be dismissed, tapping opens the app and handles the link correctly
SMS Testing
SMS is sent via a provider like Twilio or Vonage. Unlike email, it's synchronous and arrives in seconds.
- Use your personal phone number during testing
- Verify SMS arrives within 30 seconds
- Check for message splitting (long SMS are sent as multiple messages; verify they concatenate correctly on the receiving end)
- Verify links in SMS are short and clickable
- Test internationalization (different carriers, different countries)
Email & Notification Checklist
Pre-Send Checks (Development):
- ☐ Email template is formatted (no broken HTML, all variables are placeholders)
- ☐ Test email via MailHog or Mailtrap
- ☐ All links are correctly formed (no typos, correct environment)
- ☐ From address and sender name are set
- ☐ Subject line is descriptive and matches requirement
Testing Across Email Clients:
- ☐ Gmail (web, mobile app)
- ☐ Outlook (web, desktop client if enterprise)
- ☐ Apple Mail (macOS, iOS)
- ☐ Thunderbird or another standard client
Dynamic Content Testing:
- ☐ Variable replaced correctly (test with different inputs)
- ☐ No blank fields or broken syntax when variable is missing
- ☐ Special characters don't break rendering
- ☐ Long values are truncated or wrapped gracefully
Scenario-Specific:
- ☐ Confirmation emails: Token is unique and expires correctly
- ☐ Transactional emails: Order/invoice details match backend
- ☐ Push notifications: Appear on both iOS and Android, deep link works
- ☐ SMS: Arrives, links are clickable, no message splitting issues
Common Mistakes
❌ Testing Only in MailHog, Not Real Email Clients
MailHog shows you what was sent, but not how it will render. Email client rendering varies wildly. A button styled perfectly in MailHog may be invisible in Outlook. Test in actual Gmail, Outlook, and Apple Mail accounts.
❌ Not Verifying Production SMTP Settings
Your test environment uses MailHog. Production uses SendGrid. They have different configurations. Verify production SMTP settings are correctly deployed before releasing. Wrong API key = emails never arrive.
❌ Assuming Links Work Without Clicking Them
Copy-paste the URL from the email into your browser. Don't assume. Links are broken, tokens are wrong, environment mismatches happen. Click every single link in every email you send.
❌ Not Testing Duplicate Prevention
Click "forgot password" twice quickly. You should get two different reset codes or the first one should be invalidated. If both codes work, security flaw. If the system sends two copies of the same code, it's annoying.
❌ Forgetting to Check Spam Folders
Email may arrive in spam. Check. A missing SPF/DKIM record or a newly registered domain often triggers spam filters. If your email is consistently junked, adjust headers or ask your email provider why.
Self-Check
- You send a password reset email. The link has a token. How do you verify the token is secure?
The token should be unique per request, long (32+ characters), random, and expire after a fixed time (e.g., 24 hours). Request two reset emails; they should have different tokens. Try the first token after using the second; it should be rejected. - Your order confirmation email looks perfect in Gmail but broken in Outlook. Why?
Gmail and Outlook render HTML differently. Outlook uses Word's engine and has poor CSS support. Flexbox, grid, modern properties don't work. Inline styles are required. Test in both clients before releasing. - A user signs up and says they never got the confirmation email. How do you debug?
Check: (1) Is the email in spam? (2) Does the log show the email was sent? (3) Is the recipient address correct in the database? (4) Did the SMTP provider reject it? Check your MailHog or Mailtrap logs, check production SMTP logs, check the recipient's spam folder. - You test a password reset email, click the link, reset the password, try the link again. What should happen?
The link should be invalid. The token was consumed. Trying to use it again should show an error like "Link expired or already used." This prevents someone forwarding the link to an attacker. - Your notification says "Hi {username}" but the field is blank. Where's the bug?
The variable {username} wasn't replaced. Either the variable name in the template doesn't match the database field, or the variable was null. Check the template code and the data passed to it.