I'm trying to get my PHP container to send emails.
Both here and here it is mentioned that the configuration setting should be in the php.ini
file.
However, when I put a phpinfo()
somewhere in my code, this is what I see:
Configuration File (php.ini) Path /usr/local/etc/php
Loaded Configuration File (none)
Scan this dir for additional .ini files /usr/local/etc/php/conf.d
Additional .ini files parsed /usr/local/etc/php/conf.d/docker-fpm.ini, /usr/local/etc/php/conf.d/docker-php-ext-exif.ini, /usr/local/etc/php/conf.d/docker-php-ext-gd.ini, /usr/local/etc/php/conf.d/docker-php-ext-gettext.ini, /usr/local/etc/php/conf.d/docker-php-ext-gmp.ini, /usr/local/etc/php/conf.d/docker-php-ext-intl.ini, /usr/local/etc/php/conf.d/docker-php-ext-memcached.ini, /usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini, /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini, /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini, /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini, /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini, /usr/local/etc/php/conf.d/docker-php-ext-yaml.ini, /usr/local/etc/php/conf.d/docker-php-ext-zip.ini, /usr/local/etc/php/conf.d/newrelic.ini
I'm running my PHP project inside a Docker container.
Here's the Dockerfile
(a bit simplified):
FROM composer:2 as vendor
COPY public/composer.json composer.json
RUN composer clearcache
RUN composer install \
--ignore-platform-reqs \
--no-interaction \
--no-plugins \
--no-scripts \
--prefer-dist && \
composer dumpautoload --optimize
FROM php:8.3-fpm-alpine3.19
EXPOSE 80
RUN pecl install xdebug && \
docker-php-ext-enable xdebug
COPY config/docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
COPY public /var/www/repo/public
# install dependencies
COPY --from=vendor /app/vendor/ /var/www/repo/public/vendor/
RUN chown -R www-data /var/www/repo/public/vendor/
WORKDIR /var/www
CMD ["/var/www/repo/scripts/start"]
This is all fine, the container builds and the app runs fine (apart from the fact that it's not sending emails):
function _mail(
string $to,
string $subject,
string $message,
string $headers = '',
string $params = ''
): void {
if (!mail($to, $subject, $message, $headers, $params)) {
throw new Exception('Something went wrong when sending email');
}
}
When I run this, it always end up inside the if
and throwing that exception, and I can't figure out why. The fact that PHP's mail()
function is notoriously hard to debug doesn't help either (I've already read many SO questions about it, and I'm aware that using for example error_get_last()
doesn't help).
As you can see, I am already adding an extra .ini
file for my Xdebug config.
Do I need to do something similar for the mail configuration?
If so, how should that file be called and what should it contain?
The PHP mail()
function works by calling out to a system binary with default parameters defined by the ini config sendmail_path
- so usually /usr/sbin/sendmail -t -i
- and passing the e-mail on stdin.
You can set/change this in any php.ini that is loaded - which in your container is any *.ini file in /usr/local/etc/php/conf.d/
. So you can just drop a new file there with your desired configuration like you already did for xdebug.
But be aware that this then obviously also requires the configured binary to be installed within the container, i.e., sendmail
.
sendmail
on the other hand must be properly configured to relay the passed e-mails to a mail transfer agent. It is usually installed together with an MTA like postfix
to which it then delivers the mails locally.
This would then mean you'd had to run an MTA in the container, too - which is most probably something you don't want.
Instead you could rather use a sendmail
alternative that can be configured to directly forward the e-mails to another server via SMTP, e.g., msmtp
.
This may sound needlessly complex - and it is.
In the end it might be a better solution to use a proper mailing library for PHP which supports using SMTP servers directly - like the symfony/mailer
.