What's Actually Happening

Your application tries to send emails through an SMTP server, but every attempt fails. Authentication is rejected, connections are refused, or the SMTP server doesn't respond. Users aren't getting password reset emails, order confirmations, notifications, or any transactional mail from your application.

This can happen with any SMTP provider: Gmail SMTP, Microsoft Outlook/Exchange, AWS SES, SendGrid, Mailgun, Postmark, or your own self-hosted mail server. The symptoms vary but the outcome is the same - emails don't get sent and users are frustrated.

The Error You'll See

SMTP authentication failures show various error messages depending on the provider and failure type:

```bash # SMTP authentication failed 535 5.7.8 Username and Password not accepted. Learn more at 535 5.7.8 https://support.google.com/mail/?p=BadCredentials 535 5.7.8 [PROTOCOL] Authentication failed

# SMTP connection refused Connection refused: connect java.net.ConnectException: Connection refused SMTPConnectError: Could not connect to SMTP host: smtp.example.com, port: 587

# SMTP timeout SocketTimeoutException: Read timed out SMTPServerDisconnected: Connection unexpectedly closed

# SSL/TLS errors SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException STARTTLS command failed SSL certificate problem: unable to get local issuer certificate

# Authentication mechanism not supported 504 5.7.4 Unrecognized authentication type 538 5.7.11 Authentication mechanism too weak

# SMTP relay denied 550 5.7.1 Relaying denied. Proper authentication required. 550 5.7.1 SMTP; Client does not have permissions to send as this sender

# Gmail specific errors 535-5.7.8 Username and Password not accepted. For more information, go to 535 5.7.8 https://support.google.com/mail/?p=BadCredentials 534-5.7.9 Application-specific password required. Learn more at 534 5.7.9 https://support.google.com/mail/?p=InvalidSecondFactor 535-5.7.1 Please log in with your web browser and then try again. 535-5.7.1 For more information, go to https://support.google.com/mail/?p=WebLoginRequired

# AWS SES errors 454 4.7.0 TLS not available due to local policy problem 530 Must issue a STARTTLS command first 550 Message rejected: Email address is not verified.

# Office 365/Outlook errors 535 5.7.3 Authentication unsuccessful 535 5.7.3 [STAGPROXY01] Authentication unsuccessful 421 4.7.0 Temporarily rejected. Cannot decode STARTTLS command

# SendGrid errors 550 Unauthenticated senders not allowed 550 The from address does not match a verified Sender Identity.

# Postfix/dovecot errors 535 5.7.8 Error: authentication failed SASL authentication failed; server smtp.example.com[192.168.1.1] said: 535 5.7.8 Error: authentication failed: UGFzc3dvcmQ6 ```

Additional symptoms: - Application logs show SMTP exceptions repeatedly - Email queue grows without delivery - Test emails sent manually fail - Password reset functionality broken - Order confirmation emails not sent - Admin notifications not received - Marketing emails stuck in queue

Why This Happens

  1. 1.Incorrect SMTP Credentials: Username or password is wrong. Common mistakes: using email address as username when SMTP requires account ID, wrong password, credentials for wrong SMTP server, or credentials expired/changed.
  2. 2.SMTP Server Not Reachable: Server hostname is wrong, server is down, firewall blocks the port, DNS resolution fails, or server IP changed. Connection attempts timeout or get refused.
  3. 3.SSL/TLS Certificate Issues: Certificate verification fails because server cert is invalid, self-signed, expired, or CA not trusted. Client TLS settings mismatch server requirements (TLS 1.2/1.3 vs older versions).
  4. 4.Authentication Method Mismatch: Application uses authentication method the server doesn't support (PLAIN vs LOGIN vs XOAUTH2). Server requires specific method but client uses different one.
  5. 5.Two-Factor Authentication Blocking: Gmail and Outlook require app-specific passwords when 2FA is enabled. Using normal password fails. OAuth2 token expired or revoked for OAuth-based authentication.
  6. 6.SMTP Relay Permissions: Server rejects relay because sender address isn't authorized, IP address not in allowed list, or authenticated user doesn't have permission to send from that address.
  7. 7.Port Blocked by Firewall: SMTP ports (25, 587, 465, 2525) blocked by firewall, ISP, or hosting provider. Many cloud providers block port 25 to prevent spam.
  8. 8.Server Rate Limiting: Too many authentication attempts or emails triggered rate limits. Server temporarily blocks connections from your IP/user.

