Larger refactoring of the codebase + DKIM_SELECTOR

Summary
^^^^^^^

This commit refactors the code base to be more manageble and
prepares the groundwork for tests.

Refactoring
^^^^^^^^^^^

Files are now moved to subdirectories, all for the sole purpose of
easier management. Tests live in their own folders, as well as configs
and other files.

Test framework
^^^^^^^^^^^^^^

Two new important scripts/directories are available:
- `unit-tests.sh` / `/unit-test` which executes unit tests across shell
  scripts, and
- `integration-test.sh` / `integration-tests`, which spins up the
  container and tries to send the email.

Both tests use the [BATS](https://github.com/sstephenson/bats) framework
for testing. To create a new test, simply drop a `.bats` file into a
corresponding directory.

Functions have been extracted into `common-run.sh`, to be able to test
them independently.

DKIM_SELECTOR
^^^^^^^^^^^^^

It is now possible to specify a DKIM selector to use (instead of
the default "mail"). See `README.md` for more details.

JSON logging
^^^^^^^^^^^^

WIP: rsyslog will now output JSON logs. This is especially important
if you plan on deploying the image into Kubernetes, as [Prometheus](https://prometheus.io/)
can handle logs in JSON much easier.

TODO: Make this an optional feature, to not confuse existing users.
This commit is contained in:
Bojan Čekrlić 2020-06-29 18:49:52 +02:00
parent ed09d86c8d
commit 9b1902c047
26 changed files with 638 additions and 336 deletions

25
.editorconfig Normal file
View file

@ -0,0 +1,25 @@
# http://editorconfig.org
root = true
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
max_line_length = 120
# Indent shell scripts with tabs
[**.sh,**.bats]
indent_style = tab
# Indent YAML files with spaces
[**.yaml,**.yml]
indent_style = space
# The JSON files contain newlines inconsistently
[*.json]
insert_final_newline = ignore
# Minified JavaScript files shouldn't be changed
[**.min.js]
indent_style = ignore
insert_final_newline = ignore

View file

@ -27,6 +27,8 @@ ENV ALLOW_EMPTY_SENDER_DOMAINS=
ENV MESSAGE_SIZE_LIMIT=
# Enable additional debugging for connections to postfix
ENV INBOUND_DEBUGGING=
# DKIM domain selector. If not set, the default (mail) will be used
ENV DKIM_SELECTOR=
# Install supervisor, postfix
# Install postfix first to get the first account (101)
@ -40,11 +42,12 @@ RUN true && \
(rm "/tmp/"* 2>/dev/null || true) && (rm -rf /var/cache/apk/* 2>/dev/null || true)
# Set up configuration
COPY supervisord.conf /etc/supervisord.conf
COPY rsyslog.conf /etc/rsyslog.conf
COPY opendkim.conf /etc/opendkim/opendkim.conf
COPY smtp_header_checks /etc/postfix/smtp_header_checks
COPY commons.sh run.sh opendkim.sh /
COPY /configs/supervisord.conf /etc/supervisord.conf
COPY /configs/rsyslog.conf /etc/rsyslog.conf
COPY /configs/opendkim.conf /etc/opendkim/opendkim.conf
COPY /configs/smtp_header_checks /etc/postfix/smtp_header_checks
COPY /scripts/*.sh /
RUN chmod +x /run.sh /opendkim.sh
# Set up volumes

View file

@ -1,10 +1,6 @@
# docker-postfix ![Docker image](https://github.com/bokysan/docker-postfix/workflows/Docker%20image/badge.svg)
Simple postfix relay host for your Docker containers. Based on Alpine Linux.
## Project update
**Notice, that while this commits are old, there project is not dead.** It's simply considered feature complete. You will find the latest version of the code on Dockerhub (https://hub.docker.com/r/boky/postfix). If you do have any suggestions, feel free to clone and post a merge.
Simple postfix relay host ("postfix null client") for your Docker containers. Based on Alpine Linux.
## Description
@ -17,7 +13,8 @@ This is a _server side_ POSTFIX image, geared towards emails that need to be sen
## TL;DR
To run the container, do the following:
```
```sh
docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com" -p 1587:587 boky/postfix
```
@ -26,8 +23,9 @@ you haven't configured your `example.com` domain to allow sending from this IP (
[openspf](http://www.openspf.org/)), your emails will most likely be regarded as spam.
All standard caveats of configuring the SMTP server apply:
- **MAKE SURE YOUR OUTGOING PORT 25 IS NOT BLOCKED.**
- Most ISPs block outgoing connections to port 25 and several companies (e.g. [NoIP](https://www.noip.com/blog/2013/03/26/my-isp-blocks-smtp-port-25-can-i-still-host-a-mail-server/), [Dynu](https://www.dynu.com/en-US/Blog/Article?Article=How-to-host-email-server-if-ISP-blocks-port-25) offer workarounds).
- **MAKE SURE YOUR OUTGOING PORT 25 IS NOT BLOCKED.**
- Most ISPs block outgoing connections to port 25 and several companies (e.g. [NoIP](https://www.noip.com/blog/2013/03/26/my-isp-blocks-smtp-port-25-can-i-still-host-a-mail-server/), [Dynu](https://www.dynu.com/en-US/Blog/Article?Article=How-to-host-email-server-if-ISP-blocks-port-25) offer workarounds).
- Hosting centers also tend to block port 25, which can be unblocked per requirst (e.g. for AWS either [fill out a form](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-port-25-throttle/) or forward mail to their [SES](https://aws.amazon.com/ses/) service, which is free for low volumes)
- You'll most likely need to at least [set up SPF records](https://en.wikipedia.org/wiki/Sender_Policy_Framework) or [DKIM](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail)
- If using DKIM (below), make sure to add DKIM keys to your domain's DNS entries
@ -35,34 +33,38 @@ All standard caveats of configuring the SMTP server apply:
If you don't know what any of the above means, get some help. Google is your friend. It's also worth noting that as a consequence it's pretty difficult to host a SMTP server on a dynamic IP address.
**Please note that the image uses the submission (587) port by default**. Port 25 is not
**Please note that the image uses the submission (587) port by default**. Port 25 is not
exposed on purpose, as it's regularly blocked by ISP or already occupied by other services.
## Configuration options
The following configuration options are available:
```
```Dockerfile
ENV vars
$TZ = The timezone for the image
$HOSTNAME = Postfix myhostname
$RELAYHOST = Host that relays your msgs
$RELAYHOST_USERNAME = An (optional) username for the relay server
$RELAYHOST_PASSWORD = An (optional) login password for the relay server
$RELAYHOST_TLS_LEVEL = Relay host TLS connection leve
$MYNETWORKS = allow domains from per Network ( default 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 )
$ALLOWED_SENDER_DOMAINS = domains sender domains
$ALLOW_EMPTY_SENDER_DOMAINS = if value is set (i.e: "true"), $ALLOWED_SENDER_DOMAINS can be unset
$MESSAGE_SIZE_LIMIT = The size of the messsage, in bytes
$INBOUND_DEBUGGING = Set to 1 to enable detailed debugging in the logs
$MASQUERADED_DOMAINS = domains where you want to masquerade internal hosts
$DKIM_SELECTOR = override DKIM selector (by default "mail")
```
### `HOSTNAME`
You may configure a specific hostname that the SMTP server will use to identify itself. If you don't do it,
the default Docker host name will be used. A lot of times, this will be just the container id (e.g. `f73792d540a5`)
which may make it difficult to track your emails in the log files. If you care about tracking at all,
I suggest you set this variable, e.g.:
```
```sh
docker run --rm --name postfix -e HOSTNAME=postfix-docker -p 1587:587 boky/postfix
```
@ -73,41 +75,44 @@ you will most likely have a dedicated outgoing mail server. By setting this opti
(hence the name) all incoming emails to the target server for actual delivery.
Example:
```
```sh
docker run --rm --name postfix -e RELAYHOST=192.168.115.215 -p 1587:587 boky/postfix
```
You may optionally specifiy a relay port, e.g.:
```
```sh
docker run --rm --name postfix -e RELAYHOST=192.168.115.215:587 -p 1587:587 boky/postfix
```
Or an IPv6 address, e.g.:
```
```sh
docker run --rm --name postfix -e 'RELAYHOST=[2001:db8::1]:587' -p 1587:587 boky/postfix
```
If your end server requires you to authenticate with username/password, add them also:
```
```sh
docker run --rm --name postfix -e RELAYHOST=mail.google.com -e RELAYHOST_USERNAME=hello@gmail.com -e RELAYHOST_PASSWORD=world -p 1587:587 boky/postfix
```
### `RELAYHOST_TLS_LEVEL`
Define relay host TLS connection level. See http://www.postfix.org/postconf.5.html#smtp_tls_security_level for details. By default, the permissive level ("may") is used, which basically means "use TLS if available" and should be a sane default in most cases.
Define relay host TLS connection level. See [smtp_tls_security_level](http://www.postfix.org/postconf.5.html#smtp_tls_security_level) for details. By default, the permissive level ("may") is used, which basically means "use TLS if available" and should be a sane default in most cases.
This level defines how the postfix will connect to your upstream server.
### `MESSAGE_SIZE_LIMIT`
Define the maximum size of the message, in bytes.
See more in [Postfix documentation](http://www.postfix.org/postconf.5.html#message_size_limit).
Define the maximum size of the message, in bytes.
See more in [Postfix documentation](http://www.postfix.org/postconf.5.html#message_size_limit).
By default, this limit is set to 0 (zero), which means unlimited. Why would you want to set this? Well, this is especially useful in relation
with `RELAYHOST` setting. If your relay host has a message limit (and usually it does), set it also here. This will help you "fail fast" --
your message will be rejected at the time of sending instead having it stuck in the outbound queue indefenetly.
### `MYNETWORKS`
This implementation is meant for private installations -- so that when you configure your services using _docker compose_
@ -118,7 +123,8 @@ Most likely you won't need to change this. However, if you need to support IPv6
override this setting.
Example:
```
```sh
docker run --rm --name postfix -e "MYNETWORKS=10.1.2.0/24" -p 1587:587 boky/postfix
```
@ -128,7 +134,8 @@ Due to in-built spam protection in [Postfix](http://www.postfix.org/postconf.5.h
sender domains -- the domains you are using to send your emails from, otherwise Postfix will refuse to start.
Example:
```
```sh
docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com example.org" -p 1587:587 boky/postfix
```
@ -139,13 +146,13 @@ If you want to set the restrictions on the recipient and not on the sender (anyo
Enable additional debugging for any connection comming from `MYNETWORKS`. Set to a non-empty string (usually "1" or "yes") to
enable debugging.
### `MASQUERADED_DOMAINS`
If you don't want outbound mails to expose hostnames, you can use this variable to enable Postfix's [address masquerading](http://www.postfix.org/ADDRESS_REWRITING_README.html#masquerade). This can be used to do things like rewrite `lorem@ipsum.example.com` to `lorem@example.com`.
Example:
```
```sh
docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com example.org" -e "MASQUERADED_DOMAINS=example.com" -p 1587:587 boky/postfix
```
@ -154,24 +161,25 @@ docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com example.or
This image allows you to execute Postfix [header checks](http://www.postfix.org/header_checks.5.html). Header checks allow you to execute a certain
action when a certain MIME header is found. For example, header checks can be used prevent attaching executable files to emails.
Header checks work by comparing each message header line to a pre-configured list of patterns. When a match is found the corresponding action is
Header checks work by comparing each message header line to a pre-configured list of patterns. When a match is found the corresponding action is
executed. The default patterns that come with this image can be found in the `smtp_header_checks` file. Feel free to override this file in any derived
images or, alternately, provide your own in another directory.
Set `SMTP_HEADER_CHECKS` to type and location of the file to enable this feature. The sample file is uploaded into `/etc/postfix/smtp_header_checks`
Set `SMTP_HEADER_CHECKS` to type and location of the file to enable this feature. The sample file is uploaded into `/etc/postfix/smtp_header_checks`
in the image. As a convenience, setting `SMTP_HEADER_CHECKS=1` will set this to `regexp:/etc/postfix/smtp_header_checks`.
Example:
```
```sh
docker run --rm --name postfix -e "SMTP_HEADER_CHECKS="regexp:/etc/postfix/smtp_header_checks" -e "ALLOWED_SENDER_DOMAINS=example.com example.org" -p 1587:587 boky/postfix
```
## `DKIM`
**This image is equiped with support for DKIM.** If you want to use DKIM you will need to generate DKIM keys yourself.
**This image is equiped with support for DKIM.** If you want to use DKIM you will need to generate DKIM keys yourself.
You'll need to create a folder for every domain you want to send through Postfix and generate they key(s) with the following command, e.g.
```
```sh
mkdir -p /host/keys; cd /host/keys
for DOMAIN in example.com example.org; do
@ -188,12 +196,27 @@ done
`opendkim-genkey` is usually in your favourite distribution provided by installing `opendkim-tools` or `opendkim-utils`.
Add the created `<domain>.txt` files to your DNS records. Afterwards, just mount `/etc/opendkim/keys` into your image and DKIM
Add the created `<domain>.txt` files to your DNS records. Afterwards, just mount `/etc/opendkim/keys` into your image and DKIM
will be used automatically, e.g.:
```
```sh
docker run --rm --name postfix -e "ALLOWED_SENDER_DOMAINS=example.com example.org" -v /host/keys:/etc/opendkim/keys -p 1587:587 boky/postfix
```
**NOTE:** `mail` is the *default DKIM selector* and should be sufficient for most usages. If you wish to override the selector,
set the environment variable `DKIM_SELECTOR`, e.g. `... -e DKIM_SELECTOR=postfix`. Note that the same DKIM selector will be
applied to all found domains. To override a selector for a specific domain use the syntax `[<domain>=<selector>,...]`, e.g.:
```sh
DKIM_SELECTOR=foo,example.org=postfix,example.com=blah
```
This means:
- use `postfix` for `example.org` domain
- use `blah` for `example.com` domain
- use `foo` if no domain matches
## Extending the image
If you need to add custom configuration to postfix or have it do something outside of the scope of this configuration, simply
@ -201,7 +224,8 @@ add your scripts to `/docker-init.db/`: All files with the `.sh` extension will
startup script.
E.g.: create a custom `Dockerfile` like this:
```
```sh
FROM boky/postfix
LABEL maintainer="Jack Sparrow <jack.sparrow@theblackpearl.example.com>"
ADD Dockerfiles/additional-config.sh /docker-init.db/
@ -213,12 +237,12 @@ Or -- alternately -- bind this folder in your docker config and put your scripts
to your postfix server or override configs created by the script.
For example, your script could contain something like this:
```
```sh
#!/bin/sh
postconf -e "address_verify_negative_cache=yes"
```
## Security
Postfix will run the master proces as `root`, because that's how it's designed. Subprocesses will run under the `postfix` account

42
configs/rsyslog.conf Normal file
View file

@ -0,0 +1,42 @@
$ModLoad immark.so # provides --MARK-- message capability
$ModLoad imuxsock.so # provides support for local system logging (e.g. via logger command)
# default permissions for all log files.
$FileOwner root
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
template (name="devicelog" type="string" string="/dev/stdout")
template(name="json_syslog"
type="list") {
constant(value="{")
constant(value="\"@timestamp\":\"") property(name="timereported" dateFormat="rfc3339")
constant(value="\",\"type\":\"syslog_json")
constant(value="\",\"tag\":\"") property(name="syslogtag" format="json")
constant(value="\",\"relayhost\":\"") property(name="fromhost")
constant(value="\",\"relayip\":\"") property(name="fromhost-ip")
constant(value="\",\"logsource\":\"") property(name="source")
constant(value="\",\"hostname\":\"") property(name="hostname" caseconversion="lower")
constant(value="\",\"program\":\"") property(name="programname")
constant(value="\",\"priority\":\"") property(name="pri")
constant(value="\",\"severity\":\"") property(name="syslogseverity")
constant(value="\",\"facility\":\"") property(name="syslogfacility")
constant(value="\",\"severity_label\":\"") property(name="syslogseverity-text")
constant(value="\",\"facility_label\":\"") property(name="syslogfacility-text")
constant(value="\",\"message\":\"") property(name="rawmsg" format="json")
constant(value="\",\"end_msg\":\"")
constant(value="\"}\n")
}
if $syslogseverity <= '6' then {
# matching logs will be saved
action(type="omfile" DynaFile="devicelog" template="json_syslog" DirCreateMode="0755" FileCreateMode="0644")
# enable below to stop processing further this log
stop
}
stop

View file

@ -23,7 +23,6 @@ directory = /etc/postfix
command = /usr/sbin/postfix -c /etc/postfix start
startsecs = 0
[program:opendkim]
command = /opendkim.sh
user = opendkim

3
integration-test.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
cd integration-tests
docker-compose up --build --abort-on-container-exit --exit-code-from tests

View file

@ -0,0 +1,15 @@
# ---- MAILSEND ----
FROM boky/alpine-bootstrap AS mailsend
COPY install_mailsend.sh /tmp/
RUN chmod +x /tmp/install_mailsend.sh && /tmp/install_mailsend.sh
# ---- TEST ----
FROM boky/alpine-bootstrap
RUN apk add --no-cache bash bats
COPY --from=mailsend /tmp/mailsend-go-dir/mailsend-go /usr/local/bin/mailsend
WORKDIR /code
ENTRYPOINT ["/usr/bin/bats"]
CMD ["-v"]

View file

@ -1,8 +1,10 @@
version: '3.6'
version: '3.7'
services:
postfix_test_587:
hostname: "postfix"
image: "boky/postfix"
build:
context: ..
restart: always
healthcheck:
test: [ "CMD", "sh", "-c", "netstat -an | fgrep 587 | fgrep -q LISTEN" ]
@ -10,10 +12,16 @@ services:
timeout: 5s
start_period: 10s
retries: 2
ports:
- "1587:587"
volumes:
- "./test-keys:/etc/opendkim/keys"
- "./docker-init.db:/docker-init.db/"
environment:
ALLOWED_SENDER_DOMAINS: "example.org"
INBOUND_DEBUGGING: 1
tests:
image: "boky/postfix-integration-test"
restart: "no"
volumes:
- "..:/code"
build:
context: .
command: "/code/integration-tests/"

View file

@ -0,0 +1,6 @@
#!/bin/sh
. /common.sh
echo -e "$notice Relaying all mails to blackhole.${reset}"
postconf -e "smtpd_end_of_data_restrictions=check_client_access static:discard"

View file

@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -e
install_mailsend() {
local ARCH="$(uname -m)"
local MAILSEND_VERSION="1.0.9"
if [[ "$ARCH" == "x86_64" ]]; then
ARCH="64bit"
else
ARCH="ARM"
fi
cd /tmp
curl -LsS https://github.com/muquit/mailsend-go/releases/download/v${MAILSEND_VERSION}/mailsend-go_${MAILSEND_VERSION}_linux-${ARCH}.tar.gz | tar xzfv -
chmod +x /tmp/mailsend-go-dir/mailsend-go
}
install_mailsend

40
integration-tests/test.bats Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env bats
FROM=$1
TO=$2
if [ -z "$FROM" ]; then
FROM="demo@example.org"
fi
if [ -z "$TO" ]; then
TO="test@gmail.com"
fi
# Wait for postfix to startup
echo "Waiting for startup..."
wait-for-service -q tcp://postfix_test_587:587
SMTP_DATA="-smtp postfix_test_587 -port 587"
@test "Get server info" {
mailsend -info $SMTP_DATA
}
@test "Send a simple mail" {
mailsend \
-sub "Test email 1" $SMTP_DATA \
-from "$FROM" -to "$TO" \
body \
-msg "Hello world!\nThis is a simple test message!"
}
@test "Send mail with attachment" {
mailsend \
-sub "Test with attachment" $SMTP_DATA \
-from "$FROM" -to "$TO" \
body \
-msg "Hi!\nThis is an example of an attachment." \
attach \
-file "/usr/local/bin/mailsend"
}

View file

@ -1,13 +0,0 @@
$ModLoad immark.so # provides --MARK-- message capability
$ModLoad imuxsock.so # provides support for local system logging (e.g. via logger command)
# default permissions for all log files.
$FileOwner root
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
#*.info /dev/stdout
#mail.* /dev/stdout
mail.info /dev/stdout

239
run.sh
View file

@ -1,239 +0,0 @@
#!/bin/sh
. /commons.sh
echo -e "******************************"
echo -e "**** POSTFIX STARTING UP *****"
echo -e "******************************"
# Check if we need to configure the container timezone
if [ ! -z "$TZ" ]; then
TZ_FILE="/usr/share/zoneinfo/$TZ"
if [ -f "$TZ_FILE" ]; then
echo -e "$notice Setting container timezone to: ${emphasis}$TZ${reset}"
ln -snf "$TZ_FILE" /etc/localtime
echo "$TZ" > /etc/timezone
else
echo -e "$warn Cannot set timezone to: ${emphasis}$TZ${reset} -- this timezone does not exist."
fi
else
echo -e "$info Not setting any timezone for the container"
fi
# Make and reown postfix folders
mkdir -p /var/spool/postfix/ && mkdir -p /var/spool/postfix/pid
chown root: /var/spool/postfix/
chown root: /var/spool/postfix/pid
# Disable SMTPUTF8, because libraries (ICU) are missing in alpine
postconf -e smtputf8_enable=no
# Update aliases database. It's not used, but postfix complains if the .db file is missing
postalias /etc/postfix/aliases
# Disable local mail delivery
postconf -e mydestination=
# Don't relay for any domains
postconf -e relay_domains=
# Increase the allowed header size, the default (102400) is quite smallish
postconf -e "header_size_limit=4096000"
if [ ! -z "$MESSAGE_SIZE_LIMIT" ]; then
echo -e "$notice Restricting message_size_limit to: ${emphasis}$MESSAGE_SIZE_LIMIT bytes${reset}"
postconf -e "message_size_limit=$MESSAGE_SIZE_LIMIT"
else
# As this is a server-based service, allow any message size -- we hope the
# sender knows what he is doing.
echo -e "$info Using ${emphasis}unlimited${reset} message size."
postconf -e "message_size_limit=0"
fi
# Reject invalid HELOs
postconf -e smtpd_delay_reject=yes
postconf -e smtpd_helo_required=yes
postconf -e "smtpd_helo_restrictions=permit_mynetworks,reject_invalid_helo_hostname,permit"
postconf -e "smtpd_sender_restrictions=permit_mynetworks"
# Set up host name
if [ ! -z "$HOSTNAME" ]; then
echo -e "$notice Setting myhostname: ${emphasis}$HOSTNAME${reset}"
postconf -e myhostname="$HOSTNAME"
else
postconf -# myhostname
fi
if [ -z "$RELAYHOST_TLS_LEVEL" ]; then
echo -e "$info Setting smtp_tls_security_level: ${emphasis}may${reset}"
postconf -e "smtp_tls_security_level=may"
else
echo -e "$notice Setting smtp_tls_security_level: ${emphasis}$RELAYHOST_TLS_LEVEL${reset}"
postconf -e "smtp_tls_security_level=$RELAYHOST_TLS_LEVEL"
fi
# Set up a relay host, if needed
if [ ! -z "$RELAYHOST" ]; then
echo -en "$notice Forwarding all emails to ${emphasis}$RELAYHOST${reset}"
postconf -e "relayhost=$RELAYHOST"
# Alternately, this could be a folder, like this:
# smtp_tls_CApath
postconf -e "smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt"
if [ -n "$RELAYHOST_USERNAME" ] && [ -n "$RELAYHOST_PASSWORD" ]; then
echo -e " using username ${emphasis}$RELAYHOST_USERNAME${reset} and password ${emphasis}(redacted)${reset}."
echo "$RELAYHOST $RELAYHOST_USERNAME:$RELAYHOST_PASSWORD" >> /etc/postfix/sasl_passwd
postmap hash:/etc/postfix/sasl_passwd
postconf -e "smtp_sasl_auth_enable=yes"
postconf -e "smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd"
postconf -e "smtp_sasl_security_options=noanonymous"
postconf -e "smtp_sasl_tls_security_options=noanonymous"
else
echo -e " without any authentication. ${emphasis}Make sure your server is configured to accept emails coming from this IP.${reset}"
fi
else
echo -e "$notice Will try to deliver emails directly to the final server. ${emphasis}Make sure your DNS is setup properly!${reset}"
postconf -# relayhost
postconf -# smtp_sasl_auth_enable
postconf -# smtp_sasl_password_maps
postconf -# smtp_sasl_security_options
fi
if [ ! -z "$MYNETWORKS" ]; then
echo -e "$notice Using custom allowed networks: ${emphasis}$MYNETWORKS${reset}"
else
echo -e "$info Using default private network list for trusted networks."
MYNETWORKS="127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
fi
postconf -e "mynetworks=$MYNETWORKS"
if [ ! -z "$INBOUND_DEBUGGING" ]; then
echo -e "$notice Enabling additional debbuging for: ${emphasis}$MYNETWORKS${reset}"
postconf -e "debug_peer_list=$MYNETWORKS"
sed -i -E 's/^[ \t]*#?[ \t]*LogWhy[ \t]*.+$/LogWhy yes/' /etc/opendkim/opendkim.conf
if ! egrep -q '^LogWhy' /etc/opendkim/opendkim.conf; then
echo >> /etc/opendkim/opendkim.conf
echo "LogWhy yes" >> /etc/opendkim/opendkim.conf
fi
else
sed -i -E 's/^[ \t]*#?[ \t]*LogWhy[ \t]*.+$/LogWhy no/' /etc/opendkim/opendkim.conf
if ! egrep -q '^LogWhy' /etc/opendkim/opendkim.conf; then
echo >> /etc/opendkim/opendkim.conf
echo "LogWhy no" >> /etc/opendkim/opendkim.conf
fi
fi
if [ ! -z "$ALLOWED_SENDER_DOMAINS" ]; then
echo -en "$info Setting up allowed SENDER domains:"
allowed_senders=/etc/postfix/allowed_senders
rm -f $allowed_senders $allowed_senders.db > /dev/null
touch $allowed_senders
for i in $ALLOWED_SENDER_DOMAINS; do
echo -ne " ${emphasis}$i${reset}"
echo -e "$i\tOK" >> $allowed_senders
done
echo
postmap $allowed_senders
postconf -e "smtpd_restriction_classes=allowed_domains_only"
postconf -e "allowed_domains_only=permit_mynetworks, reject_non_fqdn_sender reject"
postconf -e "smtpd_recipient_restrictions=reject_non_fqdn_recipient, reject_unknown_recipient_domain, check_sender_access hash:$allowed_senders, reject"
# Since we are behind closed doors, let's just permit all relays.
postconf -e "smtpd_relay_restrictions=permit"
elif [ -z "$ALLOW_EMPTY_SENDER_DOMAINS" ]; then
echo -e "ERROR: You need to specify ALLOWED_SENDER_DOMAINS otherwise Postfix will not run!"
exit 1
fi
if [ ! -z "$MASQUERADED_DOMAINS" ]; then
echo -e "$notice Setting up address masquerading: ${emphasis}$MASQUERADED_DOMAINS${reset}"
postconf -e "masquerade_domains = $MASQUERADED_DOMAINS"
postconf -e "local_header_rewrite_clients = static:all"
fi
if [ ! -z "$SMTP_HEADER_CHECKS" ]; then
if [ "$SMTP_HEADER_CHECKS" == "1" ]; then
echo -e "$info Using default file for SMTP header checks"
SMTP_HEADER_CHECKS="regexp:/etc/postfix/smtp_header_checks"
fi
FORMAT=$(echo "$SMTP_HEADER_CHECKS" | cut -d: -f1)
FILE=$(echo "$SMTP_HEADER_CHECKS" | cut -d: -f2-)
if [ "$FORMAT" == "$FILE" ]; then
echo -e "$warn No Postfix format defined for file ${emphasis}SMTP_HEADER_CHECKS${reset}. Using default ${emphasis}regexp${reset}. To avoid this message, set format explicitly, e.g. ${emphasis}SMTP_HEADER_CHECKS=regexp:$SMTP_HEADER_CHECKS${reset}."
FORMAT="regexp"
fi
if [ -f "$FILE" ]; then
echo -e "$notice Setting up ${emphasis}smtp_header_checks${reset} to ${emphasis}$FORMAT:$FILE${reset}"
postconf -e "smtp_header_checks=$FORMAT:$FILE"
else
echo -e "$error File ${emphasis}$FILE${reset} cannot be found. Please make sure your SMTP_HEADER_CHECKS variable points to the right file. Startup aborted."
exit 2
fi
fi
DKIM_ENABLED=
if [ -d /etc/opendkim/keys ] && [ ! -z "$(find /etc/opendkim/keys -type f ! -name .)" ]; then
DKIM_ENABLED=", ${emphasis}opendkim${reset}"
echo -e "$notice Configuring OpenDKIM."
mkdir -p /var/run/opendkim
chown -R opendkim:opendkim /var/run/opendkim
dkim_socket=$(cat /etc/opendkim/opendkim.conf | egrep ^Socket | awk '{ print $2 }')
if [ $(echo "$dkim_socket" | cut -d: -f1) == "inet" ]; then
dkim_socket=$(echo "$dkim_socket" | cut -d: -f2)
dkim_socket="inet:$(echo "$dkim_socket" | cut -d@ -f2):$(echo "$dkim_socket" | cut -d@ -f1)"
fi
echo -e " ...using socket $dkim_socket"
postconf -e "milter_protocol=6"
postconf -e "milter_default_action=accept"
postconf -e "smtpd_milters=$dkim_socket"
postconf -e "non_smtpd_milters=$dkim_socket"
echo > /etc/opendkim/TrustedHosts
echo > /etc/opendkim/KeyTable
echo > /etc/opendkim/SigningTable
# Since it's an internal service anyways, it's safe
# to assume that *all* hosts are trusted.
echo "0.0.0.0/0" > /etc/opendkim/TrustedHosts
if [ ! -z "$ALLOWED_SENDER_DOMAINS" ]; then
for i in $ALLOWED_SENDER_DOMAINS; do
private_key=/etc/opendkim/keys/$i.private
if [ -f $private_key ]; then
echo -e " ...for domain ${emphasis}$i${reset}"
echo "mail._domainkey.$i $i:mail:$private_key" >> /etc/opendkim/KeyTable
echo "*@$i mail._domainkey.$i" >> /etc/opendkim/SigningTable
else
echo " ...$warn skipping for domain ${emphasis}$i${reset}. File $private_key not found!"
fi
done
fi
else
echo -e "$info No DKIM keys found, will not use DKIM."
postconf -# smtpd_milters
postconf -# non_smtpd_milters
fi
# Use 587 (submission)
sed -i -r -e 's/^#submission/submission/' /etc/postfix/master.cf
if [ -d /docker-init.db/ ]; then
echo -e "$notice Executing any found custom scripts..."
for f in /docker-init.db/*; do
case "$f" in
*.sh) chmod +x "$f"; echo -e "\trunning ${emphasis}$f${reset}"; . "$f" ;;
*) echo "$0: ignoring $f" ;;
esac
done
fi
echo -e "$notice Starting: ${emphasis}rsyslog${reset}, ${emphasis}postfix${reset}$DKIM_ENABLED"
exec supervisord -c /etc/supervisord.conf

268
scripts/common-run.sh Normal file
View file

@ -0,0 +1,268 @@
#!/bin/sh
announce_startup() {
echo -e "******************************"
echo -e "**** POSTFIX STARTING UP *****"
echo -e "******************************"
}
setup_timezone() {
if [ ! -z "$TZ" ]; then
TZ_FILE="/usr/share/zoneinfo/$TZ"
if [ -f "$TZ_FILE" ]; then
echo -e "$notice Setting container timezone to: ${emphasis}$TZ${reset}"
ln -snf "$TZ_FILE" /etc/localtime
echo "$TZ" > /etc/timezone
else
echo -e "$warn Cannot set timezone to: ${emphasis}$TZ${reset} -- this timezone does not exist."
fi
else
echo -e "$info Not setting any timezone for the container"
fi
}
reown_folders() {
mkdir -p /var/spool/postfix/ && mkdir -p /var/spool/postfix/pid
chown root: /var/spool/postfix/
chown root: /var/spool/postfix/pid
}
postfix_disable_utf8() {
postconf -e smtputf8_enable=no
}
postfix_create_aliases() {
postalias /etc/postfix/aliases
}
postfix_disable_local_mail_delivery() {
postconf -e mydestination=
}
postfix_disable_domain_relays() {
postconf -e relay_domains=
}
postfix_increase_header_size_limit() {
postconf -e "header_size_limit=4096000"
}
postfix_restrict_message_size() {
if [ ! -z "$MESSAGE_SIZE_LIMIT" ]; then
echo -e "$notice Restricting message_size_limit to: ${emphasis}$MESSAGE_SIZE_LIMIT bytes${reset}"
postconf -e "message_size_limit=$MESSAGE_SIZE_LIMIT"
else
# As this is a server-based service, allow any message size -- we hope the
# sender knows what he is doing.
echo -e "$info Using ${emphasis}unlimited${reset} message size."
postconf -e "message_size_limit=0"
fi
}
postfix_reject_invalid_helos() {
postconf -e smtpd_delay_reject=yes
postconf -e smtpd_helo_required=yes
postconf -e "smtpd_helo_restrictions=permit_mynetworks,reject_invalid_helo_hostname,permit"
postconf -e "smtpd_sender_restrictions=permit_mynetworks"
}
postfix_set_hostname() {
if [ ! -z "$HOSTNAME" ]; then
echo -e "$notice Setting myhostname: ${emphasis}$HOSTNAME${reset}"
postconf -e myhostname="$HOSTNAME"
else
postconf -# myhostname
fi
}
postfix_set_relay_tls_level() {
if [ -z "$RELAYHOST_TLS_LEVEL" ]; then
echo -e "$info Setting smtp_tls_security_level: ${emphasis}may${reset}"
postconf -e "smtp_tls_security_level=may"
else
echo -e "$notice Setting smtp_tls_security_level: ${emphasis}$RELAYHOST_TLS_LEVEL${reset}"
postconf -e "smtp_tls_security_level=$RELAYHOST_TLS_LEVEL"
fi
}
postfix_setup_relayhost() {
if [ ! -z "$RELAYHOST" ]; then
echo -en "$notice Forwarding all emails to ${emphasis}$RELAYHOST${reset}"
postconf -e "relayhost=$RELAYHOST"
# Alternately, this could be a folder, like this:
# smtp_tls_CApath
postconf -e "smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt"
if [ -n "$RELAYHOST_USERNAME" ] && [ -n "$RELAYHOST_PASSWORD" ]; then
echo -e " using username ${emphasis}$RELAYHOST_USERNAME${reset} and password ${emphasis}(redacted)${reset}."
echo "$RELAYHOST $RELAYHOST_USERNAME:$RELAYHOST_PASSWORD" >> /etc/postfix/sasl_passwd
postmap hash:/etc/postfix/sasl_passwd
postconf -e "smtp_sasl_auth_enable=yes"
postconf -e "smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd"
postconf -e "smtp_sasl_security_options=noanonymous"
postconf -e "smtp_sasl_tls_security_options=noanonymous"
else
echo -e " without any authentication. ${emphasis}Make sure your server is configured to accept emails coming from this IP.${reset}"
fi
else
echo -e "$notice Will try to deliver emails directly to the final server. ${emphasis}Make sure your DNS is setup properly!${reset}"
postconf -# relayhost
postconf -# smtp_sasl_auth_enable
postconf -# smtp_sasl_password_maps
postconf -# smtp_sasl_security_options
fi
}
postfix_setup_networks() {
if [ ! -z "$MYNETWORKS" ]; then
echo -e "$notice Using custom allowed networks: ${emphasis}$MYNETWORKS${reset}"
else
echo -e "$info Using default private network list for trusted networks."
MYNETWORKS="127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
fi
postconf -e "mynetworks=$MYNETWORKS"
}
postfix_setup_debugging() {
if [ ! -z "$INBOUND_DEBUGGING" ]; then
echo -e "$notice Enabling additional debbuging for: ${emphasis}$MYNETWORKS${reset}, as INBOUND_DEBUGGING=''${INBOUND_DEBUGGING}''"
postconf -e "debug_peer_list=$MYNETWORKS"
sed -i -E 's/^[ \t]*#?[ \t]*LogWhy[ \t]*.+$/LogWhy yes/' /etc/opendkim/opendkim.conf
if ! egrep -q '^LogWhy' /etc/opendkim/opendkim.conf; then
echo >> /etc/opendkim/opendkim.conf
echo "LogWhy yes" >> /etc/opendkim/opendkim.conf
fi
else
echo -e "$info Debugging is disabled.${reset}"
sed -i -E 's/^[ \t]*#?[ \t]*LogWhy[ \t]*.+$/LogWhy no/' /etc/opendkim/opendkim.conf
if ! egrep -q '^LogWhy' /etc/opendkim/opendkim.conf; then
echo >> /etc/opendkim/opendkim.conf
echo "LogWhy no" >> /etc/opendkim/opendkim.conf
fi
fi
}
postfix_setup_sender_domains() {
if [ ! -z "$ALLOWED_SENDER_DOMAINS" ]; then
echo -en "$info Setting up allowed SENDER domains:"
allowed_senders=/etc/postfix/allowed_senders
rm -f $allowed_senders $allowed_senders.db > /dev/null
touch $allowed_senders
for i in $ALLOWED_SENDER_DOMAINS; do
echo -ne " ${emphasis}$i${reset}"
echo -e "$i\tOK" >> $allowed_senders
done
echo
postmap $allowed_senders
postconf -e "smtpd_restriction_classes=allowed_domains_only"
postconf -e "allowed_domains_only=permit_mynetworks, reject_non_fqdn_sender reject"
postconf -e "smtpd_recipient_restrictions=reject_non_fqdn_recipient, reject_unknown_recipient_domain, check_sender_access hash:$allowed_senders, reject"
# Since we are behind closed doors, let's just permit all relays.
postconf -e "smtpd_relay_restrictions=permit"
elif [ -z "$ALLOW_EMPTY_SENDER_DOMAINS" ]; then
echo -e "ERROR: You need to specify ALLOWED_SENDER_DOMAINS otherwise Postfix will not run!"
exit 1
fi
}
postfix_setup_masquarading() {
if [ ! -z "$MASQUERADED_DOMAINS" ]; then
echo -e "$notice Setting up address masquerading: ${emphasis}$MASQUERADED_DOMAINS${reset}"
postconf -e "masquerade_domains = $MASQUERADED_DOMAINS"
postconf -e "local_header_rewrite_clients = static:all"
fi
}
postfix_setup_header_checks() {
if [ ! -z "$SMTP_HEADER_CHECKS" ]; then
if [ "$SMTP_HEADER_CHECKS" == "1" ]; then
echo -e "$info Using default file for SMTP header checks"
SMTP_HEADER_CHECKS="regexp:/etc/postfix/smtp_header_checks"
fi
FORMAT=$(echo "$SMTP_HEADER_CHECKS" | cut -d: -f1)
FILE=$(echo "$SMTP_HEADER_CHECKS" | cut -d: -f2-)
if [ "$FORMAT" == "$FILE" ]; then
echo -e "$warn No Postfix format defined for file ${emphasis}SMTP_HEADER_CHECKS${reset}. Using default ${emphasis}regexp${reset}. To avoid this message, set format explicitly, e.g. ${emphasis}SMTP_HEADER_CHECKS=regexp:$SMTP_HEADER_CHECKS${reset}."
FORMAT="regexp"
fi
if [ -f "$FILE" ]; then
echo -e "$notice Setting up ${emphasis}smtp_header_checks${reset} to ${emphasis}$FORMAT:$FILE${reset}"
postconf -e "smtp_header_checks=$FORMAT:$FILE"
else
echo -e "$error File ${emphasis}$FILE${reset} cannot be found. Please make sure your SMTP_HEADER_CHECKS variable points to the right file. Startup aborted."
exit 2
fi
fi
}
postfix_setup_dkim() {
local DKIM_ENABLED=
local domain_dkim_selector="mail"
if [ -d /etc/opendkim/keys ] && [ ! -z "$(find /etc/opendkim/keys -type f ! -name .)" ]; then
DKIM_ENABLED=", ${emphasis}opendkim${reset}"
echo -e "$notice Configuring OpenDKIM."
mkdir -p /var/run/opendkim
chown -R opendkim:opendkim /var/run/opendkim
dkim_socket=$(cat /etc/opendkim/opendkim.conf | egrep ^Socket | awk '{ print $2 }')
if [ $(echo "$dkim_socket" | cut -d: -f1) == "inet" ]; then
dkim_socket=$(echo "$dkim_socket" | cut -d: -f2)
dkim_socket="inet:$(echo "$dkim_socket" | cut -d@ -f2):$(echo "$dkim_socket" | cut -d@ -f1)"
fi
echo -e " ...using socket $dkim_socket"
postconf -e "milter_protocol=6"
postconf -e "milter_default_action=accept"
postconf -e "smtpd_milters=$dkim_socket"
postconf -e "non_smtpd_milters=$dkim_socket"
echo > /etc/opendkim/TrustedHosts
echo > /etc/opendkim/KeyTable
echo > /etc/opendkim/SigningTable
# Since it's an internal service anyways, it's safe
# to assume that *all* hosts are trusted.
echo "0.0.0.0/0" > /etc/opendkim/TrustedHosts
if [ ! -z "$ALLOWED_SENDER_DOMAINS" ]; then
for i in $ALLOWED_SENDER_DOMAINS; do
private_key=/etc/opendkim/keys/$i.private
if [ -f $private_key ]; then
domain_dkim_selector="$(get_dkim_selector "$i")"
echo -e " ...for domain ${emphasis}$i${reset} (selector: ${emphasis}${domain_dkim_selector}${reset})"
echo "${domain_dkim_selector}._domainkey.$i $i:mail:$private_key" >> /etc/opendkim/KeyTable
echo "*@$i ${domain_dkim_selector}._domainkey.$i" >> /etc/opendkim/SigningTable
else
echo " ...$warn skipping for domain ${emphasis}$i${reset}. File $private_key not found!"
fi
done
fi
else
echo -e "$info No DKIM keys found, will not use DKIM."
postconf -# smtpd_milters
postconf -# non_smtpd_milters
fi
}
postfix_open_submission_port() {
# Use 587 (submission)
sed -i -r -e 's/^#submission/submission/' /etc/postfix/master.cf
}
execute_post_init_scripts() {
if [ -d /docker-init.db/ ]; then
echo -e "$notice Executing any found custom scripts..."
for f in /docker-init.db/*; do
case "$f" in
*.sh) chmod +x "$f"; echo -e "\trunning ${emphasis}$f${reset}"; . "$f" ;;
*) echo "$0: ignoring $f" ;;
esac
done
fi
}

View file

@ -44,4 +44,34 @@ fi
info="${green}INFO:${reset}"
notice="${yellow}NOTE:${reset}"
warn="${orange}WARN:${reset}"
error="${red}ERROR:${reset}"
error="${red}ERROR:${reset}"
# Return a DKIM selector from DKIM_SELECTOR environment variable.
# See README.md for details.
get_dkim_selector() {
if [ -z "${DKIM_SELECTOR}" ]; then
echo "mail"
return
fi
local domain="$1"
local old="$IFS"
local no_domain_selector="mail"
local IFS=","
for part in ${DKIM_SELECTOR}; do
if contains "$part" "="; then
k="$(echo "$part" | cut -f1 -d=)"
v="$(echo "$part" | cut -f2 -d=)"
if [ "$k" == "$domain" ]; then
echo "$v"
IFS="${old}"
return
fi
else
no_domain_selector="$part"
fi
done
IFS="${old}"
echo "${no_domain_selector}"
}

30
scripts/run.sh Normal file
View file

@ -0,0 +1,30 @@
#!/bin/sh
set -e
. /common.sh
. /common-run.sh
announce_startup # Print startup banner
setup_timezone # Check if we need to configure the container timezone
reown_folders # Make and reown postfix folders
postfix_disable_utf8 # Disable SMTPUTF8, because libraries (ICU) are missing in alpine
postfix_create_aliases # Update aliases database. It's not used, but postfix complains if the .db file is missing
postfix_disable_local_mail_delivery # Disable local mail delivery
postfix_disable_domain_relays # Don't relay for any domains
postfix_increase_header_size_limit # Increase the allowed header size, the default (102400) is quite smallish
postfix_restrict_message_size # Restrict the size of messages (or set them to unlimited)
postfix_reject_invalid_helos # Reject invalid HELOs
postfix_set_hostname # Set up host name
postfix_set_relay_tls_level # Set TLS level security for relays
postfix_setup_relayhost # Setup a relay host, if defined
postfix_setup_networks # Set MYNETWORKS
postfix_setup_debugging # Enable debugging, if defined
postfix_setup_sender_domains # Configure allowed sender domains
postfix_setup_masquarading # Setup masquaraded domains
postfix_setup_header_checks # Enable SMTP header checks, if defined
postfix_setup_dkim # Configure DKIM, if enabled
postfix_open_submission_port # Enable the submission port
execute_post_init_scripts # Execute any scripts found in /docker-init.db/
echo -e "$notice Starting: ${emphasis}rsyslog${reset}, ${emphasis}postfix${reset}$DKIM_ENABLED"
exec supervisord -c /etc/supervisord.conf

36
test.sh
View file

@ -1,36 +0,0 @@
#!/bin/sh
docker build . -t boky/postfix
docker-compose up -d
FROM=$1
TO=$2
# Wait for postfix to startup
echo "Waiting for startup..."
while ! docker ps | fgrep postfix_test_587 | grep -q healthy; do
sleep 1
done
cat <<EOF | nc -C localhost 1587
HELO test
MAIL FROM:$FROM
RCPT TO:$TO
DATA
Subject: Postfix message test
From: $FROM
To: $TO
Date: $(date)
Content-Type: text/plain
This is a simple text of message sending using boky/postfix.
.
QUIT
EOF
# Wait for email to be delivered
echo "Waiting to shutdown..."
sleep 5
# Shut down tests
docker-compose down

3
unit-tests.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
cd unit-tests
docker-compose up --build --abort-on-container-exit --exit-code-from tests

9
unit-tests/Dockerfile Normal file
View file

@ -0,0 +1,9 @@
FROM alpine:latest
RUN apk add --no-cache bash bats
WORKDIR /code
ENTRYPOINT ["/usr/bin/bats"]
CMD ["-v"]

View file

@ -0,0 +1,10 @@
version: '3.7'
services:
tests:
image: "boky/postfix-unit-test"
restart: "no"
volumes:
- "..:/code"
build:
context: .
command: "/code/unit-tests/"

View file

@ -0,0 +1,56 @@
#!/usr/bin/env bats
load /code/scripts/common.sh
@test "check if 'mail' when DKIM_SELECTOR is not defined" {
result="$(get_dkim_selector)"
[ "$result" == "mail" ]
}
@test "check if 'xxx' when DKIM_SELECTOR is defined" {
local DKIM_SELECTOR="xxx"
result="$(get_dkim_selector)"
[ "$result" == "xxx" ]
}
@test "check if 'xxx' without domain when DKIM_SELECTOR=xxx,example.org=yyy,example.com=zzz" {
local DKIM_SELECTOR="xxx,example.org=yyy,example.com=zzz"
result="$(get_dkim_selector example.org)"
echo "result=$result"
[ "$result" == "yyy" ]
}
@test "check if 'yyy' when domain is example.org DKIM_SELECTOR=xxx,example.org=yyy,example.com=zzz" {
local DKIM_SELECTOR="xxx,example.org=yyy,example.com=zzz"
result="$(get_dkim_selector example.org)"
echo "result=$result"
[ "$result" == "yyy" ]
}
@test "check if 'zzz' when domain is example.org DKIM_SELECTOR=xxx,example.org=yyy,example.com=zzz" {
local DKIM_SELECTOR="xxx,example.org=yyy,example.com=zzz"
result="$(get_dkim_selector example.com)"
echo "result=$result"
[ "$result" == "zzz" ]
}
@test "check if 'aaa' when domain is example.net DKIM_SELECTOR=xxx,example.org=yyy,example.com=zzz,bbb,aaa" {
local DKIM_SELECTOR="xxx,example.org=yyy,example.com=zzz,bbb,aaa"
result="$(get_dkim_selector example.net)"
echo "result=$result"
[ "$result" == "aaa" ]
}
@test "check if 'bbb' when domain is example.net DKIM_SELECTOR=example.com=bbb" {
local DKIM_SELECTOR="example.com=bbb"
result="$(get_dkim_selector example.com)"
echo "result=$result"
[ "$result" == "bbb" ]
}
@test "check if 'mail' when domain is example.net DKIM_SELECTOR=example.com=bbb" {
local DKIM_SELECTOR="example.com=bbb"
result="$(get_dkim_selector example.net)"
echo "result=$result"
[ "$result" == "mail" ]
}