All in the <head>

– Ponderings & code by Drew McLellan –

– Live from The Internets since 2003 –

About

About Drew McLellan

Photo of Drew McLellan

Drew McLellan has been hacking on the web since around 1996 following an unfortunate incident with a margarine tub. Since then he’s spread himself between both front- and back-end development projects, and now is Director and Senior Web Developer at edgeofmyseat.com in Maidenhead, UK (GEO: 51.5217, -0.7177). Prior to this, Drew was a Web Developer for Yahoo!, and before that primarily worked as a technical lead within design and branding agencies for clients such as Nissan, Goodyear Dunlop, Siemens/Bosch, Caburys, ICI Dulux and Virgin.net. Somewhere along the way, Drew managed to get himself embroiled with Dreamweaver and was made an early Macromedia Evangelist for that product. This lead to book deals, public appearances, fame, glory, and his eventual downfall.

Picking himself up again, Drew is now a strong advocate for best practises, and is currently Group Lead for The Web Standards Project. He has had articles published by A List Apart, Adobe, and O’Reilly Media’s XML.com, mostly due to mistaken identity. Drew is a proponent of the lower-case semantic web, and is currently expending energies in the direction of the microformats movement, with particular interests in making parsers an off-the-shelf commodity and developing simple UI conventions. He writes here at all in the head and, with a little help from his friends, at 24 ways.

PHP mail() and The Path of No Return

2 November 2007

Recently, I learned something new about one of the oldest technologies I regularly use – email. Once you get beyond putting a simple plain text email together for sending from a web app, email can get pretty complicated. Sending things in multiple formats (such as HTML with a plain text fall-back), sending attachments, using different encodings and so on, generally there’s quite a lot to know about mail.

One thing I didn’t really know much about was the SMTP envelope. Whilst the mail has a set of headers indicating the subject, who it’s from and who it’s to, the envelope that surrounds that mail has a bunch of headers too. It was these envelope headers that were causing me an issue on one site I run.

I had a message forwarded from a rather irate user who was complaining that he wasn’t receiving our emails because our server was sending from an invalid email address. He had his mail server configured to reject any email sent from an invalid address (I guess to combat spam) and so was rejecting our mails when they got to him. I was sending using PHP’s mail() function, and was dutifully setting the From: header to a valid address, so at first didn’t get what was going on.

Turns out the problem was with the From address on the envelope, and not in the message headers themselves. PHP’s mail() function uses Sendmail to, well, send mail. On being given a message to send that has no explicit envelope From address set, Sendmail will make up an address of current-user@server-name. If you’re lucky this might coincide with a real email address, but in a lot of cases it won’t. This was the circumstance I was coming up against, and the reason our emails weren’t getting through.

Turns out (via a very helpful comment on the php.net page for mail()) that lesser-spotted fifth argument to mail() can be used to send an additional parameter to Sendmail to set the envelope From address. "-r from@example.com"

For good measure, you should also set the Return-Path header on the mail (typically to the same address), as this is also sometimes checked for validity. I’ve been using PHP’s mail() function for years without knowing this, so I thought it was probably worth sharing.

I did a bit of spot checking in my mailbox of emails I’d recently received from other online services. This default current-user@server-name envelope address and Return-Path is incredibly common. I know Shaun uses PHP over at Mint, and his emails looked exactly like mine. (As an aside – I really recommend Mint. I use it on a couple of sites and it’s both inexpensive and full of awesomeness.)

Of course, it’s valid to question whether it’s wise to be rejecting email on the basis of a mistake is some obscure mail headers that perhaps not a lot of people know about. However, by the same reasoning, if I’m going to suggest people should be liberal in what they receive, I need to uphold my end of the bargain and be strict in what I send.

- Drew McLellan

Comments

  1. § Arjan:

    Every once in a while, we get a phone from our web hoster because one of the programmers forgot to use the Return-path. Especially with large websites he gets annoyed with the lots of blocked e-mail.

  2. § Peter Mount:

    Glad to see you back on the blog Drew, I was getting worried about you. Now if I can get the php mail() function to stop sending emails from “nobody” I’d be happy.

  3. § Krijn Hoetmer:

    Shouldn’t that be ”-f from@example.com”? Or is that a different option?

  4. § Drew:

    Different option – check the link to the comment on php.net.

  5. § Adam:

    Top notch advice! You can also use the ini_set function to set the default email address that PHP uses if you wish to go that way about matters. Either or though, no more irate customers! Or, well, that’s the theory.

Photographs

Work With Me

edgeofmyseat.com logo

At edgeofmyseat.com we build custom content management systems, ecommerce solutions and develop web apps.

Recent Links

Affiliation

  • Web Standards Project
  • Britpack
  • 24 ways