Step 1: Verify SMTP Configuration Details

First, confirm your SMTP server settings are correct.

```bash # Check application SMTP configuration # For various applications/frameworks:

# Node.js - check environment or config file: cat .env | grep SMTP cat config/mail.js | grep -A20 smtp

# Python Django: cat settings.py | grep -A20 EMAIL_HOST

# Python Flask: cat config.py | grep -A10 MAIL

# PHP Laravel: cat config/mail.php | grep -A20 smtp cat .env | grep MAIL_

# Java Spring Boot: cat application.properties | grep mail cat application.yml | grep -A20 mail

# WordPress: cat wp-config.php | grep SMTP # Or check plugin settings in admin

# Typical SMTP settings needed: SMTP_HOST=smtp.gmail.com # or smtp.office365.com, email-smtp.region.amazonaws.com SMTP_PORT=587 # or 465 for SSL, 25 (often blocked) SMTP_USER=your-email@gmail.com # or account-specific username SMTP_PASS=your-password # or app-specific password SMTP_FROM=noreply@example.com

# Verify these match your email provider's documented settings:

# Gmail SMTP: Host: smtp.gmail.com Port: 587 (TLS) or 465 (SSL) User: your@gmail.com (full email) Pass: password or app-specific password

# Outlook/Office 365: Host: smtp.office365.com Port: 587 (STARTTLS required) User: your@company.com (full email) Pass: password or app-specific password

# AWS SES: Host: email-smtp.region.amazonaws.com (e.g., email-smtp.us-east-1.amazonaws.com) Port: 587 or 25 (25 often blocked) User: SES SMTP credentials (IAM generated, NOT AWS account) Pass: SES SMTP password

# SendGrid: Host: smtp.sendgrid.net Port: 587 or 2525 User: apikey (literal string "apikey") Pass: your-sendgrid-api-key

# Mailgun: Host: smtp.mailgun.org Port: 587 or 2525 User: postmaster@your-domain.mailgun.org Pass: Mailgun SMTP password ```

Step 2: Test SMTP Connection Manually

Verify you can connect to the SMTP server using command-line tools.

```bash # Test basic TCP connectivity to SMTP port: telnet smtp.gmail.com 587

# Should see: # 220 smtp.gmail.com ESMTP ...

# If connection refused or timeout, port/host unreachable

# Test with netcat: nc -v -z smtp.gmail.com 587

# Should show: # Connection to smtp.gmail.com 587 port [tcp/*] succeeded!

# For SSL port (465): nc -v -z smtp.gmail.com 465

# Using curl to test SMTP: curl -v smtp://smtp.gmail.com:587

# More detailed test using openssl for SSL: openssl s_client -connect smtp.gmail.com:465 -crlf

# For STARTTLS (port 587): openssl s_client -connect smtp.gmail.com:587 -starttls smtp -crlf

# Should show SSL certificate details and SMTP greeting

# Full SMTP authentication test using swaks (install first): # Ubuntu/Debian: sudo apt install swaks

# macOS: brew install swaks

# Test SMTP auth: swaks --to recipient@example.com --from sender@gmail.com \ --server smtp.gmail.com:587 \ --auth LOGIN \ --auth-user your@gmail.com \ --auth-password 'your-password'

# Output should show successful authentication and email sent

# For Gmail with app-specific password: swaks --to test@example.com --from your@gmail.com \ --server smtp.gmail.com:587 \ --auth LOGIN \ --auth-user your@gmail.com \ --auth-password 'abcd efgh ijkl mnop' # App password

# For AWS SES: swaks --to verified@example.com --from verified@example.com \ --server email-smtp.us-east-1.amazonaws.com:587 \ --auth LOGIN \ --auth-user AKIAIOSFODNN7EXAMPLE \ --auth-password 'SES_SMTP_PASSWORD'

# Using Python for detailed test: python3 << 'EOF' import smtplib import ssl

context = ssl.create_default_context()

try: server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls(context=context) server.ehlo() server.login('your@gmail.com', 'password') print("Authentication successful!") server.quit() except Exception as e: print(f"Error: {e}") EOF ```

