Skip to content

SMTP (outbound email)

TravStats sends three kinds of email and only three:

  1. Invitations — when an admin invites a new user, the link arrives by email.
  2. Password resets — the Forgot password link uses SMTP to deliver the reset token.
  3. Flight reminders — opt-in emails 24 h before each flight (configurable per user).

Single-user instances rarely need this — admins can create users manually and there’s nothing to remind yourself of. Multi-user instances or anyone who wants self-service password recovery does.

Admin → Settings → SMTP. Six fields:

FieldWhat it is
Hostsmtp.gmail.com, mail.example.com, …
Port465 for TLS, 587 for STARTTLS, 25 unencrypted (rare)
EncryptionTLS / STARTTLS / None
UsernameLogin for the SMTP server (full email address for most providers)
PasswordApp-specific password from your provider — almost never your real account password
From addressThe From: header users see in their inbox

Save and the Send test mail button appears. Enter any address you own; a one-line “TravStats SMTP test” should arrive in seconds. If it fails the error is shown inline.

Gmail won’t accept your account password over SMTP. You must create an “app password”:

  1. Visit myaccount.google.com/security2-Step Verification → enable it (mandatory for app passwords).
  2. App passwords → create one labelled “TravStats” → 16-character code.
  3. In TravStats:
    Host: smtp.gmail.com
    Port: 465
    Encryption: TLS
    Password: <16-character app password from above>
    From: [email protected] (or any verified alias)

Gmail caps outbound at ~500 messages per day on free accounts. Plenty for a personal TravStats; not for high-volume distribution.

Cleaner option for sending from a custom domain ([email protected]):

  1. Sign up at mailgun.com, add and verify your sending domain.
  2. Sending → Domain settings → SMTP credentials → create credentials.
  3. In TravStats:
    Host: smtp.mailgun.org (EU users: smtp.eu.mailgun.org)
    Port: 587
    Encryption: STARTTLS
    Password: <SMTP password from Mailgun dashboard>
    From: TravStats <[email protected]>

Mailgun’s free tier covers 5000 messages / month. More than enough for a personal TravStats.

Similar to Mailgun:

  1. Sign up at sendgrid.com, verify a single sender (or whole domain).
  2. Settings → API Keys → create with Mail Send permission.
  3. In TravStats:
    Host: smtp.sendgrid.net
    Port: 587
    Encryption: STARTTLS
    Username: apikey (literal string "apikey")
    Password: <the API key from above>
    From: TravStats <[email protected]>

Self-hosted Postfix / mailcow / Mail-in-a-Box

Section titled “Self-hosted Postfix / mailcow / Mail-in-a-Box”

If you run your own mail server, treat it like any other SMTP:

Host: mail.example.com
Port: 465 (or 587 / 25 depending on your server)
Encryption: TLS or STARTTLS
Password: <the password for that mailbox>
From: TravStats <[email protected]>

The advantage is full deliverability control. The downside is the DKIM / SPF / DMARC setup if you haven’t done it yet — Gmail and Outlook reject mail from servers without proper SPF/DKIM in 2026.

SymptomLikely cause
”Authentication failed”Password wrong (most often: account password instead of app-specific password for Gmail / Outlook)
“Connection timeout”Host wrong, or port blocked outbound on your network (some ISPs block port 25 — use 587 or 465)
“TLS handshake failed”Encryption setting mismatched (host requires STARTTLS but you set TLS, or vice versa)
Mail sent successfully but recipient never receives itDKIM / SPF / DMARC missing on your sending domain → mail filtered as spam by recipient
”Test mail” works but invitation emails don’t arriveDNS-level issue between when you tested (~30 s ago) and now — try again, often resolves

The TravStats logs (docker compose logs app | grep smtp) carry the underlying error verbatim. If the test-mail UI says “failed” without a clear reason, the log line right before will name the actual provider error.

Single-user, single-admin instances skip SMTP entirely:

  • Admins create users via Admin → Users → Create user with a password that’s known and shared out-of-band.
  • Password recovery for the admin uses the bcrypt-reset trick.
  • Flight reminders: just disabled in Settings → Notifications.

A working multi-user instance with three or more users should configure SMTP — getting people their own login credentials gets tedious without it.

Plain-text and HTML emails for the three message types. No tracking pixels, no embedded images served from third-party CDNs, no analytics. Each email contains:

  • Subject line that names the message type
  • The relevant link (invitation token, password reset, flight detail)
  • A footer with your TravStats instance name and base URL

The email body is composed from a template at backend/src/services/emailService.ts. Custom templates aren’t a UI feature yet but you can fork and patch if you really want to.