SMTP Email Configuration for Self-Hosted Services

6 October 2025 · Updated 6 October 2025

smtpemailconfigurationself-hostedmail-server

Notes on wiring SMTP into self-hosted applications so password reset emails, alert notifications, and admin messages actually get delivered. Most of the time you don’t want to run a mail server yourself — use a transactional SMTP provider and point your apps at it.

SMTP Configuration Basics

Common SMTP Settings

ParameterDescriptionExample Values
HostSMTP server addresssmtp.gmail.com, smtp.example.com
PortSMTP port25, 587 (STARTTLS), 465 (SSL)
SecurityEncryption methodSTARTTLS, SSL/TLS, None
UsernameSMTP auth usernameuser@example.com
PasswordSMTP auth passwordApp-specific or account password
From AddressSender emailnoreply@example.com

Port Selection Guide

PortProtocolUse CaseSecurity
25SMTPServer-to-serverUsually unencrypted
587SMTP+STARTTLSModern standardEncrypted after STARTTLS
465SMTP+SSLLegacy SSLEncrypted from start
2525SMTPAlternative (ISP blocks 25)Depends on configuration

Bitwarden SMTP Configuration

Environment Variables

Location: ./bwdata/env/global.override.env

# Admin email
globalSettings__mail__replyToEmail=no-reply@example.com

# SMTP settings
globalSettings__mail__smtp__host=smtp.example.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__username=bitwarden@example.com
globalSettings__mail__smtp__password=smtp_password

# Use STARTTLS
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__startTls=true

Config.yml Format

Location: ./bwdata/config.yml

mail:
  replyToEmail: no-reply@example.com
  smtp:
    host: smtp.example.com
    port: 587
    ssl: false
    startTls: true
    username: bitwarden@example.com
    password: smtp_password

Vaultwarden SMTP Configuration

Environment Variables

# SMTP server
SMTP_HOST=smtp.example.com
SMTP_FROM=vaultwarden@example.com
SMTP_FROM_NAME=Vaultwarden

# Port and security
SMTP_PORT=587
SMTP_SECURITY=starttls  # or 'force_tls' or 'off'

# Authentication
SMTP_USERNAME=vaultwarden@example.com
SMTP_PASSWORD=smtp_password

# Advanced options
SMTP_TIMEOUT=15
SMTP_AUTH_MECHANISM=Plain  # or Login, Xoauth2

Docker Compose Integration

version: '3'

services:
  vaultwarden:
    image: vaultwarden/server:latest
    environment:
      - SMTP_HOST=smtp.example.com
      - SMTP_FROM=vaultwarden@example.com
      - SMTP_PORT=587
      - SMTP_SECURITY=starttls
      - SMTP_USERNAME=vaultwarden@example.com
      - SMTP_PASSWORD=${SMTP_PASSWORD}  # From .env file
    volumes:
      - ./vw-data:/data

Provider-Specific Configurations

Gmail

Requirements:

  • Enable 2-Factor Authentication
  • Create App-Specific Password

Configuration:

SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-specific-password

Note: Gmail has sending limits (500/day for free accounts)

Office 365 / Microsoft 365

Configuration:

SMTP_HOST=smtp.office365.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=your-email@yourdomain.com
SMTP_PASSWORD=your-password

Modern Auth (OAuth2):

  • Requires application registration in Azure AD
  • More secure than basic auth
  • Basic auth being phased out

SendGrid

Configuration:

SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=apikey
SMTP_PASSWORD=your-sendgrid-api-key

Advantages:

  • 100 emails/day free tier
  • Better deliverability
  • Detailed analytics

Amazon SES

Configuration:

SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=your-ses-smtp-username
SMTP_PASSWORD=your-ses-smtp-password

Setup Steps:

  1. Verify domain or email in SES console
  2. Generate SMTP credentials
  3. Request production access (remove sandbox limits)

Mailgun

Configuration:

SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=postmaster@your-domain.mailgun.org
SMTP_PASSWORD=your-mailgun-smtp-password

Self-Hosted (Postfix/Dovecot)

Configuration:

SMTP_HOST=mail.example.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=sender@example.com
SMTP_PASSWORD=your-password

Requirements:

  • Properly configured MX records
  • SPF, DKIM, DMARC records
  • Reverse DNS (PTR record)
  • Not on spam blacklists

Testing SMTP Configuration

Manual Test with Telnet

# Connect to SMTP server
telnet smtp.example.com 587

# Expected response
220 smtp.example.com ESMTP

# Initiate STARTTLS
EHLO localhost
250-smtp.example.com
250-STARTTLS
250 AUTH PLAIN LOGIN

# Start TLS
STARTTLS
220 Ready to start TLS

