Giter VIP home page Giter VIP logo

docker-postfix's Introduction

Postfix Docker Image

Postfix SMTP Relay based on Debian Bullseye.

Highly configurable Docker image for SMTP relaying. Use wherever a connected service requires SMTP sending capabilities. Supports TLS out of the box and DKIM (if enabled and configured).

Not intended to be used for receiving email for local delivery or end-user email access.

This image is available on quay.io quay.io/panubo/postfix and AWS ECR Public public.ecr.aws/panubo/postfix.

Environment Variables

  • MAILNAME - set this to a legitimate FQDN hostname for this service (required). (example, mail.example.com)
  • MYNETWORKS - comma separated list of IP subnets that are allowed to relay. Default 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • LOGOUTPUT - Log file location. eg /var/log/maillog. Default /dev/stdout. See Logging
  • TZ - set timezone. This is used by Postfix to create Received headers. Default UTC.
  • POSTFIX_EXPORTER_ENABLED - enable the Prometheus postfix_exporter. Default false. See Postfix Exporter

General Postfix:

  • SIZELIMIT - Postfix message_size_limit. Default 15728640.
  • POSTFIX_ADD_MISSING_HEADERS - add missing headers. Default no. (options, yes, no)
  • INET_PROTOCOLS - IP protocols, eg ipv4 or ipv6. Default all. (options, ipv4, ipv6, all)
  • BOUNCE_ADDRESS - Email address to receive delivery failure notifications. Default is to log the delivery failure.
  • HEADER_CHECKS - If true activates a set of pre-configured header_checks. (options, true, false)
  • DISABLE_VRFY_COMMAND - Prevents some email address harvesting techniques. Default yes. (options, yes, no)

Rate limiting parameters:

These are common parameters to rate limit outbound mail:

  • SMTP_DESTINATION_CONCURRENCY_LIMIT - Number of concurrent connections per receiving domain.
  • SMTP_DESTINATION_RATE_DELAY - Additional delay (eg 5s) between messages to the same receiving domain.
  • SMTP_EXTRA_RECIPIENT_LIMIT - Limit the number of recipients of each message sent to the receiving domain.

Relay host parameters:

  • RELAYHOST - Postfix relay host. Default ''. (example mail.example.com:25, or [email-smtp.us-west-2.amazonaws.com]:587). N.B. Use square brackets to prevent MX lookup on relay hostname.
  • RELAYHOST_AUTH - Enable authentication for relay host. Generally used with RELAYHOST_PASSWORDMAP. Default no. (options, yes, no).
  • RELAYHOST_PASSWORDMAP - Relay host password map in format: RELAYHOST_PASSWORDMAP=[mail1.example.com]:587:user1:pass1,mail2.example.com:user2:pass2,user3:pass3.
  • RELAYHOST_MAP - Sender dependent relayhost map in format: [email protected]:smtp.example.com:587,@domain2.com:[smtp.example.com]:587
  • SENDER_DEPENDENT_RELAYHOST_AUTH - Enable sender dependent authentication for relay host. Generally used with RELAYHOST_MAP and RELAYHOST_PASSWORDMAP. Default no. (options, yes, no).

Client authentication parameters:

Client authentication is used to authenticate relay clients. Client authentication can be used in conjunction with, or as an alternative to MYNETWORKS.

  • SMTPD_USERS - SMTPD Users user1:password1,user2:password2

