PHP mail and ISP relays
This did my head in so I thought it worthy of a small write up.
Here the problem: I wanted to send an email from a DRUPAL 5.12 site hosted on a home linux configured with sendmail/postfix and a SMART RELAYHOST.
Sounds simply enough.
Here is my simple test program in PHP to send an email.
<?php $Name = "Da Duder"; $email = "dude@duder.com"; $recipient = "yo@company.com"; $mail_body = "The text for the mail..."; $subject = "Subject for reviewer"; $header = "From: ". $Name . " <" . $email . ">\r\n"; mail($recipient, $subject, $mail_body, $header); ?>
Doesn't get easier than that. Now this is where the fun starts. If you look at the mail log.
/var/log/maillog
Dec 3 16:05:53 elmo postfix/pickup[13979]: 06BCA92EE80: uid=48 from=<apache> Dec 3 16:05:53 elmo postfix/cleanup[14081]: 06BCA92EE80: message-id=<20081203160553.06BCA92EE80@elmo.local> Dec 3 16:05:53 elmo postfix/qmgr[13980]: 06BCA92EE80: from=<apache@elmo.local>, size=330, nrcpt=1 (queue active) Dec 3 16:05:53 elmo postfix/smtp[14083]: 06BCA92EE80: to=<yo@company.com>, relay=smtp.blueyonder.co.uk[195.188.53.60]:25, delay=0.21, delays=0.06/0.02/0.07/0.06, dsn=2.0.0, status=sent (250 OK id=1L7sEh-0000Yg-Kl) Dec 3 16:05:53 elmo postfix/qmgr[13980]: 06BCA92EE80: removed
You see that the envelope-sender is actually apache@elmo.local this address is checked by yo@company.com spam's filter says “Hay that not valid I'll reject that”.
So what you need to do is tell sendmail that it should use the “from:” as the envelope sender too.
Small modification to the PHP and this is done. Why did that take me an hours to figure out? God only knows.
mail($recipient, $subject, $mail_body, $header,'-f'.$email);
So back to DRUPAL the PHP mail() function is wrapped by the function drupal_mail() in the includes/common.inc file.
So we tweak the invokation like so:
function extract_email_from($string){ preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $string, $matches); return $matches[0][0]; } function drupal_mail($mailkey, $to, $subject, $body, $from = NULL, $headers = array()) { .. snip .. return mail( $to, mime_header_encode($subject), str_replace("\r", '', $body), join("\n", $mimeheaders), '-f '.extract_email_from($defaults['From']) ); }
Reference: http://drupal.org/node/131737, http://codesnippets.joyent.com/posts/show/179