Я пытаюсь заставить свой PHP-контейнер отправлять электронные письма.
И здесь , и здесь упоминается, что настройка конфигурации должна находиться в файле php.ini
.
Однако когда я ставлю phpinfo()
где-то в своем коде, я вижу вот что:
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
Я запускаю свой проект PHP внутри контейнера Docker.
Вот Dockerfile
(немного упрощенно):
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"]
Все в порядке, контейнер создается и приложение работает нормально (не считая того факта, что оно не отправляет электронные письма):
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');
}
}
Когда я запускаю это, оно всегда оказывается внутри if
и выдает это исключение, и я не могу понять, почему. Тот факт, что функцию mail()
в PHP общеизвестно сложно отладить, также не помогает (я уже читал много вопросов SO об этом и знаю, что использование, например, error_get_last()
не помогает).
Как видите, я уже добавляю дополнительный файл .ini
для своей конфигурации Xdebug.
Нужно ли мне делать что-то подобное для настройки почты?
Если да, то как следует называть этот файл и что он должен содержать?
Когда вы не отправляете электронное письмо, вы имеете в виду, что оно выдает ошибку о том, что функция mail
не существует или что-то еще? Вы используете PHPMailer? mail
функция обычно ненадежна, и вы можете найти много вопросов по поводу того, что она не отправляет электронные письма
Вы также можете поместить все это в один файл конфигурации, это не имеет значения. Разделение конфигов предназначено только для организации. Вы также можете смонтировать файлы конфигурации как тома, и тогда вам не придется перестраивать каждый раз, когда вы что-то меняете.
@Justinas это означает, что mail
просто ничего не делает. Оно возвращается false
но я не знаю почему. Я отредактировал вопрос, чтобы добавить это.
Затем посмотрите, почему это не удается, а не на то, как включить расширение по умолчанию. stackoverflow.com/questions/786221/mail-returns-false
@Justinas, в вопросе, на который вы ссылаетесь, упоминается php.ini, который я не могу найти в своем проекте. Я думаю, что часть проблемы заключается в том, что мои настройки SMTP неверны или отсутствуют, и я не знаю, где и как их исправить. Как видите, вопрос именно об этом, а не о «включении расширения по умолчанию». Я не знаю, откуда ты это взял.
Также я вижу, что есть Loaded Configuration File (none)
. Попробуйте этот вопрос: stackoverflow.com/questions/10711698/…
Попытка выполнить SMTP с помощью mail() не сработает. Вы не можете передать пароль. Поэтому вам, возможно, придется установить почтовый сервер и настроить PHP, чтобы он видел почтовый сервер в этом контейнере или, если возможно, в отдельном почтовом контейнере.
Функция PHP mail()
работает, вызывая системный двоичный файл с параметрами по умолчанию, определенными в ini-конфигурации sendmail_path — так обычно /usr/sbin/sendmail -t -i
— и передавая электронное письмо на стандартный ввод.
Вы можете установить/изменить это в любом загруженном php.ini, которым в вашем контейнере является любой файл *.ini в /usr/local/etc/php/conf.d/
. Таким образом, вы можете просто переместить туда новый файл с желаемой конфигурацией, как вы это уже сделали для xdebug.
Но имейте в виду, что для этого, очевидно, также требуется установка настроенного двоичного файла внутри контейнера, то есть sendmail
.
sendmail
с другой стороны, должен быть правильно настроен для ретрансляции переданных электронных писем агенту передачи почты. Обычно он устанавливается вместе с MTA, например postfix
, на который затем доставляет почту локально.
Тогда это означало бы, что вам также пришлось запустить MTA в контейнере, а это, скорее всего, вам не нужно.
Вместо этого вы можете использовать альтернативу sendmail
, которую можно настроить для прямой пересылки электронной почты на другой сервер через SMTP, например, msmtp.
Это может показаться излишне сложным – и это так. В конце концов, возможно, лучшим решением будет использовать подходящую библиотеку рассылки для PHP, которая поддерживает прямое использование SMTP-серверов — например, symfony/mailer.
+1 за предложение SMTP-сервера. Поставщики электронной почты большинства пользователей (например, Gmail, Outlook) будут искать подписи DKIM в заголовках входящих писем и автоматически перенаправлять их в спам, если они отсутствуют. Использование службы электронной почты (например, Mailchimp) вместо sendmail
гарантирует наличие подписей DKIM и не нужно беспокоиться об их установке. Вы можете настроить sendmail
, чтобы установить их, но это муторно. В общем, настройка sendmail
— это головная боль.
Да, вам необходимо загрузить расширения, чтобы их использовать. Базовое изображение намеренно минимальное.