Step 3: Check Network Connectivity and Firewall

Verify network allows SMTP traffic.

```bash # Check if SMTP ports are reachable: nc -z -v smtp.gmail.com 25 nc -z -v smtp.gmail.com 587 nc -z -v smtp.gmail.com 465 nc -z -v smtp.gmail.com 2525

# If all fail, likely firewall issue

# Check local firewall (iptables): sudo iptables -L -n | grep -E "25|587|465"

# Check local firewall (firewalld): sudo firewall-cmd --list-ports sudo firewall-cmd --list-services

# Allow SMTP ports if needed: sudo firewall-cmd --add-port=587/tcp --permanent sudo firewall-cmd --add-port=465/tcp --permanent sudo firewall-cmd --reload

# Check if hosting provider blocks SMTP: # AWS EC2: Port 25 is blocked by default # Request to unblock: https://aws.amazon.com/forms/aws-port-25-request/

# Google Cloud: Port 25 blocked # Use ports 587 or 465

# Azure: Port 25 may be blocked for new subscriptions

# Check DNS resolution: nslookup smtp.gmail.com dig smtp.gmail.com

# Should resolve to valid IP addresses

# Check routing: traceroute smtp.gmail.com

# If traceroute stops before reaching server, network issue

# Check if server is up: ping smtp.gmail.com

# Check from application server's perspective: # If app is in container, test from inside container: docker exec -it app-container nc -z -v smtp.gmail.com 587

# Kubernetes pod: kubectl exec -it pod-name -- nc -z -v smtp.gmail.com 587 ```

Step 4: Fix Authentication Credentials

Correct authentication settings based on your provider.

```bash # For Gmail: # If 2FA is enabled, you MUST use app-specific password # Create app password: # 1. Go to https://myaccount.google.com/ # 2. Security > 2-Step Verification > App passwords # 3. Generate new app password (16 characters like "abcd efgh ijkl mnop") # 4. Use this password in SMTP_PASS

# Check if 2FA is enabled: # Visit Google account security settings

# For Gmail without 2FA: # May need to enable "Less secure apps" (deprecated, not recommended) # Better: Use OAuth2

# For Gmail OAuth2 authentication: # Use XOAUTH2 authentication: python3 << 'EOF' import smtplib import base64 from email.message import EmailMessage

# Get OAuth2 token from Google # Token must have scope: https://mail.google.com/

auth_string = f"user={email}\x01auth=Bearer {token}\x01\x01" auth_string_b64 = base64.b64encode(auth_string.encode()).decode()

server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.docmd('AUTH XOAUTH2 ' + auth_string_b64) # ... EOF

# For Outlook/Office 365: # If 2FA enabled, use app password: # 1. https://account.microsoft.com/security # 2. Advanced security options > App passwords # 3. Create new app password

# For AWS SES SMTP: # SMTP credentials are DIFFERENT from AWS credentials # Generate SES SMTP credentials: # 1. AWS Console > SES > SMTP Settings # 2. Create SMTP credentials # 3. This creates IAM user with SMTP permissions # 4. Use the generated username/password (NOT your AWS keys)

aws ses get-smtp-access --region us-east-1 # If available

# Or manually generate SES SMTP password from secret key: python3 << 'EOF' import hmac import hashlib import base64

# SES SMTP password algorithm secret = "AwsSecretAccessKeyHere" # Your AWS secret key message = "SendRawEmail" # SES SMTP action version = "\x02"

signature = hmac.new(secret.encode(), (version + message).encode(), hashlib.sha256).digest() smtp_password = base64.b64encode(signature).decode() print(smtp_password) EOF

# For SendGrid: # Username is literally "apikey" (not your email) # Password is your SendGrid API key

SMTP_USER=apikey SMTP_PASS=SG.your_api_key_here

# For Mailgun: # User is postmaster@your-domain.mailgun.org (from Mailgun dashboard) # Password is the SMTP password shown in Mailgun domain settings

# Verify SES email addresses are verified: aws ses list-verified-email-addresses --region us-east-1

# If sender email not verified, SES rejects: aws ses verify-email-identity --email-address sender@example.com --region us-east-1

# Check SES sandbox mode (new accounts limited): aws ses get-account-sending-enabled --region us-east-1

# If in sandbox, can only send to verified addresses # Request production access in SES console ```

