Mail Troubleshooting
Common mail issues and how to fix them. Diagnose SMTP connection problems, authentication failures, and configuration errors.
Quick Diagnostic Steps
Start here when experiencing mail issues.
bash
# Test your SMTP configuration
dart run example/lib/smtp_diagnostic_example.dart
# Or test programmatically in your code
dart run lib/test_mail.dart
1. Test Connection
Verify SMTP server is reachable
2. Check Credentials
Ensure username/password are correct
3. Test Firewall
Check if ports are blocked
Common Errors & Solutions
Quick fixes for the most common mail issues.
Connection Timeout
SMTP server not responding within timeout period.
- Increase timeout:
SMTP_TIMEOUT=60 - Check firewall settings
- Verify correct host and port
- Test with telnet or nc
Authentication Failed
Wrong credentials or auth method.
- Use App Password for Gmail (not regular password)
- Check username format (full email vs username)
- Enable "Less secure app access" (Gmail)
- Verify credentials in provider dashboard
Connection Refused
Server not accepting connections.
- Wrong port number (try 587, 465, or 25)
- Server is down or unreachable
- Firewall blocking outbound connections
- ISP blocking SMTP ports
SSL/TLS Error
Encryption configuration issue.
- Use 'tls' for port 587, 'ssl' for port 465
- Update SSL certificates
- Try 'none' encryption temporarily to test
- Check if antivirus is interfering
Provider-Specific Settings
Correct SMTP settings for popular email providers.
bash
# Gmail
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_ENCRYPTION=tls
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password # App Password, NOT regular password!
# Outlook/Office 365
SMTP_HOST=smtp.office365.com
SMTP_PORT=587
SMTP_ENCRYPTION=tls
SMTP_USERNAME=your-email@outlook.com
SMTP_PASSWORD=your-password
# Mailtrap (Testing)
SMTP_HOST=smtp.mailtrap.io
SMTP_PORT=2525
SMTP_ENCRYPTION=tls
SMTP_USERNAME=your-mailtrap-username
SMTP_PASSWORD=your-mailtrap-password
# SendGrid
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_ENCRYPTION=tls
SMTP_USERNAME=apikey
SMTP_PASSWORD=your-sendgrid-api-key
# Mailgun SMTP
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_ENCRYPTION=tls
SMTP_USERNAME=postmaster@yourdomain.com
SMTP_PASSWORD=your-mailgun-smtp-password
Testing Port Connectivity
Verify that SMTP ports are accessible from your network.
bash
# Using telnet (Windows/Mac/Linux)
telnet smtp.gmail.com 587
# Expected output:
# 220 smtp.gmail.com ESMTP
# Press Ctrl+C to exit
# Using PowerShell (Windows)
Test-NetConnection -ComputerName smtp.gmail.com -Port 587
# Expected output:
# TcpTestSucceeded : True
# Using nc (Mac/Linux)
nc -zv smtp.gmail.com 587
# Expected output:
# Connection to smtp.gmail.com port 587 [tcp/*] succeeded!
# Test multiple ports
for port in 25 587 465 2525; do
nc -zv smtp.gmail.com $port
done
Firewall Configuration
Allow SMTP ports through your firewall.
bash
# Windows Firewall (PowerShell as Administrator)
New-NetFirewallRule -DisplayName "SMTP Outbound" -Direction Outbound -Protocol TCP -LocalPort 587 -Action Allow
# Linux (iptables)
sudo iptables -A OUTPUT -p tcp --dport 587 -j ACCEPT
sudo iptables -A OUTPUT -p tcp --dport 465 -j ACCEPT
sudo iptables-save
# Linux (ufw)
sudo ufw allow out 587/tcp
sudo ufw allow out 465/tcp
# MacOS
# Usually no action needed - outbound connections are allowed by default
# If using Little Snitch, add a rule for your Dart application
Gmail Configuration
Gmail has specific requirements for SMTP access.
⚠️ Important: Use App Password!
Gmail requires an App Password when 2-factor authentication is enabled. Do NOT use your regular Google account password.
text
Step 1: Enable 2-Factor Authentication
1. Go to https://myaccount.google.com/security
2. Click "2-Step Verification"
3. Follow setup instructions
Step 2: Generate App Password
1. Go to https://myaccount.google.com/apppasswords
2. Select app: "Mail"
3. Select device: "Other (Custom name)"
4. Enter name: "Khadem App"
5. Click "Generate"
6. Copy the 16-character password (spaces will be removed)
Step 3: Use App Password in .env
Use the generated password, NOT your Google account password!
bash
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_ENCRYPTION=tls
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=abcd efgh ijkl mnop # App Password from Step 2
# Gmail Limits:
# - Free accounts: 500 emails/day
# - Google Workspace: 2,000 emails/day
# - Consider using Mailgun/SES for higher volumes
Alternative Mail Drivers
If SMTP continues to fail, switch to API-based drivers that use HTTPS.
bash
# Mailgun (API-based, no SMTP)
MAIL_DRIVER=mailgun
MAILGUN_DOMAIN=mg.yourdomain.com
MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxxxxxxxxxx
# Amazon SES (API-based, no SMTP)
MAIL_DRIVER=ses
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_DEFAULT_REGION=us-east-1
# Postmark (API-based, no SMTP)
MAIL_DRIVER=postmark
POSTMARK_SERVER_TOKEN=your-server-token
# These use HTTPS (port 443) which is rarely blocked
Programmatic Diagnostics
Run connection tests programmatically in your application.
dart
import 'package:khadem/khadem.dart';
void main() async {
try {
final mailManager = container.resolve<MailManager>();
// Test connection
print('Testing SMTP connection...');
await mailManager
.to('test@example.com')
.subject('Test Email')
.text('If you receive this, SMTP is working!')
.send();
print('✓ Email sent successfully!');
} on MailException catch (e) {
print('✗ Mail error: ${e.message}');
print('Stack trace: ${e.stackTrace}');
// Check specific error types
if (e.message.contains('timeout')) {
print('Suggestion: Increase SMTP_TIMEOUT');
} else if (e.message.contains('authentication')) {
print('Suggestion: Check username/password');
} else if (e.message.contains('connection refused')) {
print('Suggestion: Check firewall and port settings');
}
} catch (e) {
print('✗ Unexpected error: $e');
}
}
// Run advanced diagnostics
Future<void> runDiagnostics() async {
final config = SmtpConfig(
host: env('SMTP_HOST'),
port: env.getInt('SMTP_PORT'),
encryption: env('SMTP_ENCRYPTION'),
timeout: env.getInt('SMTP_TIMEOUT', defaultValue: 30),
);
final report = await SmtpDiagnostics.testConnection(config);
print('=== SMTP Diagnostic Report ===');
print('Server: ${config.host}:${config.port}');
print('Status: ${report.isHealthy ? "HEALTHY" : "UNHEALTHY"}');
print('Message: ${report.summary}');
if (!report.isHealthy) {
print('\nRecommendations:');
print(SmtpDiagnostics.generateDiagnosticMessage(report));
}
}
Testing with Mailtrap
Use Mailtrap to test email sending without sending real emails.
✅ Recommended for Development
Mailtrap is a free email testing service that catches all emails sent from your application. Perfect for development and testing.
text
Step 1: Sign Up for Mailtrap
1. Go to https://mailtrap.io
2. Create a free account
3. Verify your email
Step 2: Create an Inbox
1. Click "Create Inbox"
2. Name it "Khadem Development"
3. Click "Save"
Step 3: Get SMTP Credentials
1. Click on your inbox
2. Go to "SMTP Settings"
3. Copy the credentials shown
Step 4: Configure Khadem
Use the credentials in your .env file
All emails sent will appear in your Mailtrap inbox!
No emails will be sent to real recipients.
bash
# Mailtrap Configuration
SMTP_HOST=smtp.mailtrap.io
SMTP_PORT=2525
SMTP_ENCRYPTION=tls
SMTP_USERNAME=1a2b3c4d5e6f7g # From Mailtrap inbox settings
SMTP_PASSWORD=1a2b3c4d5e6f7g # From Mailtrap inbox settings
# Benefits:
# - Free tier: 500 emails/month
# - No real emails sent
# - Test spam score
# - HTML/text preview
# - View all headers
# - API access
Enable Debug Mode
Get detailed logging for mail operations.
dart
// Enable verbose mail logging
import 'package:khadem/khadem.dart';
// In your service provider or bootstrap
void configureMailLogging() {
Log.channel('mail').level = LogLevel.debug;
}
// Or in config/logging.dart
const loggingConfig = {
'channels': {
'mail': {
'level': 'debug', // debug, info, warning, error
'handler': 'file',
'path': 'storage/logs/mail.log',
},
},
};
// This will log:
// - SMTP connection attempts
// - Authentication steps
// - Email content
// - Send confirmations
// - Errors with stack traces
// Check logs
// tail -f storage/logs/mail.log
Prevention Best Practices
Follow these practices to avoid mail issues.
✅ Do:
- Test mail configuration in development first
- Use Mailtrap for development testing
- Verify email addresses before sending
- Handle mail exceptions gracefully
- Queue emails instead of sending synchronously
- Monitor mail delivery rates
- Keep credentials in .env file
- Use API-based drivers in production
❌ Don't:
- Commit credentials to version control
- Use personal Gmail in production
- Ignore email sending failures
- Send emails synchronously in HTTP requests
- Use weak passwords
- Skip testing before production
- Forget to handle rate limits
- Use default error messages for users