TLS parameters:

  • USE_TLS - Enable TLS. Default yes (options, yes, no)

  • TLS_SECURITY_LEVEL - Default may (opportunistic). (options, may, encrypt, others see: www.postfix.org/postconf.5.html#smtp_tls_security_level)

  • TLS_KEY - Default /etc/ssl/private/ssl-cert-snakeoil.key

  • TLS_CRT - Default /etc/ssl/certs/ssl-cert-snakeoil.pem

  • TLS_CA - Default ''

  • CLIENT_TLS_SECURITY_LEVEL - Default may same as TLS_SECURITY_LEVEL but for client TLS

  • CLIENT_TLS_KEY - Default /etc/ssl/private/ssl-cert-snakeoil.key

  • CLIENT_TLS_CRT - Default /etc/ssl/certs/ssl-cert-snakeoil.pem

  • CLIENT_TLS_CA - Default ''

NB. A self-signed ("snake-oil") certificate will be generated on start if required.

DKIM parameters:

  • USE_DKIM - Enable DKIM. Default no (options, yes, no)
  • DKIM_KEYFILE - DKIM Keyfile location. Default /etc/opendkim/dkim.key
  • DKIM_DOMAINS - Domains to sign. Defaults to MAILNAME. Multiple domains will use the same key and selector.
  • DKIM_SELECTOR - DKIM key selector. Default mail. <selector>._domainkey.<domain> is used for resolving the public key in DNS.
  • DKIM_INTERNALHOSTS - Defaults to MYNETWORKS.
  • DKIM_EXTERNALIGNORE - Defaults to MYNETWORKS.
  • DKIM_OVERSIGN_HEADERS - Sets OversignHeaders. Default From.
  • DKIM_SENDER_HEADERS - Sets SenderHeaders. Default unset.
  • DKIM_SIGN_HEADERS - Sets SignHeaders. Default unset.
  • DKIM_OMIT_HEADERS - Sets OmitHeaders. Default unset.

Advanced Postfix parameters:

In some cases it might be necessary to further customise Postfix parameters that are not explicitly exposed via environment variables. In this case the environment variable POSTCONF provides a hook that is directly passed to postconf -e after splitting it by ;. N.B. this is different from existing usage of other multi-value options that use a comma.

Example usage:

POSTCONF=masquerade_domains=foo.example.com example.com;masquerade_exceptions=root,mailer-daemon

Would result in masquerade_domains and masquerade_exceptions being configured for Postfix.

Config Reloader

The config reloader watches the known TLS cert and keys (TLS_CRT, TLS_KEY etc) for changes (mv or updated Kubernetes secret) then reloads Postfix.

  • CONFIG_RELOADER_ENABLED - Enable the config reloader. Default false, must be set to true to enable.

Postfix Prometheus Exporter

This image comes with kumina/postfix_exporter pre-installed. To enable set the environment variable POSTFIX_EXPORTER_ENABLED=true (this must be exactly "true"). The exporter requires that the logoutput is /dev/stdout it can't be anything else.

The exporter listens on port 9154/tcp.

See Logging

Logging

This container outputs the Postfix mail log to stdout by default, additionally logs are saved to /var/log/s6-maillog/current which is rotated every 10MB with only 3 log files retained.

If you want to output somewhere else you can set environment variable LOGOUTPUT. For example LOGOUTPUT=/var/log/maillog.

When enabled OpenDKIM only supports syslog output, the syslogd daemon is only used for OpenDKIM. Only /dev/stdout is supported for OpenDKIM syslog logs.

Note: the Postfix Prometheus exporter only works when the logs are left at /dev/stdout. This requirement of logs going to /dev/stdout is due to the containers logging structure. This may be improved but was needed to keep with backwards compatibility without adding additional variables to configured

Note: The log /var/log/s6-maillog/current is always created but won't actually contain any logs if LOGOUTPUT is not /dev/stdout.

Custom Scripts

Executable shell scripts and binaries can be mounted or copied in to /etc/entrypoint.d. These will be run when the container is launched but before postfix is started. These can be used to customise the behaviour of the container.

Usage Example

Simple example:

docker run -e MAILNAME=mail.example.com quay.io/panubo/postfix:latest

Usage with SendGrid:

docker run --rm -t -i \
  --name smtp \
  -v $(pwd)/spool:/var/spool/postfix:rw \
  -e MAILNAME=mail1.example.com \
  -e RELAYHOST_AUTH='yes' \
  -e RELAYHOST='[smtp.sendgrid.net]:587' \
  -e RELAYHOST_PASSWORDMAP="[smtp.sendgrid.net]:587:apikey:<apikey goes here>" \
  quay.io/panubo/postfix:latest

Volumes

No volumes are defined. If you want persistent spool storage then mount /var/spool/postfix outside of the container.

Ports

Ports 25, 587 and 2525 are enabled.

Test email

To send a test email via the command line, make sure heirloom-mailx (aka bsd-mailx) is installed.

echo -e "To: Bob <[email protected]>\nFrom: Bill <[email protected]>\nSubject: Test email\n\nThis is a test email message" | mailx -v -S smtp=smtp://... -S [email protected] -t

# With TLS
echo -e "To: Bob <[email protected]>\nFrom: Bill <[email protected]>\nSubject: Test email\n\nThis is a test email message" | mailx -v -S smtp-use-starttls -S ssl-verify=ignore -S smtp=smtp://... -S [email protected] -t

# With TLS on Centos/Fedora (extra nss-config-dir)
echo -e "To: Bob <[email protected]>\nFrom: Bill <[email protected]>\nSubject: Test email\n\nThis is a test email message" | mailx -v -S smtp-use-starttls -S ssl-verify=ignore -S nss-config-dir=/etc/pki/nssdb -S smtp=smtp://... -S [email protected] -t

Developing

See the Makefile for make targets.

Releases

For production usage, please use a versioned release rather than the floating 'latest' tag.

See the releases for tag usage and release notes.

Status

Production ready and stable.

docker-postfix's People

Contributors

apollo13 avatar jamesgol avatar jebw avatar macropin avatar pragmatic avatar trnubo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

docker-postfix's Issues

Add disable_vrfy_command=yes to main.cf

Vulnerability scanners flag this as a vulnerability because it allows an attacker to find if a mailbox exists on the postfix server or not. This doesn't apply specifically to this container as it's just an SMTP relay and has no mailboxes hosted on it, but it would be an easy addition to the configuration file.

[Help] Host or domain name not found. Name service error for name

Got this issues:

postfix/error[3180]: DF27F16456B: to=<[email protected]>, relay=none, delay=369825, delays=369825/0.15/0/0, dsn=4.4.3, status=deferred (delivery temporarily suspended: Host or domain name not found. Name service error for name=yahoo.co.id type=MX: Host not found, try again)

Here is my docker compose:

image: panubo/postfix
    environment:
      MAILNAME: domain_name.id 
      MYNETWORKS: "127.0.0.1/32, 10.21.0.0/24"
      USE_TLS: 'no'
    volumes:
      - /etc/resolv.conf:/etc/resolv.conf
      - ./mail/spool/postfix:/var/spool/postfix
    restart: always
    ports:
      - "587:25"

Anyone can help, what i miss in config ?

if use_tls is false than even smtp_use_tls needs to be set to no.

if the Host server has authentication but is not in TLS. than both smtp_use_tls and smtpd_use_tls should be set to no.
However As seen in the code below the smtp_use_tls is set to true if there is RELAYHOST_AUTH is set.

if [ "${RELAYHOST_AUTH}" == "yes" ]; then
    echo "postfix >> Enabling relayhost authentication"
    touch /etc/postfix/sasl-passwords
    postconf -e smtp_sasl_auth_enable=yes
    postconf -e smtp_sasl_security_options=noanonymous
    postconf -e smtp_sasl_password_maps=hash:/etc/postfix/sasl-passwords
    # require encryption with relayhost auth
    postconf -e smtp_use_tls=yes
    postconf -e smtp_tls_security_level=encrypt
    postconf -e smtp_sasl_mechanism_filter="PLAIN LOGIN"
fi

in such case both

    postconf -e smtp_use_tls=yes
    postconf -e smtp_tls_security_level=encrypt

Needs to be removed.

Invalid dkim signature

Hi, docker-postfix is mostly working great but I'm having some issues with DKIM. I have a valid dkim key that I was using on my system's postfix before migrating to this docker image, and I'm mounting it at /etc/opendkim/dkim.key in the container and setting USE_DKIM to yes. The server signs outgoing emails but mail-tester is saying the DKIM signature is invalid. I've verified that the TXT record is correct.

Do you have any ideas on how to troubleshoot? Do I need to mount any other files for DKIM?

normalise boolean tokens

Need to add a function to normalise boolean tokens, yes, no, true, false, True, False to make configuration less error prone.

Support Docker secrets for sensitive data, e.g. `RELAYHOST_PASSWORDMAP`

Currently passwords are stored in env variable RELAYHOST_PASSWORDMAP.

So I think it would be nice if the container either asks for RELAYHOST_PASSWORDMAP or RELAYHOST_PASSWORDMAP_FILE. Then I could set RELAYHOST_PASSWORDMAP_FILE=/run/secrets/relay-password and the container could make sure that postmap is called on that file.

buster image is not able to resolve hosts

I started using the buster image, because of the non default ports I use.
But I had problem, that postfix was not able to resolve the relay hostname.
I think the problem comes from the change to start postfix directly instead of the service script.
The service script does a lot for postfix, because it's instances runs in chroot environment.

quick and dirty, going into the running container and executing the following worked:
cp /etc/resolv.conf /var/spool/postfix/etc/resolv.conf

I forked your version to just copy this file in the run script, which works for me.
But I think it would be cleaner to somehow reuse the init script again. Otherwise you have to re-implement all that again.
i.e. init script calls /usr/lib/postfix/configure-instance.sh for EACH instance of postfix which does a lot more than just copy the resolve.conf file.

Support changing an envelope sender address to a subdomain to support DMARC

When sending or relaying mail on behalf of a customer it would be useful to be able to rewrite the envelope sender to a subdomain that has been delegated to the email service provider (this container) so that DMARC compliance can be achieved.

This doc https://dmarcian.com/how-to-send-dmarc-compliant-email-on-behalf-of-others/ describes getting a subdomain delegated so the mail provider can configured DKIM and SPF independently of the root organisation domain.

It would be good if this container should rewrite the envelope sender to use a subdomain even if the From header is the root organisation domain.

eg. From: [email protected] rewrite to [email protected]

entrypoint.d runs before normal configuration

The initialisation and configuration of postfix etc, should be moved out of the s6 scripts and into separate init scripts that are run from entry.sh before the entrypoint.d scripts. This will allow for entrypoint.d scripts to override any config done.

Recipient address rejected: User unknown in local recipient table

When sending an email to my domain specified in the MAILNAME, getting an error:

smtp-server: 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown in local recipient table

SMTP relay is not my mail server. Variable mydestination is responsible for this

postconf -e mydestination="${MAILNAME}"

Just change to

postconf -e mydestination="${MYDESTINATION}"

By default it is better to make a value localhost

Thanks for your image.

`postfix set-permissions` fails when the overlay Docker Storage Driver is used

Postfix initialization (/etc/s6/postfix/run) includes a call to postfix set-permissions.

This will check the /etc/mailname file and will cause an error (and ultimately a failure to start this Docker image) if the file has hard links.

One can figure out if the problem will manifest itself by running this command:

/usr/bin/docker run -it --rm \
--entrypoint=/bin/bash \
panubo/postfix:latest \
-c '/usr/bin/stat /etc/mailname'

Why would the file have a different number of hard links? So far, my guess is that it's due to the way the overlay Storage Driver for Docker is implemented.

I appears that I can reproduce this problem (the file has 7 hard links for me) when running Docker with the overlay Storage Driver.

I cannot reproduce it on machines that use the the overlay2 or devicemapper drivers.

Looking at the Overlay documentation confirms it:

While the overlay driver only works with a single lower OverlayFS layer and hence requires hard links for implementation of multi-layered images, the overlay2 driver natively supports up to 128 lower OverlayFS layers.

And here's another comment that confirms the Postfix problem.


While this is more of a problem caused by:

  • a limitation of the overlay Docker storage driver
  • postfix being overly-precautions about hard links

.. it still makes this image fail on Docker systems using the overlay driver.

If you'd like to support those, this image may employ some workaround.

It seems like the following code (to be executed before postfix set-permissions) should be able to work-around the problem, by making sure that a new file is created:

echo 'mail.example.com' > /etc/mailname

SMTPD_USERS not working

Either I am confused about how this is supposed to work, or it is not working. When I enter a value for
SMTPD_USERS (e.g. notblank:notblank ), I can still submit emails to postfix without any credentials and they are accepted and relayed. Is that expected behavior? Here are the relevant log entries:

postfix >> Setting smtpd sasl auth postfix >> Adding user SASL user: notblank Jul 19 06:06:22 saslpasswd2: error deleting entry from sasldb: BDB0073 DB_NOTFOUND: No matching key/data pair found Jul 19 06:06:22 saslpasswd2: error deleting entry from sasldb: BDB0073 DB_NOTFOUND: No matching key/data pair found Jul 19 06:06:22 saslpasswd2: error deleting entry from sasldb: BDB0073 DB_NOTFOUND: No matching key/data pair found Jul 19 06:06:22 saslpasswd2: DIGEST-MD5 common mech free smtp >> Info: "saslpasswd2: error deleting entry from sasldb: BDB0073 DB_NOTFOUND: No matching key/data pair found" can be ignored see https://github.com/cyrusimap/cyrus-sasl/issues/264

Support sender_dependent_relayhost_maps

Adding support for sender_dependent_relayhost_maps will allow this container to send to different relay hosts based on the sender.

For example we want to send *@example.com via relay 1 and *@example.net via relay 2.

RELAYHOST_PASSWORDMAP does not support non standard ports

Unable to set the /etc/postfix/sasl-passwords file when a non-default port is used.
when a non default port is set .. the format become like
the format of the file is
[<domain_name>]:<Port> <user>:<Password>
However the code is incorrectly mentioned.

    IFS=',' read -r -a PASSWORDMAP <<< "${RELAYHOST_PASSWORDMAP}"
    for P in "${PASSWORDMAP[@]}"; do
        IFS=':' read -ra MAP <<< "$P"
        HOST=${MAP[0]}
        USER=${MAP[1]}
        PASS=${MAP[2]}

Here the USER becomes <Port> <user> which is incorrect.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.