diff --git a/Dockerfile.apache b/Dockerfile.apache index 41b5b0b5..a92c97af 100644 --- a/Dockerfile.apache +++ b/Dockerfile.apache @@ -1,5 +1,6 @@ ARG INSTALL_CRON=1 ARG INSTALL_COMPOSER=1 +ARG INSTALL_DMA=1 ARG PHP_VERSION ARG GLOBAL_VERSION FROM thecodingmachine/php:${PHP_VERSION}-${GLOBAL_VERSION}-slim-apache diff --git a/Dockerfile.cli b/Dockerfile.cli index 5c8662dd..fd46a30f 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -1,5 +1,6 @@ ARG INSTALL_CRON=1 ARG INSTALL_COMPOSER=1 +ARG INSTALL_DMA=1 ARG PHP_VERSION ARG GLOBAL_VERSION FROM thecodingmachine/php:${PHP_VERSION}-${GLOBAL_VERSION}-slim-cli diff --git a/Dockerfile.fpm b/Dockerfile.fpm index 8621add5..c533bd7a 100644 --- a/Dockerfile.fpm +++ b/Dockerfile.fpm @@ -1,5 +1,6 @@ ARG INSTALL_CRON=1 ARG INSTALL_COMPOSER=1 +ARG INSTALL_DMA=1 ARG PHP_VERSION ARG GLOBAL_VERSION FROM thecodingmachine/php:${PHP_VERSION}-${GLOBAL_VERSION}-slim-fpm diff --git a/Dockerfile.slim.apache b/Dockerfile.slim.apache index 597488d6..819f10c1 100644 --- a/Dockerfile.slim.apache +++ b/Dockerfile.slim.apache @@ -293,6 +293,7 @@ ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini COPY utils/generate_cron.php /usr/local/bin/generate_cron.php +COPY utils/generate_dma.php /usr/local/bin/generate_dma.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php COPY utils/enable_apache_mods.php /usr/local/bin/enable_apache_mods.php @@ -386,3 +387,18 @@ ONBUILD RUN if [ -n "$NODE_VERSION" ]; then \ sudo apt-get update && \ sudo apt-get install -y --no-install-recommends yarn; \ fi; + +# |-------------------------------------------------------------------------- +# | DragonFly Mail Agent +# |-------------------------------------------------------------------------- +# | +# | Installs DragonFly Mail Agent, a sendmail-compatible MTA that can be used +# | to send email from PHP, either using direct delivery or through an SMTP +# | smarthost. +# | + +ONBUILD ARG INSTALL_DMA +ONBUILD RUN if [ -n "$INSTALL_DMA" ]; then \ + sudo apt-get update && \ + sudo -E apt-get install -y --no-install-recommends dma; \ + fi; diff --git a/Dockerfile.slim.cli b/Dockerfile.slim.cli index 40da3e38..a7ac397a 100644 --- a/Dockerfile.slim.cli +++ b/Dockerfile.slim.cli @@ -219,6 +219,7 @@ ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini COPY utils/generate_cron.php /usr/local/bin/generate_cron.php +COPY utils/generate_dma.php /usr/local/bin/generate_dma.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php COPY utils/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh @@ -291,3 +292,18 @@ ONBUILD RUN if [ -n "$NODE_VERSION" ]; then \ sudo apt-get update && \ sudo apt-get install -y --no-install-recommends yarn; \ fi; + +# |-------------------------------------------------------------------------- +# | DragonFly Mail Agent +# |-------------------------------------------------------------------------- +# | +# | Installs DragonFly Mail Agent, a sendmail-compatible MTA that can be used +# | to send email from PHP, either using direct delivery or through an SMTP +# | smarthost. +# | + +ONBUILD ARG INSTALL_DMA +ONBUILD RUN if [ -n "$INSTALL_DMA" ]; then \ + sudo apt-get update && \ + sudo -E apt-get install -y --no-install-recommends dma; \ + fi; diff --git a/Dockerfile.slim.fpm b/Dockerfile.slim.fpm index 8354060b..5946e926 100644 --- a/Dockerfile.slim.fpm +++ b/Dockerfile.slim.fpm @@ -232,6 +232,7 @@ ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini COPY utils/generate_cron.php /usr/local/bin/generate_cron.php +COPY utils/generate_dma.php /usr/local/bin/generate_dma.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php COPY utils/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh @@ -314,3 +315,18 @@ ONBUILD RUN if [ -n "$NODE_VERSION" ]; then \ sudo apt-get update && \ sudo apt-get install -y --no-install-recommends yarn; \ fi; + +# |-------------------------------------------------------------------------- +# | DragonFly Mail Agent +# |-------------------------------------------------------------------------- +# | +# | Installs DragonFly Mail Agent, a sendmail-compatible MTA that can be used +# | to send email from PHP, either using direct delivery or through an SMTP +# | smarthost. +# | + +ONBUILD ARG INSTALL_DMA +ONBUILD RUN if [ -n "$INSTALL_DMA" ]; then \ + sudo apt-get update && \ + sudo -E apt-get install -y --no-install-recommends dma; \ + fi; diff --git a/README.md b/README.md index b1e4400e..a2444a7f 100644 --- a/README.md +++ b/README.md @@ -404,6 +404,34 @@ ENV APACHE_RUN_USER=www-data \ ``` +## Sending email + +The `sendmail` binary is available through [DragonFly Mail Agent (DMA)](https://wiki.mageia.org/en/Dma_Dragonfly_Mail_Agent) to make the [`mail()`](https://www.php.net/manual/de/function.mail.php) function work. Without configuration, it sends email directly, using `noreply@example.org` as the sender by default - this won't work for various reasons (greylisting, spam blacklists, SPF record of example.org, ...), and email is quite complex to set up correctly with direct delivery. + +**Important**: To reliably send email, you thus should specify a smarthost which will be used as an SMTP relay - all you need is an account at any email provider that supports SMTP (ideally suited for mass/transactional mails, according to your usecase - e.g. Mailgun, Postmark, or a self-hosted [Postal](https://github.com/postalhq/postal) instance). Then, to configure DMA, you'll just have to set the following environment variables: + +```bash +# your sender address +DMA_FROM=noreply@your-domain.example.org +# your smarthost settings +DMA_CONF_SMARTHOST=smtp.example.org +DMA_AUTH_USERNAME=noreply +DMA_AUTH_PASSWORD=helloworld123 +# further DMA settings, according to the DMA man page, prefixed with DMA_CONF_ +# (see https://manpages.debian.org/unstable/dma/sendmail.8.en.html#dma.conf) +DMA_CONF_STARTTLS=1 +``` + +DMA is **installed by default in the fat images**. If you are using the "*slim*" images, you need to install it by passing +a single argument before the "FROM" clause in your Dockerfile: + +```Dockerfile +ARG INSTALL_DMA=1 +FROM thecodingmachine/php:7.4-v3-slim-apache +# The build triggers automatically the installation of DragonFly Mail Agent +``` + + ## Setting up CRON jobs You can set up CRON jobs using environment variables too. diff --git a/utils/Dockerfile.blueprint b/utils/Dockerfile.blueprint index 81cbcb08..50a25822 100644 --- a/utils/Dockerfile.blueprint +++ b/utils/Dockerfile.blueprint @@ -2,6 +2,7 @@ ARG INSTALL_CRON=1 ARG INSTALL_COMPOSER=1 +ARG INSTALL_DMA=1 ARG PHP_VERSION ARG GLOBAL_VERSION FROM thecodingmachine/php:${PHP_VERSION}-${GLOBAL_VERSION}-slim-{{ $variant }} diff --git a/utils/Dockerfile.slim.blueprint b/utils/Dockerfile.slim.blueprint index 3d43ca25..f32b617f 100644 --- a/utils/Dockerfile.slim.blueprint +++ b/utils/Dockerfile.slim.blueprint @@ -311,6 +311,7 @@ ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini COPY utils/generate_cron.php /usr/local/bin/generate_cron.php +COPY utils/generate_dma.php /usr/local/bin/generate_dma.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php {{if eq $variant "apache" }} COPY utils/enable_apache_mods.php /usr/local/bin/enable_apache_mods.php @@ -418,3 +419,18 @@ ONBUILD RUN if [ -n "$NODE_VERSION" ]; then \ sudo apt-get update && \ sudo apt-get install -y --no-install-recommends yarn; \ fi; + +# |-------------------------------------------------------------------------- +# | DragonFly Mail Agent +# |-------------------------------------------------------------------------- +# | +# | Installs DragonFly Mail Agent, a sendmail-compatible MTA that can be used +# | to send email from PHP, either using direct delivery or through an SMTP +# | smarthost. +# | + +ONBUILD ARG INSTALL_DMA +ONBUILD RUN if [ -n "$INSTALL_DMA" ]; then \ + sudo apt-get update && \ + sudo -E apt-get install -y --no-install-recommends dma; \ + fi; diff --git a/utils/README.blueprint.md b/utils/README.blueprint.md index 9b84de65..f9e0f3aa 100644 --- a/utils/README.blueprint.md +++ b/utils/README.blueprint.md @@ -359,6 +359,34 @@ ENV APACHE_RUN_USER=www-data \ ``` +## Sending email + +The `sendmail` binary is available through [DragonFly Mail Agent (DMA)](https://wiki.mageia.org/en/Dma_Dragonfly_Mail_Agent) to make the [`mail()`](https://www.php.net/manual/de/function.mail.php) function work. Without configuration, it sends email directly, using `noreply@example.org` as the sender by default - this won't work for various reasons (greylisting, spam blacklists, SPF record of example.org, ...), and email is quite complex to set up correctly with direct delivery. + +**Important**: To reliably send email, you thus should specify a smarthost which will be used as an SMTP relay - all you need is an account at any email provider that supports SMTP (ideally suited for mass/transactional mails, according to your usecase - e.g. Mailgun, Postmark, or a self-hosted [Postal](https://github.com/postalhq/postal) instance). Then, to configure DMA, you'll just have to set the following environment variables: + +```bash +# your sender address +DMA_FROM=noreply@your-domain.example.org +# your smarthost settings +DMA_CONF_SMARTHOST=smtp.example.org +DMA_AUTH_USERNAME=noreply +DMA_AUTH_PASSWORD=helloworld123 +# further DMA settings, according to the DMA man page, prefixed with DMA_CONF_ +# (see https://manpages.debian.org/unstable/dma/sendmail.8.en.html#dma.conf) +DMA_CONF_STARTTLS=1 +``` + +DMA is **installed by default in the fat images**. If you are using the "*slim*" images, you need to install it by passing +a single argument before the "FROM" clause in your Dockerfile: + +```Dockerfile +ARG INSTALL_DMA=1 +FROM thecodingmachine/php:{{ $image.php_version }}-v3-slim-apache +# The build triggers automatically the installation of DragonFly Mail Agent +``` + + ## Setting up CRON jobs You can set up CRON jobs using environment variables too. diff --git a/utils/docker-entrypoint-as-root.sh b/utils/docker-entrypoint-as-root.sh index f8c6c9ea..287d4ac4 100755 --- a/utils/docker-entrypoint-as-root.sh +++ b/utils/docker-entrypoint-as-root.sh @@ -116,6 +116,26 @@ fi unset DOCKER_FOR_MAC_REMOTE_HOST unset REMOTE_HOST_FOUND +if [ -e /usr/sbin/dma ]; then + # set sendmail path for PHP + if [ "$DMA_FROM" = "" ]; then + DMA_FROM=noreply@example.org + fi + export PHP_INI_SENDMAIL_PATH="/usr/sbin/sendmail -t -i -f'$DMA_FROM'" + + # generate DMA config based on DMA_CONF_... environment variables + php /usr/local/bin/generate_dma.php > /etc/dma/dma.conf + + # generate DMA authentication file based on DMA_AUTH_... environment variables + if [ -n "$DMA_AUTH_USERNAME" ] && [ -n "$DMA_AUTH_PASSWORD" ]; then + if [ -z "$DMA_CONF_SMARTHOST" ]; then + echo "DMA_AUTH_USERNAME and DMA_AUTH_PASSWORD are set, but DMA_CONF_SMARTHOST is empty - not attempting authentication" >&2 + else + echo "$DMA_AUTH_USERNAME|$DMA_CONF_SMARTHOST:$DMA_AUTH_PASSWORD" > /etc/dma/auth.conf + fi + fi +fi + php /usr/local/bin/generate_conf.php > /etc/php/${PHP_VERSION}/mods-available/generated_conf.ini php /usr/local/bin/setup_extensions.php | sudo bash diff --git a/utils/generate_dma.php b/utils/generate_dma.php new file mode 100644 index 00000000..cc85c295 --- /dev/null +++ b/utils/generate_dma.php @@ -0,0 +1,26 @@ + $value) { + if (strpos($key, 'DMA_') === 0) { + $found = true; + } + if (strpos($key, 'DMA_CONF_') === 0) { + $suffix = substr($key, 9); + + echo $suffix." ".$value."\n"; + } +} + +if (($found === true) && !file_exists('/usr/sbin/dma')) { + // Let's check DMA is installed (it could be not installed is we are using the slim version...) + error_log('DMA is not available in this image. If you are using the thecodingmachine/php "slim" variant, do not forget to add "ARG INSTALL_DMA=1" in your Dockerfile. Check the documentation for more details.'); + exit(1); +}