Step 5: Fix SSL/TLS Certificate Issues

Resolve certificate and encryption problems.

```bash # Test TLS connection: openssl s_client -connect smtp.gmail.com:587 -starttls smtp

# Check certificate details: openssl s_client -connect smtp.gmail.com:587 -starttls smtp 2>/dev/null | openssl x509 -noout -text

# For certificate validation errors: # Check if system CA certificates are up to date:

# Ubuntu/Debian: sudo apt update && sudo apt install ca-certificates sudo update-ca-certificates

# macOS: # System certificates updated automatically # For custom certs, add to Keychain

# CentOS/RHEL: sudo yum update ca-certificates sudo update-ca-trust

# Alpine: apk add ca-certificates update-ca-certificates

# If using self-signed certificate on custom SMTP server: # Option 1: Add certificate to trusted store sudo cp company-smtp-cert.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates

# Option 2: Disable certificate verification (not recommended for production) # In application config: SMTP_TLS_VERIFY=false # Or in code: ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE

# For STARTTLS vs SSL wrapper: # STARTTLS (port 587): Connect plain, then upgrade to TLS # SSL wrapper (port 465): Connect with SSL from start

# Test STARTTLS: python3 << 'EOF' import smtplib import ssl

server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() context = ssl.create_default_context() server.starttls(context=context) server.ehlo() print("STARTTLS successful") server.quit() EOF

# Test SSL wrapper (port 465): python3 << 'EOF' import smtplib import ssl

context = ssl.create_default_context() server = smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) server.ehlo() print("SSL connection successful") server.quit() EOF

# Check TLS version compatibility: # Some servers require TLS 1.2 or higher openssl s_client -connect smtp.gmail.com:587 -starttls smtp -tls1_2

# If fails, server may require newer TLS # Application must support TLS 1.2 or 1.3 ```

Step 6: Fix Authentication Method Issues

Use the correct authentication mechanism.

```bash # SMTP authentication methods: # - LOGIN: Username and password sent in two separate commands # - PLAIN: Username and password sent in one base64-encoded string # - XOAUTH2: OAuth2 access token # - CRAM-MD5: Challenge-response (older, rarely used)

# Test which methods server supports: telnet smtp.gmail.com 587

# After connection: EHLO test.example.com # Server response includes AUTH line showing supported methods: # 250-SIZE 35882577 # 250-8BITMIME # 250-STARTTLS # 250-ENHANCEDSTATUSCODES # 250-PIPELINING # 250-CHUNKING # 250 SMTPUTF8 # (AUTH line appears after STARTTLS)

# After STARTTLS: STARTTLS EHLO test.example.com # Now should see: # 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER

# Use appropriate method: # LOGIN (most common): swaks --auth LOGIN --auth-user user --auth-password pass

# PLAIN: swaks --auth PLAIN --auth-user user --auth-password pass

# For applications, specify auth method: # Python: server.login(user, password) # Uses LOGIN by default

# Node.js nodemailer: transport: { auth: { user: 'user', pass: 'pass' // method: 'LOGIN' // usually automatic } }

# For "authentication method too weak" error: # Server requires stronger auth (like OAuth2) # Gmail may require OAuth2 if less secure apps disabled

# Use OAuth2: # Get token from OAuth2 flow, then use XOAUTH2 ```

Step 7: Test Sending Email Through Application

Verify your application can send emails after fixes.

