Email Deliverability Guide
Why Emails Go to Spam
Magic link emails often end up in spam because:
- No authentication records - SPF, DKIM, DMARC not configured
- New/unknown sender - Email provider hasn’t seen your domain before
- Suspicious content - Links trigger spam filters
- Poor sender reputation - Sending domain has low trust score
- Missing plain text - HTML-only emails are suspicious
- Generic subject lines - “Sign in” looks like phishing
Quick Fixes (Already Implemented)
✅ Plain text alternative - Emails now include both HTML and plain text versions ✅ Email headers - Added Message-ID, Reply-To, X-Mailer, List-Unsubscribe ✅ Proper From address - Uses configured SMTP_FROM_EMAIL ✅ Clear subject line - “Sign in to ECTLogger” (uses your APP_NAME)
Long-Term Solutions
1. Configure Email Authentication (Recommended)
SPF Record - Allows your mail server to send on behalf of your domain:
Type: TXT
Name: @
Value: v=spf1 include:_spf.your-mail-provider.com ~all
DKIM Record - Digitally signs your emails:
- Contact your email hosting provider (server229.web-hosting.com) for your DKIM key
- Add the TXT record they provide to your DNS
DMARC Record - Tells receivers how to handle unauthenticated emails:
Type: TXT
Name: _dmarc
Value: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
2. Use a Dedicated Email Domain
Instead of sending from your main domain, use a subdomain:
- Example:
noreply@mail.ectlogger.cominstead ofnoreply@ectlogger.com - This isolates your main domain’s reputation from automated emails
3. Warm Up Your Sending Domain
- Start by sending emails to known contacts
- Gradually increase volume over days/weeks
- Monitor bounce rates and spam reports
4. Use a Transactional Email Service
Consider using a service like:
- AWS SES - $0.10 per 1,000 emails, excellent deliverability
- SendGrid - 100/day free tier, handles SPF/DKIM automatically
- Mailgun - 5,000/month free tier
- Postmark - Specialized for transactional emails
These services have established sender reputations and handle all authentication.
User Instructions
For Recipients
Add to Safe Senders List:
Gmail:
- Open the email in Spam folder
- Click “Not spam” at the top
- Star or mark as important for future emails
Outlook/Microsoft 365:
- Right-click the email
- Select “Junk” → “Not Junk”
- Check “Always trust email from [sender]”
Apple Mail:
- Select the email
- Click “Not Junk” in the banner
Create a Filter (Gmail):
- Open email, click three dots
- “Filter messages like this”
- Set: From contains
noreply@yourdomain.com - Create filter: “Never send to Spam”
For Administrators
Whitelist in Organization:
- Ask your IT department to whitelist your ECTLogger email address
- This ensures all team members receive magic links in inbox
Use Microsoft 365 Admin Center:
- Go to Exchange Admin Center
- Protection → Anti-spam
- Add your sending address to allowed senders
Use Google Workspace Admin:
- Apps → Google Workspace → Gmail
- Spam, phishing, and malware → Email whitelist
- Add your domain or specific address
Testing Deliverability
Mail-Tester.com
- Request a magic link to the test address shown on mail-tester.com
- Click “Check your score”
- Review detailed spam analysis
- Fix issues highlighted in report
Check DNS Records
# Check SPF
dig TXT yourdomain.com +short | grep spf
# Check DKIM
dig TXT default._domainkey.yourdomain.com +short
# Check DMARC
dig TXT _dmarc.yourdomain.com +short
Gmail Postmaster Tools
- Sign up at: https://postmaster.google.com
- Verify your sending domain
- Monitor reputation, spam rate, and delivery errors
Configuration Tips
Use Professional “From” Address
In your .env:
SMTP_FROM_EMAIL=noreply@yourdomain.com # Not gmail.com!
SMTP_FROM_NAME=YourOrg ECTLogger
APP_NAME=YourOrg Emergency Net Logger
Customize Email Content
The emails are professional and clear, but you can:
- Use your organization’s name in
APP_NAME - Set
FRONTEND_URLto your actual domain (not IP address) - Use a custom domain for both frontend and email
Common Issues
Issue: “This message was not authenticated”
Solution: Configure SPF, DKIM, DMARC records
Issue: Gmail “be careful with this message”
Solution:
- Configure email authentication
- Use your own domain (not Gmail/Outlook)
- Build sender reputation over time
Issue: Blocked by corporate firewall
Solution:
- Contact IT to whitelist your domain
- Use a recognized transactional email service
- Document that ECTLogger is an approved internal tool
Issue: Email never arrives
Solution:
- Check spam folder (you found them!)
- Verify SMTP credentials in
.env - Check server console logs for errors
- Ensure firewall allows outbound SMTP
AWS SES Setup (Recommended)
AWS SES is affordable and has excellent deliverability:
1. Create AWS SES Account
# Install AWS CLI
aws configure
# Verify email address (for testing)
aws ses verify-email-identity --email-address noreply@yourdomain.com
# Verify domain (for production)
aws ses verify-domain-identity --domain yourdomain.com
2. Add DNS Records
AWS will provide TXT records for verification and DKIM - add them to your DNS.
3. Configure ECTLogger
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_USER=your-ses-smtp-username
SMTP_PASSWORD=your-ses-smtp-password
SMTP_FROM_EMAIL=noreply@yourdomain.com
4. Request Production Access
- By default, SES is in sandbox mode (can only send to verified addresses)
- Request production access in AWS Console: Amazon SES → Account Dashboard → Request production access
Pricing: $0.10 per 1,000 emails (62,000 free emails/month if running on EC2)
SendGrid Setup (Alternative)
1. Sign Up
- Free tier: 100 emails/day forever
- No credit card required
2. Get API Key
- Settings → API Keys → Create API Key
- Select “Mail Send” permission
3. Configure ECTLogger
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASSWORD=your-sendgrid-api-key
SMTP_FROM_EMAIL=noreply@yourdomain.com
4. Verify Domain
- Settings → Sender Authentication → Domain Authentication
- Add provided DNS records
Monitoring
Check Logs
# If running as systemd service
sudo journalctl -u ectlogger -f | grep EMAIL
# Look for:
# [SUCCESS] Email sent successfully
# [ERROR] SMTP ERROR
Track Deliverability
- Monitor how many users report emails in spam
- Ask users to whitelist your sender address
- Consider user feedback on email arrival time
Regular Maintenance
- Review bounce rates monthly
- Update email content if spam rates increase
- Test deliverability with mail-tester.com quarterly
- Keep SPF/DKIM records updated if changing providers
Best Practices
- Always use your own domain - Not Gmail, Outlook, etc.
- Configure authentication - SPF, DKIM, DMARC are essential
- Keep volume reasonable - Don’t blast thousands of emails suddenly
- Monitor bounces - Remove invalid addresses
- Provide unsubscribe - Already included in email headers
- Use plain text + HTML - Already implemented
- Professional content - Clear, concise, no excessive links
- Consistent sender - Don’t change From address frequently
For Emergency Operations
If you need immediate deliverability:
- Manual whitelist: Have all users add your sender to contacts before the event
- Test emails: Send test emails days before to establish pattern
- Domain warmup: Start using the address for non-critical emails first
- Backup method: Have phone/SMS as fallback for critical notifications
- User education: Include “check spam folder” in training materials
Troubleshooting
Connection Refused Error
If you see ERR_CONNECTION_REFUSED in the browser console, the frontend can’t reach the backend.
Solution: Reconfigure with your LAN IP:
./configure.sh
# Or use the migration script:
./migrate.sh --lan-ip YOUR_LAN_IP
Common SMTP Problems
1. SMTP Authentication Failed
Symptoms: “Authentication failed” or “Invalid credentials”
Solution for Gmail: Use an App Password, not your regular password:
- Enable 2-Step Verification
- Go to https://myaccount.google.com/apppasswords
- Generate a new App Password
- Use that 16-character password in configuration
2. SSL/TLS Configuration
Symptoms: “SSL handshake failed” or “Certificate verification failed”
Solution: Use port 465 for SSL:
SMTP_HOST=smtp.yourprovider.com
SMTP_PORT=465
3. Certificate Hostname Mismatch
Symptoms: “Certificate hostname mismatch”
Solution: Ensure SMTP_HOST matches the SSL certificate exactly.
Test SMTP Connection
cd ~/ectlogger/backend
source venv/bin/activate
python3 -c "
import asyncio
from app.email_service import EmailService
async def test():
await EmailService.send_magic_link('your-email@example.com', 'test-token')
print('Email sent successfully!')
asyncio.run(test())
"
Ad Blocker Issues
Some ad blockers block requests containing “magic-link” in the URL.
Solutions:
- Whitelist your ECTLogger domain
- Disable ad blocker temporarily
- Try a different browser
Need Help?
If emails continue going to spam:
- Test with mail-tester.com and share results
- Check server console logs for SMTP errors
- Verify DNS records are correct
- Consider switching to AWS SES or SendGrid
- Contact your email hosting provider for assistance
Related Documentation
- MAGIC-LINK-CONFIGURATION.md - Magic link expiration settings
- MANUAL-INSTALLATION.md - Manual installation and configuration