malte70.blog()

PHP mail(), sendmail und MSMTP

PHP mail()-Funktion & sendmail

Wenn Dein Webserver nicht gleichzeitig ein E-Mail-Server ist, scheitert der korrekte Mail-Versand via sendmail. Das betrifft sowohl die häufig von Skripten verwendete PHP-Funktion mail(), als auch die klassischen Mailutils, die z.B. auch vom cron-Daemon für Benachrichtigungen verwendet werden.

Mit MSMTP besteht jedoch die Möglichkeit, E-Mails über einen externen Mail-Server zuzustellen.

Im folgenden zeige ich Dir, wie du MSMTP installierst und einrichtest, sowie den Mail-Versand via Mailutils und PHP konfigurierst.

Anmerkungen

  • Die Server-Konfiguration in den folgenden Beispielen ist für Hosted Mailcow; sollte jedoch bei den meisten Mailservern funktionieren
  • Im folgenden gehe ich von einem eigenen E-Mail-Postfach für den Server aus: server@example.com. Der Account kann außerdem den alternativen Absender webmaster@john-doe.example nutzen.

MSMTP installieren

Debian/Ubuntu

sudo apt-get install msmtp msmtp-mta mailutils

ArchLinux

ArchLinux nutzt s-nail als mailx-Implementierung, d.h. das mailutils-Paket enthält kein mailx-Binary.

sudo pacman -S msmtp msmtp-mta mailutils s-nail

macOS

brew install msmtp msmtp-mta mailutils

Achtung

Alle via Homebrew installierten Pakete haben einen Prefix, vergleichbar mit /usr/local/ bei FreeBSD-Ports:

  • Apple Silicon: /opt/homebrew
  • Intel: /usr/local

Dieser muss bei den im folgenden genannten Pfaden immer voran gestellt werden, also z.B. /opt/homebrew/etc/mail.rc statt /etc/mail.rc auf einem Apple Silicon-Mac.

/etc/msmtprc

Die systemweite Konfiguration von MSMTP befindet sich in der Datei /etc/msmtprc. Alternativ kann auch pro Benutzer eine ~/.msmtprc genutzt werden, worauf wir hier jedoch verzichten werden.

Zunächst werden einige Default-Werte für alle Accounts festgelegt, und das Logging feinjustiert.

# 
# /etc/msmtprc
# 

# 
# Defaults for all accounts
# 
defaults

# Hosted Mailcow
host hosted.mailcow.de
port 587
tls on
tls_starttls on
auth on

# Syslog logging with facility LOG_MAIL instead of the default LOG_USER
syslog LOG_MAIL
# Logfile
#logfile /var/tmp/msmtp.log

Es folgen die Einstellungen für die Accounts. Hier wird der Account server@example.com konfiguriert, sowie die alternative Absenderadresse webmaster@john-doe.example mit dem selben Account:

# 
# Account server[@example.com]
# 
account server
from "example.com Server" <server@example.com>
user server@example.com
password asdf1234

# Alternate envelope-from address
account webmaster : server
from "john-doe.example Webmaster" <webmaster@john-doe.example>

Als Standard-Account wird webmaster@john-doe.example genutzt; außerdem wird eine Mailalias-Datei angegeben, damit für Cronjobs und die Mailutils lokalen Benutzern Accounts zugeordnet werden:

# Set a default account
account default: webmaster

# Map local users to mail addresses (for crontab)
aliases /etc/msmtp_aliases

/etc/msmtp_aliases

Die Alias-Datei hat das gleiche Format wie /etc/aliases, außer dass Benutzer nicht anderen Benutzern zugeordnet werden, sondern zu E-Mail-Adressen. Außerdem kann ein default-Empfänger angegeben werden für alle nicht explizit erwähnten Nutzer.

# vim: set filetype=mailaliases:
# 
# /etc/msmtp_aliases
# 

root: hostmaster@example.com
john: mail@john-doe.example

# Default
default: hostmaster@example.com

/etc/mail.rc

Um die Mailutils zu verwenden, muss in der Datei /etc/mail.rc das zu verwendende sendmail-Kommando festgelegt werden:

set sendmail="/usr/bin/msmtp -t"

Desweiteren bietet das Paket oben bereits mit installierte msmtp-mta eine Drop-In-Kompatiblität mit sendmail für alle Programme, die nicht auf die sendmail-Option in der /etc/mail.rc zugreifen. Wann immer möglich empfehle ich jedoch, MSMTP explizit als sendmail-Implementierung einzustellen, siehe dazu auch weiter unten die PHP-Konfiguration.

Mit Mailutils testen

Mit mailx kannst Du nun den Versand von E-Mails an lokale Nutzer testen. Die Abfrage nach CC und Betreff wird mit <Enter> bestätigt, und am Ende der Mail beendet ein <Strg>+<D> die Eingabe und die Mail wird versendet:

$ mailx root
Cc: 
Subject: mailx-Test via MSMTP
Hallo root!

Dies ist eine Testmail, die von mailx an MSMTP übergeben werden soll, um dann via
SMTP ausgeliefert zu werden.

-- 
mfg
John Doe
^D

php.ini

Da PHP nicht auf /etc/mail.rc zugreift, muss das sendmail-Kommando auch in der php.ini nochmal angegeben werden. Der Pfad dieser hängt meist von der Verwendeten Runtime und PHP-Version ab; bei PHP-FPM 8.2 unter Raspbian ist dies z.B. /etc/php/8.2/fpm/php.ini.

[mail function]
; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
; https://php.net/sendmail-path
#sendmail_path = "/usr/bin/msmtp -C /var/www/.msmtprc -t"; Per-user config
sendmail_path = "/usr/bin/msmtp -t" ; Global config

Jetzt testen wir den Versand mit einem kleinen PHP-Skript:

<?php
$email = Array(
	"subject"   => "PHP mail() via MSMTP",
	"recipient" => "mail@john-doe.example",
	"message"   => "Hallo!\n\nDiese E-Mail wurde mit der PHP-mail()-Funktion via MSMTP zugestellt.\n\n-- \nmfg\nWebmaster",
);

mail($email["recipient"], $email["subject"], $email["message"]);

crontab

In crontab-Dateien kann eine Empfänger-Adresse für Benachrichtigungen angegeben werden. So kannst Du dann die Benachrichtigungsmails anhand des Empfängers von Deinem Mailfilter verarbeiten lassen:

# Beispiel-crontab-Datei

MAILTO=crontab@john-doe.com

# m  h   dom mon dow   command
@reboot                /usr/bin/env /usr/local/sbin/dns-update.sh
0    *   *   *   *     /usr/bin/env /usr/local/sbin/dns-update.sh