```bash # For Node.js applications using nodemailer: node << 'EOF' const nodemailer = require('nodemailer');

const transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 587, secure: false, // true for 465, false for other ports auth: { user: 'your@gmail.com', pass: 'app-specific-password' }, tls: { rejectUnauthorized: true } });

transporter.verify(function(error, success) { if (error) { console.log('SMTP connection error:', error); } else { console.log('SMTP server is ready');

transporter.sendMail({ from: 'your@gmail.com', to: 'recipient@example.com', subject: 'Test Email', text: 'This is a test email' }, (err, info) => { if (err) console.log('Send error:', err); else console.log('Email sent:', info.response); }); } }); EOF

# For Python applications: python3 << 'EOF' import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import ssl

context = ssl.create_default_context()

msg = MIMEMultipart() msg['From'] = 'your@gmail.com' msg['To'] = 'recipient@example.com' msg['Subject'] = 'Test Email' msg.attach(MIMEText('This is a test email', 'plain'))

try: server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls(context=context) server.ehlo() server.login('your@gmail.com', 'app-password') server.send_message(msg) server.quit() print("Email sent successfully") except Exception as e: print(f"Error: {e}") EOF

# For PHP applications: php << 'EOF' <?php require 'vendor/autoload.php';

use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP;

$mail = new PHPMailer(true);

try { $mail->SMTPDebug = SMTP::DEBUG_SERVER; $mail->isSMTP(); $mail->Host = 'smtp.gmail.com'; $mail->SMTPAuth = true; $mail->Username = 'your@gmail.com'; $mail->Password = 'app-password'; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587;

$mail->setFrom('your@gmail.com', 'Test'); $mail->addAddress('recipient@example.com'); $mail->Subject = 'Test Email'; $mail->Body = 'This is a test email';

$mail->send(); echo 'Email sent successfully'; } catch (Exception $e) { echo "Error: {$mail->ErrorInfo}"; } ?> EOF

# For Java applications (Spring Boot): # Add to application.properties: spring.mail.host=smtp.gmail.com spring.mail.port=587 spring.mail.username=your@gmail.com spring.mail.password=app-password spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true

# Test with RestController or service ```

Step 8: Check Email Queue and Logs

Examine application logs for SMTP errors.

```bash # Check application logs for SMTP errors:

# Node.js application logs: tail -100 /var/log/node-app.log | grep -i smtp tail -100 /var/log/node-app.log | grep -i "ECONNREFUSED|authentication|535"

# Python Django logs: tail -100 /var/log/django.log | grep -i mail journalctl -u django-app | grep -i smtp

# PHP Laravel logs: tail -100 storage/logs/laravel.log | grep -i mail tail -100 storage/logs/laravel.log | grep -i "Swift_TransportException"

# Java Spring Boot logs: tail -100 /var/log/spring-boot.log | grep -i mail tail -100 /var/log/spring-boot.log | grep -i "MailAuthenticationException|MailSendException"

# WordPress logs (if using SMTP plugin): tail -100 /var/log/apache2/error.log | grep -i smtp # Check wp-content/debug.log if WP_DEBUG enabled

# Check mail queue if using queue system: # For Laravel queue: php artisan queue:work --once --verbose php artisan queue:failed

# For Django Celery: celery -A yourproject inspect active celery -A yourproject inspect reserved

# For RabbitMQ mail queue: rabbitmqctl list_queues name messages rabbitmqctl purge_queue mail_queue

# Check if emails are queued but not sent: # For sidekiq (Ruby): sidekiq-web # Check queue status

# For Redis queue: redis-cli LLEN mail_queue redis-cli LRANGE mail_queue 0 10

# Monitor SMTP connections in real-time: tail -f /var/log/mail.log # Postfix/Sendmail logs tail -f /var/log/syslog | grep -i smtp ```

Step 9: Monitor SMTP Health

Set up monitoring for SMTP service health.

