Page 1 of 1

Using PHP to send emails

Posted: Fri 10 Jul 2009 14:42
by David Gibson
Using PHP to send emails

This note is aimed at people who are already using a PHP routine to automatically send emails on the BCA web server. (i.e. this is not a PHP email 'tuition' document). For example, you might have an enquiry form, where the customer types an enquiry and his email address; the contents of the form are emailed to you, and a copy sent to the customer.

Summary

To send your customers a sensible-looking email and to avoid bothering the system administrator with your bounces, you should always set both a From: address and a Return Path. The From: address has to be constructed manually as part of the headers argument to PHP's mail() function and the return path is set using the 'additional parameters' argument.

In addition, you should make sure that the return path is a valid email address because some mail servers will simply discard mail that does not have a valid return path. Therefore, if you dont do this, random emails will simply disappear.

Details

In the above scenario – an enquiry form on your web site – a problem arises if the customer types an invalid email address. When the web server attempts to send a message to him it will fail and the mail transport agent (MTA) will attempt to generate a failure notification (a 'bounce' message) but who should it send it to? If you do not tell PHP what to do with bounces they will be sent to the system administrator, which is an annoyance both for him and you!

This note assumes that you already understand* the complexities of generating email messages in PHP (e.g. the required line terminations, line lengths and so on) and it addresses only the problem of setting a correct 'return path' for your automatically generated emails.

*well, OK, you know that headers are separated by \r\n but that the lines of the message are separated only by \n and shouldn’t be > 70 characters? And that you must be careful that the syntax of each of your headers is correct?

Basically, the fifth argument to PHP's mail() function (see http://uk.php.net/manual/en/function.mail.php) is a string representing additional parameters to be passed to the underlying MTA. This is obviously system-dependent, and the following guidance is based on practical observation of the particular set-up currently used on the BCA server. It does not necessarily apply anywhere else! It is known, for example, that the –f parameter is ignored by some MTA installations.

To set an email address of joe@bloggs.name as a return path you should set the fifth argument to mail() to be the string "-fjoe@bloggs.name" with no space between the '-f' and the email address. You should also set a From: address in the 'additional headers', which is the fourth argument to mail() – its arguments being mail($to, $subject, $message, $headers, $parameters). You should specify both a From: address and a return path. If you do not specify both, this is what happens…
  1. If youre on the BCA web server and you do not specify a return path, the MTA will set a default of nobody@[bca-webserver] and so any bounces will go to the BCA system administrator. (Ive used [bca-webserver] to avoid publishing the actual email address). On other servers, you may get 'nobody@' or perhaps 'anonymous@'.
  2. If youre on the BCA web server and you do not specify a From: address, the MTA will set the From: username to be 'Nobody' and will take their email address from the Return Path. In other words, if you set a return path of joe@bloggs.name but do not set a From: address then the From: address will default to Nobody <joe@bloggs.name> . If you didn’t set a return path, the From: address would default to Nobody <nobody@[bca-webserver]>.
Testing email addresses

The other thing you can do to avoid your customers submitting an invalid email address is to test the address before you use it. PHP has routines that will check whether a given domain is valid and whether a given email address has a valid MX record. Unfortunately, in my experience, these do not always work, and particular domains will always return the wrong result. Whether this is due to badly set-up DNS records or what, I dont know, but it happens frequently enough to make this method annoying – i.e. it is annoying for the customer to be told his email address is not valid when he knows that it IS valid.

It is more reliable to simply check that the syntax of an address is correct (and, of course, you can trap typos by making your customer type the address twice). A simple routine in Javascript, to check the syntax of an email address, is

Code: Select all

Function checkEmailSyntax($email)
// If the argument is syntactically correct then return true
// else print a warning message and return false.
{
  var $pattern = /^[0-9a-z_]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\.[a-z]{2,4}$/i;
  if (!$pattern.test($email))
  { window.alert($email + "\nis not a valid email address"); return false; }
}
You can, of course, do this in PHP if it suits your set-up better – the code will be different but the regular expression will be similar.

