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

On this page