I am cross-posting from https://github.com/PHPMailer/PHPMailer/issues/2267 in hopes that someone here can help me resolve this issue.
I apologize in advance for asking a beginner question but I'm not that good with PHP (though I am working on that).
Currently, I am trying to get PHPMailer to output only server related information to to STDERR (we operate in a Docker environment and this is useful to us).
Here is my current code:
// Enable logging to STDERR
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'wb'));
// Output SMTP errors to STDERR
$phpmailer->SMTPDebug = 2;
$phpmailer->Debugoutput = function($str, $level) {error_log("debug level $level; message: $str");};
This pretty much does exactly what I want it to do, except it also outputs the entire contents of the email message body into the log which I do not want.
I have tried all the different debug levels and none of them seems to prevent the entire message from being outputted.
I would appreciate any assistance you can provide.
Thank you,
Crossposting my answer, as I figure it may be useful here too!
You can filter the error messages before saving them to your log. Look out for the DATA
command being sent, and ignore client output until you see a new server command. Here is a typical message send:
2021-02-18 08:28:00 Connection: opening to localhost:2500, timeout=300, options=array()
2021-02-18 08:28:00 Connection: opened
2021-02-18 08:28:00 SERVER -> CLIENT: 220 mac-en0.lan ESMTP
2021-02-18 08:28:00 CLIENT -> SERVER: EHLO mac-en0.lan
2021-02-18 08:28:00 SERVER -> CLIENT: 250-mac-en0.lan Nice to meet you, [127.0.0.1]
250-PIPELINING
250-8BITMIME
250-SMTPUTF8
250 AUTH LOGIN PLAIN
2021-02-18 08:28:00 CLIENT -> SERVER: AUTH LOGIN
2021-02-18 08:28:00 SERVER -> CLIENT: 334 VXNlcm5hbWU6
2021-02-18 08:28:00 CLIENT -> SERVER: [credentials hidden]
2021-02-18 08:28:00 SERVER -> CLIENT: 334 UGFzc3dvcmQ6
2021-02-18 08:28:00 CLIENT -> SERVER: [credentials hidden]
2021-02-18 08:28:00 SERVER -> CLIENT: 235 Authentication successful
2021-02-18 08:28:00 CLIENT -> SERVER: MAIL FROM:<my@email.fr>
2021-02-18 08:28:00 SERVER -> CLIENT: 250 Accepted
2021-02-18 08:28:00 CLIENT -> SERVER: RCPT TO:<name_lastname@example.com>
2021-02-18 08:28:00 SERVER -> CLIENT: 250 Accepted
2021-02-18 08:28:00 CLIENT -> SERVER: DATA
2021-02-18 08:28:00 SERVER -> CLIENT: 354 End data with <CR><LF>.<CR><LF>
2021-02-18 08:28:00 CLIENT -> SERVER: Date: Thu, 18 Feb 2021 08:28:00 +0000
2021-02-18 08:28:00 CLIENT -> SERVER: To: "Lastname, Name" <name_lastname@example.com>
2021-02-18 08:28:00 CLIENT -> SERVER: From: Root User <my@email.fr>
2021-02-18 08:28:00 CLIENT -> SERVER: Subject: =?UTF-8?B?2LfZhNioINin2YbYqtiv2KfYqA==?=
2021-02-18 08:28:00 CLIENT -> SERVER: Message-ID: <CdIzpGbLD6Kc99lGGX3wTS0vGRcMNungIzDbEuHDlQ@Octoo-en0.lan>
2021-02-18 08:28:00 CLIENT -> SERVER: X-Mailer: PHPMailer 6.2.0 (https://github.com/PHPMailer/PHPMailer)
2021-02-18 08:28:00 CLIENT -> SERVER: MIME-Version: 1.0
2021-02-18 08:28:00 CLIENT -> SERVER: Content-Type: text/html; charset=UTF-8
2021-02-18 08:28:00 CLIENT -> SERVER:
2021-02-18 08:28:00 CLIENT -> SERVER: some text
2021-02-18 08:28:00 CLIENT -> SERVER:
2021-02-18 08:28:00 CLIENT -> SERVER: .
2021-02-18 08:28:00 SERVER -> CLIENT: 250 OK: message queued
2021-02-18 08:28:00 CLIENT -> SERVER: QUIT
2021-02-18 08:28:00 SERVER -> CLIENT: 221 Bye
2021-02-18 08:28:00 Connection: closed
The approach would be to stop logging when you see SERVER -> CLIENT: 354
, and start again when you see SERVER -> CLIENT
. This does mean that your logging is stateful, which isn't ideal (e.g. you can end up in a broken state if the mail server drops the connection while the message data is sending), but it it should work ok.
A different approach might be to rearrange how you're sending. Install a mail server like postfix inside your container and relay your sends through that from PHPMailer, then you can get the mail server to do your logging. This will also take care of many other things relating to sending email that your script will not be doing, such as bounce handling, deferrals, etc, and will also be much faster as far as your sending scripts are concerned.
Something like this (using PHP 8):
$phpmailer->Debugoutput = function ($str, $level) {
static $logging = true;
if ($logging === false && str_contains($str, 'SERVER -> CLIENT')) {
$logging = true;
}
if ($logging) {
error_log("debug level $level; message: $str");
}
if (str_contains($str, 'SERVER -> CLIENT: 354')) {
$logging = false;
}
};
I do the "turn off" check after the debug output so that the 354
line will appear in the logs.