docker-postfix

repository·master·Indexed 21 days ago

https://github.com/bokysan/docker-postfix

A simple Postfix relay host designed to run as a Docker container or Kubernetes deployment. It centralizes outgoing email sending for applications, supporting direct mail or relaying through a primary corporate SMTP server. Features include DKIM signing via rspamd (default since v6.0.0) or OpenDKIM, SASL XOAuth2 for Gmail relay, email anonymization in logs, and support for multiple CPU architectures. It can be deployed via Docker or Helm charts.

Tokens
12.5K
Snippets
25
Records
37
Agent score
65%

What's inside docker-postfix

  1. Important considerations for SMTP relaying

    master

    When using docker-postfix to send mail, be aware of the following requirements to prevent your emails from being flagged as spam:

    • Port 25 Blocking: Many ISPs and hosting providers (like AWS) block outgoing connections on port 25. This image uses port 587 by default to avoid common issues.
    • DNS Records: You will likely need to configure:
      • SPF (Sender Policy Framework) records.
      • DKIM (DomainKeys Identified Mail) records.
      • PTR (Reverse DNS) records.
    • Static IP: It is difficult to host an SMTP server on a dynamic IP address; a static IP is highly recommended.
  2. Anonymize emails in Postfix logs

    master

    Use the ANONYMIZE_EMAILS variable to mask email addresses in logs. The syntax is ANONYMIZE_EMAILS=<filter>?<option>=<value>. Options are URL-encoded.

    Available Filters:

    1. smart (or default): Leaves the first and last letter of the local part and the TLD, replacing the rest with a single asterisk.

      • Example: demo@example.org -> d*o@*******.org
      • Parameter: mask_symbol (default *)
    2. paranoid: Replaces the entire local part and the domain (except TLD) with a single asterisk.

      • Example: demo@example.org -> *@*.org
      • Parameter: mask_symbol (default *)
    3. hash: Replaces the email with a salted HMAC-SHA256 hash. This allows searching logs if you know the email.

      • Example: ANONYMIZE_EMAILS=hash?salt=demo
      • Parameters:
        • salt (Required): HMAC key.
        • prefix: Prefix for the hash.
        • suffix: Suffix for the hash.
        • split: Set to 1, t, or true to hash local and domain parts separately.
        • short_sha: Set to 1, t, or true to return only the first 8 characters.
        • case_sensitive: Set to 0, f, or false to lowercase before hashing.
    4. noop: Does nothing (for testing).

  3. Quickstart: Run docker-postfix with Docker

    master

    To run the Postfix relay host as a container, use the following command. You must specify ALLOWED_SENDER_DOMAINS to restrict which domains can send mail through this relay. The image uses port 587 (submission) by default, which is mapped to host port 1587 in this example.

    Once running, your applications can send emails using localhost:1587 as the SMTP server address.

    docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com" -p 1587:587 boky/postfix
    # or
    docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com" -p 1587:587 ghcr.io/bokysan/postfix
  4. Quickstart: Install docker-postfix with Helm

    master

    To install the Postfix relay host in a Kubernetes cluster using Helm, add the repository and upgrade/install the chart. This example disables persistence and allows empty sender domains.

    helm repo add bokysan https://bokysan.github.io/docker-postfix/
    helm upgrade --install --set persistence.enabled=false --set config.general.ALLOW_EMPTY_SENDER_DOMAINS=yes mail bokysan/mail
    # or, using the OCI registry:
    helm upgrade --install --set persistence.enabled=false --set config.general.ALLOW_EMPTY_SENDER_DOMAINS=yes mail oci://ghcr.io/bokysan/charts/mail
  5. Use Docker or Kubernetes Secrets for sensitive data

    master

    Instead of plain environment variables, you can append _FILE to certain variables to load values from files (e.g., Docker secrets in /run/secrets/).

    Supported variables for _FILE suffix:

    • RELAYHOST_PASSWORD_FILE (Note: documentation implies RELAYHOST_PASSWORD is the base, but usage shows _FILE suffix on others)
    • XOAUTH2_CLIENT_ID_FILE
    • XOAUTH2_SECRET_FILE
    • XOAUTH2_INITIAL_ACCESS_TOKEN_FILE
    • XOAUTH2_INITIAL_REFRESH_TOKEN_FILE
    docker run --rm --name pruebas-postfix \
        -e RELAYHOST="[smtp.gmail.com]:587" \
        -e RELAYHOST_USERNAME="<put.your.account>@gmail.com" \
        -e POSTFIX_smtp_tls_security_level="encrypt" \
        -e XOAUTH2_CLIENT_ID_FILE="/run/secrets/xoauth2-client-id" \
        -e XOAUTH2_SECRET_FILE="/run/secrets/xoauth2-secret" \
        -e ALLOW_EMPTY_SENDER_DOMAINS="true" \
        -e XOAUTH2_INITIAL_ACCESS_TOKEN_FILE="/run/secrets/xoauth2-access-token" \
        -e XOAUTH2_INITIAL_REFRESH_TOKEN_FILE="/run/secrets/xoauth2-refresh-token" \
        boky/postfix
  6. Relay messages through a Google Apps (G Suite) account

    master

    If you have a Google Apps/G Suite account and a static IP, you can use the Google SMTP relay service to send email from any address within your domain.

    Steps to configure in Google Admin:

    1. Navigate to Admin / Apps / G Suite / Gmail / Advanced settings.
    2. Find Routing / SMTP relay service and click Add another.
    3. Set Allowed senders to "Only registered Apps users in my domains".
    4. Select Only accept mail from specified IP Addresses and add your server's external IP.
    5. Ensure Require SMTP Authentication is NOT selected (you may select Require TLS encryption).

    Required environment variables:

    • RELAYHOST: Set to smtp-relay.gmail.com:587.
    • ALLOWED_SENDER_DOMAINS: Your domain name.

    Gmail automatically handles DKIM and SPF headers for these relayed messages.

    RELAYHOST=smtp-relay.gmail.com:587
    ALLOWED_SENDER_DOMAINS=<your-domain>
  7. Relay messages through Amazon SES

    master

    Use Amazon SES to send email, especially if running on Amazon EC2. You must use Amazon SES SMTP credentials, which are unique to each AWS Region and are different from your AWS secret access key.

    Required environment variables:

    • RELAYHOST: The SES SMTP endpoint for your region (e.g., email-smtp.eu-central-1.amazonaws.com:587).
    • RELAYHOST_USERNAME: Your SES SMTP username.
    • RELAYHOST_PASSWORD: Your SES SMTP password.
    • ALLOWED_SENDER_DOMAINS: Your domain name.

    Note: You must manually configure DKIM and SPF for your domain when using Amazon SES.

    RELAYHOST=email-smtp.eu-central-1.amazonaws.com:587
    RELAYHOST_USERNAME=AKIAGHEVSQTOOSQBCSWQ
    RELAYHOST_PASSWORD=BK+kjsdfliWELIhEFnlkjf/jwlfkEFN/kDj89Ufj/AAc
    ALLOWED_SENDER_DOMAINS=<your-domain>
  8. Send messages directly (No Relay)

    master

    To send email directly from your server without a relay host, you must meet several strict requirements to avoid being flagged as spam:

    • Have a fixed IP address.
    • Configure a reverse PTR record.
    • Configure SPF and/or DKIM records.
    • Ideally, own your own IP block.

    Required environment variables:

    • ALLOWED_SENDER_DOMAINS: Your domain name.

    Warnings:

    • Many hosting providers block outgoing connections on port 25 (e.g., AWS requires a request to unblock it).
    • Microsoft (Outlook/Hotmail) is highly restrictive; you may need to enroll in their Smart Network Data Service (SNDS) program, which requires owning the netblock.
    ALLOWED_SENDER_DOMAINS=<your-domain>
  9. Relay messages through a Gmail account

    master

    To use a personal Gmail account as a relay, you must use an "app password" (via Less secure apps) or configure XOAuth2 authentication. Note that you must use your Gmail address as the sender address. Gmail automatically handles DKIM and SPF headers for these relayed messages.

    Required environment variables:

    • RELAYHOST: Set to smtp.gmail.com:587.
    • RELAYHOST_USERNAME: Your Gmail address.
    • RELAYHOST_PASSWORD: Your Gmail app password.
    • ALLOWED_SENDER_DOMAINS: Set to gmail.com.
    RELAYHOST=smtp.gmail.com:587
    RELAYHOST_USERNAME=you@gmail.com
    RELAYHOST_PASSWORD=your-gmail-app-password
    ALLOWED_SENDER_DOMAINS=gmail.com
  10. Migrate DKIM backend from OpenDKIM to rspamd

    master

    Starting with v6.0.0, the default DKIM backend has changed from OpenDKIM to rspamd.

    Automatic Migration

    For most users, the transition is automatic:

    • Key Import: On first startup, any DKIM keys found in /etc/opendkim/keys are automatically copied into rspamd. Your existing keys are preserved, allowing you to switch back if necessary.
    • DNS Compatibility: rspamd uses relaxed/relaxed canonicalization, so your existing DNS records remain valid.
    • Internal Wiring: Postfix is automatically configured to use the rspamd milter at inet:localhost:11332 instead of OpenDKIM's inet:localhost:8891.

    Manual Configuration

    • Keep OpenDKIM: If you are not ready to migrate, set the environment variable DKIM_BACKEND=opendkim to continue using OpenDKIM. Note that OpenDKIM is deprecated and will be removed in a future major release.
    • Read-Only Filesystems: If running with a read-only root filesystem, you must provide writable paths for rspamd. Mount volumes (e.g., emptyDir or tmpfs) to:
      • /etc/rspamd
      • /var/lib/rspamd
    # To keep using OpenDKIM
    DKIM_BACKEND=opendkim
    
    # Required writable paths for read-only root setups
    # Mount these as emptyDir or tmpfs
    /etc/rspamd
    /var/lib/rspamd
  11. Enable Prometheus metrics

    master

    To enable Prometheus metrics, set metrics.enabled=true in your Helm values.

    Important Caveats:

    • When metrics are enabled, Postfix logs will be sent to /var/log/mail.log in addition to stdout.
    • The /var/log/mail.log file is always in plain-text format, regardless of your LOG_FORMAT setting.
    • You can configure a ServiceMonitor for Prometheus Operator integration via metrics.serviceMonitor.enabled.
  12. Extend the image with custom init scripts

    master

    You can execute custom logic or configuration during the container startup by adding .sh files to the /docker-init.d/ directory. All scripts in this directory are executed automatically at the end of the startup script.

    Method 1: Custom Dockerfile Use ADD to include your script in the image.

    FROM boky/postfix
    ADD Dockerfiles/additional-config.sh /docker-init.d/

    Method 2: Bind Mount Bind a local folder containing your scripts to /docker-init.d/ in your container runtime configuration. This is useful for overriding configurations without rebuilding the image.

    Example script content (/docker-init.d/custom-config.sh):

    #!/bin/sh
    postconf -e "address_verify_negative_cache=yes"
    FROM boky/postfix
    LABEL maintainer="Jack Sparrow <jack.sparrow@theblackpearl.example.com>"
    ADD Dockerfiles/additional-config.sh /docker-init.d/