Posted: Fri 10 Jul 2009 16:15
by David Cooke
Excellent post. :thumbleft:

I'll now badger the Wessex, BCA & SBSS webmasters to sort out their php code so I don't continue to receive their bounces. :smt071

Re: Using PHP to send emails

Posted: Wed 15 Jul 2009 11:24
by David Gibson
David Gibson wrote:you should make sure that the return path is a valid email address because some mail servers will simply discard mail that does not have a valid return path. Therefore, if you dont do this, random emails will simply disappear.
It looks like that might be the cause of a problem on the http://ukcaving.com forum. See http://ukcaving.com/board/index.php/topic,6137.0.html

I cannot get their server to send me any messages - password reminders, activation codes, reply notifications, PM notifications etc - and neither of the ISPs I use for email (Demon and Gradwell) will accept messages with an invalid return path.

The last time the http://ukcaving.com server managed to send me a message was in 2006 with, as I now see, a return path that is (currently) invalid. Not exactly a QED but ... close?

Im currently locked out of ukcaving.com because I cannot re-activate my account after changing the email address as an experiment. It wont send me the re-activation code! Neither has it sent me a copy of the message I sent to Admin. Im putting my money on a Return Path problem!

Re: Using PHP to send emails

Posted: Wed 15 Jul 2009 16:16
by David Gibson
David Gibson wrote: you should make sure that the return path is a valid email address because some mail servers will simply discard mail that does not have a valid return path. Therefore, if you dont do this, random emails will simply disappear.
Hmm. That specific behaviour appears to be limited to a certain set of conditions on Gradwell's mail server (that hosts CAVES and BCRA), which is that if the spam filtering is turned OFF then the server attempts to verify the complete return path (i.e. username as well as domain) and if it doesnt check out, it drops the message without issuing a rejection.

There may be other servers that do similar - accounting for intermittent loss of email, but the prevalent behaviour is, in fact, something different, viz...

If the return path does not have a valid domain (or, more probably, a domain with a valid MX or A record) then the mail is dropped by the sending program.

That is, of course, a completely different effect

Also, I was wrong to say that that's what Demon does. Currently Demon allows bad return paths. But Demon will - from the end of this month - issue a 550 rejection if the return path does not have a valid MX or A record. See http://www.demon.net/helpdesk/networkst ... 9july.html

Re: Using PHP to send emails

Posted: Mon 20 Jul 2009 18:08
by David Gibson
David Gibson wrote: That specific behaviour appears to be limited to a certain set of conditions on Gradwell's mail server (that hosts CAVES and BCRA), which is that if the spam filtering is turned OFF then the server attempts to verify the complete return path (i.e. username as well as domain) and if it doesnt check out, it drops the message without issuing a rejection.
That's completely wrong, I now realise. :oops:

The reason I was getting inconsistent and very puzzling behaviour was due to something else entirely. But .. bloody hell .. it took some detective work to find the fault. So ... to summarise ...
  • You should ALWAYS set a valid return path, to avoid bothering SysAdmin with your bounces.
  • If the domain of your return path does not have a valid MX or A record then your mail might be rejected (550) by some servers
  • If the domain of your return path does not have a valid MX or A record then your mail might be dropped by the sending program without generating any error. (Still requires further testing to verify this behaviour).
The problem I had was an obscure one, but I will mention it for completeness. If you attempt to do a mail operation (e.g. sendmail, mailman) on the same host on which you are running mail forwarding it can produce odd effects. This is because the machine probably does not do a genuine MX lookup, because it "knows" that your mail is handled locally. I was using PHP to send email from the caves.org.uk web server, but that machine "knew" that my caves email forwarding was hosted by the same ISP so it did not bother to look for an MX record. If it had done, it would have realised that I moved the mail forwarding a long time ago! Thus the machine was using an out-of-date look-up table for the mail forwarding, which lead to the intermittent and very peculiar errors. Actually, its doubly embarassing because I already knew that this was a problem with many ISPs, viz: to save resources they dont do proper MX lookups for local mail.
:smt013