```bash # Create SMTP health check script: cat > scripts/check-smtp-health.sh << 'EOF' #!/bin/bash # SMTP Health Check Script

SMTP_HOST="${SMTP_HOST:-smtp.gmail.com}" SMTP_PORT="${SMTP_PORT:-587}" SMTP_USER="${SMTP_USER:-}" SMTP_PASS="${SMTP_PASS:-}" TEST_TO="${TEST_TO:-test@example.com}" ALERT_EMAIL="${ALERT_EMAIL:-ops@company.com}"

LOG_FILE="/var/log/smtp-health.log"

echo "$(date): Checking SMTP health..." >> $LOG_FILE

# Test connection if ! nc -z -v $SMTP_HOST $SMTP_PORT 2>&1 | grep -q succeeded; then echo "$(date): ERROR - Cannot connect to $SMTP_HOST:$SMTP_PORT" >> $LOG_FILE echo "SMTP connection failed to $SMTP_HOST:$SMTP_PORT" | mail -s "SMTP Alert" $ALERT_EMAIL exit 1 fi

# Test authentication (if credentials provided) if [ -n "$SMTP_USER" ] && [ -n "$SMTP_PASS" ]; then AUTH_RESULT=$(swaks --server $SMTP_HOST:$SMTP_PORT \ --auth LOGIN \ --auth-user $SMTP_USER \ --auth-password "$SMTP_PASS" \ --to $TEST_TO \ --h-Subject "SMTP Health Check" \ --body "SMTP health check test" \ 2>&1)

if echo "$AUTH_RESULT" | grep -q "authentication successful"; then echo "$(date): OK - SMTP authentication successful" >> $LOG_FILE exit 0 else echo "$(date): ERROR - SMTP authentication failed" >> $LOG_FILE echo "$AUTH_RESULT" >> $LOG_FILE echo "SMTP authentication failed" | mail -s "SMTP Alert" $ALERT_EMAIL exit 1 fi fi

echo "$(date): OK - SMTP port reachable" >> $LOG_FILE exit 0 EOF

chmod +x scripts/check-smtp-health.sh

# Run the check: scripts/check-smtp-health.sh

# Add to cron for regular monitoring: (crontab -l; echo "*/5 * * * * SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=user SMTP_PASS=pass /path/to/scripts/check-smtp-health.sh") | crontab -

# Create Nagios/Icinga check: cat > scripts/nagios-smtp-check.sh << 'EOF' #!/bin/bash # Nagios SMTP Check Plugin

STATE_OK=0 STATE_WARNING=1 STATE_CRITICAL=2 STATE_UNKNOWN=3

SMTP_HOST=$1 SMTP_PORT=$2 SMTP_USER=$3 SMTP_PASS=$4

if [ -z "$SMTP_HOST" ]; then echo "Usage: $0 host port [user] [password]" exit $STATE_UNKNOWN fi

# Test connection if ! nc -z -w5 $SMTP_HOST ${SMTP_PORT:-587} 2>/dev/null; then echo "SMTP CRITICAL - Cannot connect to $SMTP_HOST:$SMTP_PORT" exit $STATE_CRITICAL fi

# Test authentication if credentials provided if [ -n "$SMTP_USER" ]; then AUTH_TEST=$(swaks --server $SMTP_HOST:${SMTP_PORT:-587} \ --auth LOGIN \ --auth-user $SMTP_USER \ --auth-password "$SMTP_PASS" \ --quit 2>&1)

if echo "$AUTH_TEST" | grep -qi "authentication failed"; then echo "SMTP CRITICAL - Authentication failed" exit $STATE_CRITICAL fi fi

echo "SMTP OK - $SMTP_HOST:$SMTP_PORT reachable" exit $STATE_OK EOF

chmod +x scripts/nagios-smtp-check.sh ```

Step 10: Implement Email Sending Best Practices

Set up proper email handling to prevent future issues.

bash
# Use connection pooling for SMTP:
# Node.js nodemailer:
javascript
const transporter = nodemailer.createTransport({
  pool: true,  // Use connection pool
  maxConnections: 5,  // Max concurrent connections
  maxMessages: 100,  // Max messages per connection
  rateDelta: 1000,  // Min time between messages
  rateLimit: 10,  // Max messages per rateDelta
  host: 'smtp.gmail.com',
  port: 587,
  auth: { user: 'email', pass: 'password' }
});

