Why Email and Notification Testing Matters
Emails and notifications are critical communication channels between an application and its users. A broken password reset email means users cannot recover their accounts. A missing order confirmation erodes trust. A poorly rendered marketing email damages brand perception.
Despite their importance, email and notification testing is often overlooked because these features involve external systems and are harder to automate than UI testing.
Types of Emails to Test
Transactional Emails
Triggered by user actions — highest priority for testing:
| Email Type | Critical Checks |
|---|---|
| Registration confirmation | Link works, correct user data |
| Password reset | Token expires, one-time use, timely delivery |
| Order confirmation | Correct items, prices, order number |
| Payment receipt | Accurate amounts, tax, payment method |
| Account changes | Correct notification of what changed |
| Two-factor authentication | Code is valid, expires correctly |
Marketing Emails
Sent to groups of users:
- Personalization tokens resolve correctly (name, preferences)
- Unsubscribe link works and is prominent
- CAN-SPAM/GDPR compliance (physical address, sender identification)
- Dynamic content renders based on user segments
System Notifications
Automated alerts:
- Error notifications to admins
- Scheduled report emails
- Threshold alerts (disk space, API limits)
Email Testing Environment
Tools for Capturing Test Emails
Never send test emails to real addresses. Use email sandboxes:
| Tool | Type | Key Features |
|---|---|---|
| Mailtrap | Cloud service | SMTP inbox, HTML preview, spam analysis |
| Mailhog | Self-hosted | Local SMTP server, web UI |
| Ethereal Email | Free service | Disposable SMTP accounts |
| AWS SES Sandbox | Cloud | AWS-integrated sandbox mode |
Setting Up Mailhog Locally
# Install (macOS)
brew install mailhog
# Run
mailhog
# SMTP: localhost:1025
# Web UI: http://localhost:8025
Configure your application to use localhost:1025 as the SMTP server in test environments.
What to Test in Emails
Delivery
- Email arrives within expected time (transactional: <30 seconds, marketing: <5 minutes)
- Email is not caught by spam filters (check spam score)
- Correct recipient (To, CC, BCC fields)
- Correct sender (From address matches expected)
- Reply-To address is correct
Content
- Subject line is correct and personalized
- Body content matches the trigger action
- Dynamic data is correct (names, amounts, dates, order numbers)
- Links are valid and point to correct destinations
- Unsubscribe link is present and functional
- Footer contains required legal information
HTML Rendering
Email HTML is notoriously limited compared to web HTML:
| Works Everywhere | Unreliable | Avoid |
|---|---|---|
| Tables for layout | Flexbox | JavaScript |
| Inline CSS | External CSS | CSS Grid |
| Basic images | SVG | Video |
<a> links | CSS animations | Custom fonts (mostly) |
Test rendering in at least:
- Gmail (web and mobile)
- Apple Mail (macOS and iOS)
- Outlook (desktop and web)
- Yahoo Mail
Security (Transactional Emails)
- Password reset tokens are one-time use
- Tokens expire after appropriate time (1 hour typical)
- Tokens are cryptographically secure (not sequential)
- Old tokens are invalidated when new one is requested
- Links use HTTPS
- No sensitive data exposed in email body (full credit card numbers, passwords)
Exercise: Testing a Registration and Password Reset Flow
You are testing the email notifications for a web application’s authentication system.
Scenario 1: Registration Confirmation Email
| Step | Action | Expected Result |
|---|---|---|
| 1 | Register with email test@example.com | Confirmation email arrives within 30 seconds |
| 2 | Check email subject | “Confirm your email address” or similar |
| 3 | Check sender | noreply@yourapp.com |
| 4 | Check body content | Contains user’s name, confirmation link |
| 5 | Click confirmation link | Account is activated, redirects to dashboard |
| 6 | Click confirmation link again | Shows “already confirmed” message, not an error |
| 7 | Register with same email | Should not send new confirmation (account exists) |
Scenario 2: Password Reset Email
| Step | Action | Expected Result |
|---|---|---|
| 1 | Request password reset for test@example.com | Reset email arrives within 30 seconds |
| 2 | Check reset link | Contains unique token, uses HTTPS |
| 3 | Click reset link | Shows password reset form |
| 4 | Set new password | Password changed, confirmation email sent |
| 5 | Click the same reset link again | Token expired/used — shows error, not reset form |
| 6 | Request reset for non-existent email | Same response as valid email (security: no email enumeration) |
| 7 | Request multiple resets | Only the latest token works |
| 8 | Wait 1+ hour, click link | Token expired — shows appropriate message |
Scenario 3: Notification Preferences
| Step | Action | Expected Result |
|---|---|---|
| 1 | Disable marketing emails in settings | Marketing emails stop |
| 2 | Trigger a transactional event | Transactional email still arrives (cannot be disabled) |
| 3 | Click unsubscribe in marketing email | Preferences updated, confirmation shown |
| 4 | Re-enable marketing emails | Marketing emails resume |
Solution: Common Bugs in Email Testing
Bug 1: Password reset link reusable The reset token was not invalidated after use, allowing anyone with the link to reset the password multiple times. Severity: Critical (security).
Bug 2: Email enumeration via password reset Different response messages for existing vs non-existing emails (“Email sent” vs “Email not found”). This allows attackers to discover valid accounts. Fix: Always show the same message regardless of whether the email exists.
Bug 3: Confirmation link expired too quickly Token expired after 10 minutes, but some email providers delay delivery by 5+ minutes. Users could not confirm. Fix: Extend to 24 hours for confirmation emails.
Bug 4: HTML broken in Outlook
Email used <div> layout that Outlook does not support. Product images were stacked vertically instead of in a grid. Fix: Use <table> layout for email HTML.
Bug 5: Unsubscribe link missing in marketing emails CAN-SPAM violation — all commercial emails must include an unsubscribe mechanism. This can result in legal penalties and ISP blocking.
Bug 6: Dynamic content showing raw template variables “Hello {{user.firstName}}” instead of “Hello Alice” when the user profile had no first name. Fix: Add fallback text (e.g., “Hello there”).
Push Notification Testing
What to Test
| Aspect | Checks |
|---|---|
| Permission | Prompt appears once, respects user choice |
| Delivery | Arrives within expected time window |
| Content | Title, body, icon are correct |
| Action | Clicking notification opens correct screen |
| Grouping | Multiple notifications stack properly |
| DND mode | Notifications respect Do Not Disturb settings |
| Background | Notifications arrive when app is in background |
| Offline | Notifications queued and delivered when back online |
In-App Notification Testing
- Notification badge count updates in real-time
- Marking notification as read decreases the count
- Notification links navigate to the correct page
- Old notifications are accessible in notification history
- Notifications appear for the correct user (multi-user testing)
Key Takeaways
- Never use real email addresses for testing — always use email sandboxes like Mailtrap or Mailhog
- Transactional emails require security testing (token expiration, one-time use, no email enumeration)
- HTML email rendering varies dramatically across clients — test in Gmail, Outlook, and Apple Mail at minimum
- Push notifications need testing for permission flow, delivery timing, and DND mode interaction
- Always verify unsubscribe functionality and legal compliance (CAN-SPAM, GDPR)
- Test edge cases: what happens when dynamic data is missing, when emails bounce, when notifications queue