I recently noticed that the to field was getting added twice when I was sending e-mail with PHP's mail function. I spend several hours trying to figure out why, but eventually gave up and started using PHPMailer instead.
Under the hood, PHPMailer still uses the mail() function. But, the thing about PHPMailer is that it already deals with formatting and differences between Linux and Windows, which allows you to focus on more important stuff. You really do not want to spend time reinventing the wheel.
I suspect my issue might have to do with poor documentation of mail() on php.net. For example, I noticed they mention you must use "\r\n" as a separator between header fields, but on Linux postfix work with both "\n" and "\r\n" – you just have to be consistent. Note. It is recommended to use PHP_EOL for maximum portability.
I have tried both "\r\n" and "\n". In my case, both actually appeared to be working. But in both cases the to field was getting duplicated, so this was clearly not it.
If you look carefully at the source, then this might give you a hint as to what is happening. First we got the problematic e-mail, using the bare mail() function:
To: Jacob <firstname.lastname@example.org>, Subject: Message from bare mail() MIME-Version: 1.0 Content-type: text/html; charset=UTF-8 To: Jacob <email@example.com>, From: Example <firstname.lastname@example.org> Reply-To: email@example.com Date: Tue, 11 Oct 2019 08:18:25 +0200 (CEST) Hallo Jacob. This is just a test.
As you can see, the to field is actually added twice! The comma "," in the field is not supposed to be there, and does not exist in the PHP code.
Now, if we look at the headers of PHPMailer, we can see that it only adds the field once, and without the unwanted comma:
To: Jacob <firstname.lastname@example.org> Subject: Message from mailer Date: Tue, 11 Oct 2019 18:20:30 +0200 From: "example.com" <email@example.com> Reply-To: noreply <firstname.lastname@example.org> MIME-Version: 1.0 Content-Type: text/html; charset=UTF-8
The cause of the problem
I later discovered my problem was due to an apparent error in the official documentation. It was not because of incorrect use of line breaks, the Mail Transfer Agent (MTA) messing with the header fields, or other things like that.
If you look carefully on the code I was using to send e-mail with, then you will notice that I was both supplying the $to field as a parameter in the mail() function, and in the additional headers parameter. When I uncommented the "to" header field, the duplication finally disappeared. Yay!
$headers = array(); $headers = 'MIME-Version: 1.0'; $headers = 'Content-type: ' . $this->content_type . '; charset=' . $this->charset; // $headers = 'To: ' . $to; // Comma separated list of names and emails I.e. John <email@example.com>, smith <firstname.lastname@example.org> $headers = 'From: ' . $from; $headers = 'Reply-To: ' . $from_email; // $headers = 'Cc: '; // $headers = 'Bcc: '; mail($to, $subject, $message, implode(PHP_EOL, $headers));
Why use the bare mail() function
I think this has to do with simplicity and convenience.
It is very easy and convenient to use the build-in mail function, and for the most part it should work. But, it is, unfortunately, also very easy to mess up the formatting. If you do use the bare mail function, you should carefully observe the headers to check that everything is correct.
The fact that it appears to be working and you are getting the e-mails, does not mean that your message is broadly compatible, or that the headers are correctly formatted.
I would probably not have noticed this to field duplication issue, unless I did not carefully look at the to area in my e-mail client.
Also note, according to php.net, there is a strange character limit per line of 70 characters in the message body, and this needs to be handled like this:
$message = wordwrap($message, 70, "\r\n");
In addition, there are other issues with maximum line lengths of headers, which might corrupt the message. This is another reason to use PHPMailer–it is hard to account for all of these poorly documented issues on your own.