```bash # Implement retry logic: cat > scripts/email-with-retry.sh << 'EOF' #!/bin/bash # Email with retry logic

RECIPIENT=$1 SUBJECT=$2 BODY=$3 MAX_RETRIES=3

for i in $(seq 1 $MAX_RETRIES); do if swaks --to $RECIPIENT --from noreply@example.com \ --server smtp.example.com:587 \ --auth-user user --auth-password pass \ --h-Subject "$SUBJECT" --body "$BODY" \ 2>&1 | grep -q "Message delivered"; then echo "Email sent successfully on attempt $i" exit 0 fi

echo "Attempt $i failed, retrying in 30 seconds..." sleep 30 done

echo "Failed to send email after $MAX_RETRIES attempts" exit 1 EOF

# Queue emails instead of sending directly: # Use Redis queue, RabbitMQ, or database queue

# Implement email verification workflow: # Verify sender addresses for AWS SES aws ses verify-email-identity --email-address noreply@example.com

# For SendGrid, verify sender identity curl -X POST "https://api.sendgrid.com/v3/senders" \ -H "Authorization: Bearer $SENDGRID_KEY" \ -d '{"from_email":"noreply@example.com"}'

# Use dedicated email service instead of Gmail for production: # - AWS SES (cost-effective) # - SendGrid (good analytics) # - Mailgun (developer-friendly) # - Postmark (reliable delivery)

# Configure SPF/DKIM/DMARC for custom domain: # SPF record in DNS: example.com TXT "v=spf1 include:sendgrid.net include:amazonses.com ~all"

# DKIM: Get key from provider and add to DNS # DMARC: _dmarc.example.com TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com" ```

Checklist for Fixing SMTP Authentication Failures

StepActionCommandStatus
1Verify SMTP configurationCheck app config file
2Test SMTP connection manuallytelnet smtp.server 587
3Check network connectivitync -z -v smtp.server 587
4Fix authentication credentialsUse correct username/password
5Fix SSL/TLS issuesopenssl s_client -connect server:587 -starttls smtp
6Fix authentication methodUse LOGIN, PLAIN, or XOAUTH2
7Test sending through applicationSend test email
8Check email queue and logs`tail app.log \grep smtp`
9Monitor SMTP healthCreate health check script
10Implement best practicesUse connection pooling, retry, queue

Verify the Fix

After fixing SMTP issues, verify emails are being sent:

```bash # 1. SMTP connection works nc -z -v smtp.gmail.com 587 # Should show: succeeded

# 2. Authentication succeeds swaks --server smtp.gmail.com:587 --auth LOGIN --auth-user user --auth-password pass # Should show: authentication successful

# 3. Test email sent successfully swaks --to test@example.com --from your@email.com --server smtp.gmail.com:587 \ --auth-user user --auth-password pass --h-Subject "Test" --body "Test" # Should show: Message delivered

# 4. Application can send emails # Run application test script

# 5. No SMTP errors in logs tail -100 /var/log/app.log | grep -i smtp # Should not show errors

# 6. Email queue is processing # Check queue depth is decreasing

# 7. Received test email in inbox # Check recipient received email

# 8. SPF/DKIM/DMARC passing # Use mail tester: https://www.mail-tester.com/

# 9. SMTP health check passing scripts/check-smtp-health.sh # Exit code 0

# 10. Monitoring alerts not triggered # No alerts in last hour ```

  • [Fix Gmail App Password Not Working](/articles/fix-gmail-app-password-not-working) - Gmail authentication
  • [Fix AWS SES Email Not Sending](/articles/fix-aws-ses-email-not-sending) - AWS SES issues
  • [Fix SendGrid Sender Not Verified](/articles/fix-sendgrid-sender-not-verified) - SendGrid verification
  • [Fix Email SPF DKIM Failed](/articles/fix-email-spf-dkim-failed) - DNS authentication
  • [Fix Postfix SMTP Relay Denied](/articles/fix-postfix-smtp-relay-denied) - Postfix configuration
  • [Fix Office 365 Modern Auth Failed](/articles/fix-office-365-modern-auth-failed) - Outlook authentication
  • [Fix Firewall Blocking SMTP Ports](/articles/fix-firewall-blocking-smtp-ports) - Network firewall issues