PHP mail() function and GMail

or Another reason to avoid PHP’s mail() function

Since launching on Monday we’ve fixed a few bugs that only came to light as a result of the way other people work. One such was an email problem with messages sent to GMail (thanks to Alan for catching this). I’ve never had a GMail account so it wasn’t one of the email applications we tested the messages with.

Email messages were arriving at GMail with messages garbled into a string of apparently random characters and with the sender listed as unknown. I was using mb_send_mail() to send UTF-8 email messages from PHP. I always intended to implement a different email solution at some point but evaluating the various possibilities and making a choice didn’t seem as important for the launch period as many of the other features so I chose to start with mb_send_mail() and switch to another solution later.

mb_send_mail() was sending messages as UTF-8 and base64 encoded, and it seems that GMail failed to correctly understand this from the email headers. As a result, GMail simply displayed the base64 encoded data. The quick fix just to get it working was to switch to PHP’s mail() function. This would suffice for a few hours while we sought a better solution.

The other problem was GMail displaying the sender as unknown, despite having the sender data in the From: header. I tried various different formats for the From: header (quotes around the name, extra spaces etc.) but none seemed to work for GMail. Instead, it always displayed the From: header line in the body of the message (there were no blank lines in the header so that’s not the problem, and the messages worked with a number of other email applications we tested them with).

I still haven’t discovered what the problem was but have three possibilities.

  1. Does GMail dislike the unconventional (but not technically wrong) ordering of the headers that mail() and mb_send_mail() produce?
  2. Does GMail distrust messages in which the X-Mailer header lists “PHP mailer” as the system used and consequently displays the sender as unknown and places the from data in the message?
  3. Is mail() doing something wrong in its headers, and most email applications are simply ignoring the mistake and figuring out what’s intended?

If anyone knows the actual cause please add a comment below.

Anyway, the obvious solution was to avoid PHP’s mail functions altogether so I hurriedly added Chris Corbyn’s Swift Mailer script and altered my code to use it, and all was well. I haven’t thoroughly tested Swift Mailer yet but it seems to be working fine – the messages are in UTF-8 and GMail is happy with them.

Swift Mailer is just one of many alternatives to the mail() function but I like it for it’s simplicity of use. Hopefully, when I test it out more thoroughly later this month I’ll still be very happy with it.

12 thoughts on “PHP mail() function and GMail

  1. Maybe try using PHPMailer

    I have discovered though, that I need to set the mail encoding to iso 8559-1 or whatever it is when sending out multipart and pure text messages, otherwise the special characters in German all get stuffed up (with any mailer btw.).
    Oh, and in case you’re using some sort of templates coming from files that were stored in utf8, a utf8_decode before putting the string into the mail helps as well. Maybe that’s your issue right there.

  2. I’m using simple mail() and have no problems with GMail. It could be I guessed some special order of headers that GMail prefers. I don’t know. Here’s the code anyway:

    $headers = "MIME-Version: 1.0\r\n";
    $headers .= "Content-type: text/plain; charset=iso-8859-2\r\nContent-Transfer-Encoding: 8bit\r\nX-Priority: 1\r\nX-MSMail-Priority: High\r\n";
    $headers .= "From: $from\r\n" . "Reply-To: $from\r\n" . "X-Mailer: PHP/" . phpversion() . "\r\nX-originating-IP: " . remoteaddr () . "\r\n";
    $success = @mail ($to, $subject, $message, $headers);

  3. Jan, the mail() function will always send mail as iso 8559-1, that’s why it fails with characters in any other encoding. However, mb_send_mail() is specifically intended for sending mail using other encodings (it’s part of the mbstring extension for PHP and is intended as a direct replacement for mail() where other encodings are required).

    My original setup used mb_send_mail() to send UTF-8 mail. This worked fine with all the mail readers I’ve tested it with apart from GMail.

    Even when sending iso-8559-1 mail using the mail() function, GMail fails to use the sender data from the header and shows the sender as unknown – this is the second problem outlined above.

    I looked at PHPMailer but was dissuaded by the complexity of the interface and the fact that it doesn’t appear to be worked on currently – the latest version is 16 months old. Not that there’s anything wrong with that but my brief comparison with Swift Mailer suggests the latter has a similar feature set with a simpler interface.

  4. Swift Mailer is newer and in active development. PHPMailer died a quiet death a couple of years ago (just look at the last change on!) yet everybody still insists upon using it. It’s also pretty nasty OOP ;)

    Swift Mailer will be making it’s next release very soon which actually provides the ability to compose your email with swift and send it elsewhere among other enhancements such as an improved plugin API.

    I am more commonly seeing Swift recommended as a standard these days over PHPMailer although there still seem to be a lot of people who stick with the one that started first for whatever reasons they have.

    *cough* if you hadn’t guessed, I wrote swift hence the slightly biased post :P

  5. This was stupid. My script didn’t work with gmail until I stripped \r and just used \n. Both created a double rowbreak resulting in gmail thinking headers were all sent after first row.

  6. I had the same problem too and after a lot of hours trying to solve it, you save me!

  7. yep, same problem here. stripping out the \r fixed it for me in gmail…

    if (preg_match('/gmail/',$email_address))
    $headers = str_replace("\r\n","\n",$headers);

  8. Try using ‘wordwrap’ when sending the message, this should break up the email and
    fix the issue:

    @mail($to, $subject, wordwrap($message), $headers);

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>