Test with OpenSSL

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

# For SSL (port 465)
openssl s_client -connect smtp.example.com:465

Test with swaks (SMTP Test Tool)

# Install swaks
sudo apt install swaks  # Debian/Ubuntu
brew install swaks      # macOS

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

Test from Application Container

Bitwarden:

docker exec -it bitwarden-api bash
telnet smtp.example.com 587

Vaultwarden:

docker exec -it vaultwarden sh
nc -zv smtp.example.com 587

Troubleshooting Common Issues

Authentication Failures

Symptoms: Login failed, authentication error

Causes:

  • Incorrect username/password
  • 2FA not configured (requires app password)
  • App passwords not enabled

Solutions:

  1. Verify credentials
  2. Generate app-specific password
  3. Check for special characters in password (escape if needed)

Connection Timeouts

Symptoms: Cannot connect to SMTP server

Causes:

  • Firewall blocking outbound SMTP
  • ISP blocking port 25/587
  • Incorrect hostname

Solutions:

  1. Check firewall rules: sudo ufw status
  2. Try alternative port (2525)
  3. Verify DNS resolution: nslookup smtp.example.com
  4. Test connectivity: telnet smtp.example.com 587

TLS/SSL Errors

Symptoms: Certificate errors, TLS handshake failed

Causes:

  • Self-signed certificates
  • Expired certificates
  • Wrong security mode

Solutions:

  1. Use SMTP_SECURITY=off for testing (not production)
  2. Update CA certificates: sudo update-ca-certificates
  3. Match security mode to port (587=STARTTLS, 465=SSL)

Emails Going to Spam

Causes:

  • Missing SPF/DKIM/DMARC records
  • Shared IP with poor reputation
  • Generic “noreply” addresses

Solutions:

  1. Configure SPF record:
    v=spf1 include:_spf.google.com ~all
  2. Enable DKIM signing
  3. Set up DMARC policy:
    v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com
  4. Use reputable SMTP provider

Rate Limiting

Symptoms: Some emails not delivered

Causes:

  • Provider rate limits exceeded
  • Too many recipients

Solutions:

  1. Reduce email frequency
  2. Upgrade to paid plan
  3. Implement email queuing

Security Best Practices

Securing SMTP Credentials

1. Use Environment Variables

# .env file
SMTP_PASSWORD=your-secure-password

2. Use Docker Secrets (Swarm)

services:
  app:
    environment:
      SMTP_PASSWORD_FILE: /run/secrets/smtp_password
    secrets:
      - smtp_password

secrets:
  smtp_password:
    file: ./secrets/smtp_password.txt

3. Use Vault/Secrets Manager

  • HashiCorp Vault
  • AWS Secrets Manager
  • Azure Key Vault

Email Security Headers

SPF (Sender Policy Framework):

v=spf1 ip4:192.0.2.0/24 include:_spf.google.com ~all

DKIM (DomainKeys Identified Mail):

  • Sign emails with private key
  • Publish public key in DNS

DMARC (Domain-based Message Authentication):

v=DMARC1; p=quarantine; rua=mailto:reports@example.com; pct=100

Encryption Requirements

PortEncryptionRecommendation
25None/STARTTLS❌ Avoid for user auth
587STARTTLS✅ Recommended
465SSL/TLS✅ Acceptable
2525STARTTLS✅ If 587 blocked

Monitoring Email Delivery

Log Monitoring

Vaultwarden logs:

docker logs vaultwarden 2>&1 | grep -i smtp
docker logs vaultwarden 2>&1 | grep -i email

Bitwarden logs:

docker logs bitwarden-api | grep -i mail

Delivery Status Notifications

Configure bounce handling:

# Set bounce email address
SMTP_FROM=noreply@example.com

Monitor bounce email inbox for:

  • Hard bounces (invalid addresses)
  • Soft bounces (temporary failures)
  • Spam complaints

Email Analytics

Track metrics:

  • Delivery rate
  • Open rate (if supported)
  • Bounce rate
  • Spam complaints

Tools:

  • SendGrid Analytics
  • Mailgun Statistics
  • AWS SES Dashboard

Alternative Email Solutions

Relay Services

1. SMTP Relay (Internal)

# Configure Postfix as relay
SMTP_HOST=localhost
SMTP_PORT=25
SMTP_SECURITY=off

2. Cloud Relay

  • Google Workspace SMTP Relay
  • Office 365 Connector
  • AWS SES SMTP Interface

API-Based Email

Instead of SMTP, use APIs:

  • SendGrid API
  • Mailgun API
  • Amazon SES API
  • Postmark API

Advantages:

  • Better deliverability
  • More features (templates, analytics)
  • Easier troubleshooting