Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Manual smoke test: SMTP notifications

The SMTP backend talks a real mail protocol, so CI can’t exercise the TLS modes without a relay. Message construction is covered automatically by the build_message unit tests in src/notify/smtp.rs, and plaintext delivery by tests/smtp_plaintext.rs against an in-process fake server; this procedure verifies the transport (connection, STARTTLS, auth) against a real catcher.

Prerequisites

  • freshdock built locally: just build.

  • A local SMTP catcher. mailpit is the simplest. It exposes SMTP on :1025 and a web inbox on :8025:

    docker run --rm -p 1025:1025 -p 8025:8025 axllent/mailpit
    

Plain delivery (no TLS, no auth)

  1. Write a freshdock.toml pointing at the catcher. tls = "none" because mailpit’s default listener speaks plaintext SMTP:

    [notifications.email]
    type = "smtp"
    host = "localhost"
    port = 1025
    from = "[email protected]"
    to = ["[email protected]"]
    tls = "none"
    # triggers omitted: subscribes to available, succeeded, and failed
    

    Or skip the file entirely and declare the same target with an env URL:

    export FRESHDOCK_NOTIFY_EMAIL_URL='smtp://localhost:1025/[email protected]&[email protected]&tls=none'
    

    Not starttls = false: that legacy key selects implicit TLS (SMTPS), so the earlier version of these instructions opened a TLS handshake against mailpit’s plaintext listener and could never deliver (#57/#58). Only tls = "none" disables encryption.

    port is spelled out on purpose: an omitted port defaults from the mode, and for tls = "none" that is the classic SMTP port 25. Mailpit listens on 1025.

  2. Trigger a notification. The quickest path is a watch-mode container with a newer image available; or force a failed update (a broken healthcheck) to exercise the failed trigger and its rollback detail. Run the daemon:

    cargo run -- run
    

    Startup logs one WARN per plaintext target (smtp target uses a PLAINTEXT transport ...). That warning is expected here, and it is the reason tls = "none" never belongs in a deployment.

  3. Open the mailpit inbox at http://localhost:8025 and confirm a message arrived with the rendered Subject (Update available: ... / Updated: ... / Update failed: ...) and the matching body.

STARTTLS + auth

STARTTLS and PLAIN/LOGIN auth must be verified against a server that requires them (mailpit’s --smtp-auth modes, a real provider, or smtp4dev with TLS enabled):

  1. Point host/port at the TLS-capable relay, set tls = "starttls", and add credentials. The password may be supplied inline or via the environment override (so it stays out of the file):

    [notifications.email]
    type = "smtp"
    host = "smtp.example.com"
    port = 587
    username = "[email protected]"
    from = "[email protected]"
    to = ["[email protected]"]
    tls = "starttls"
    
    export FRESHDOCK_NOTIFY_EMAIL_PASSWORD='app-password'
    cargo run -- run
    

    Or as a single env URL (percent-encode @/: in the login as %40/%3A):

    export FRESHDOCK_NOTIFY_EMAIL_URL='smtp://freshdock%40example.com:[email protected]:587/[email protected]&[email protected]&tls=starttls'
    
  2. Confirm the message is delivered. A STARTTLS handshake failure surfaces as a smtp send failed: ... WARN line; delivery is non-fatal, so the daemon keeps running regardless.

Pass criteria

  • A message with the correct subject/body lands in the inbox for each trigger.
  • The STARTTLS run authenticates and delivers without falling back to plaintext.
  • The bot token / SMTP password never appears in freshdock’s log output.