Just came up with a fairly smart way to validate email that removes a few issues generally caused by this sort of stuff. It’s not totally complete and it’s obviously part of a validation class – anybody planning on using it will need to modify it to make it work to their needs.
I return a value so the class which calls this can replace the value back in the form if there is an error, and it actually replaces it in the data that is used (sent to the DB or whatever), I also use a custom validation exception class, these are all things that will need to be considered if anybody who sees it plans on using. Caveat emptor and whatnot.
What it does is sends the value to the PHP filter functions for validating as looking remotely like an email address, which is handy but it will validate local addresses and for domains that don’t exist.
What my code does is check if there is a remote address part and then if it is an IP just allows it, if it’s a domain it checks if the domain has MX records using checkdnsrr() – if that’s all good it allows it.
What could be improved? It doesn’t work so well at preventing local IP addresses going through. It also won’t tell you if the user is legit at a given domain or if the user has any association at all, so address validation will be a must in some circumstances, but it will prevent the standard dfgdf@dfdgdf.com type stuff. At least you’ll know if the domain part looks even close to reasonable, which is one of the ‘failings’ (read: missing features?) of FILTER_VALIDATE_EMAIL if you want internet-only addresses entering.
public function email_address($value) {
$result = filter_var($value, FILTER_VALIDATE_EMAIL);
if($result == false) {
throw new validateException("Invalid email address");
}
$domain = explode("@", $value, 2);
if(filter_var($domain[1], FILTER_VALIDATE_IP) !== false) {
return $value;
}
if(checkdnsrr($domain[1]) == false) {
throw new validateException("Email domain doesn't seem to exist or is incapable of recieving mail");
}
return $value;
}
« Doing Fun Stuff With Servers What’s Taking So Long, Damnit? »

Is it really necessary to have so sophisticated check? Just send a validation email and it will mostly tell you if the user uses a legit email or not…
To an extent that’s true. That being said, if you’re anything like me you’ve seen your databases full of this sort of crap in signups et al:
dsfs@dsfsdf.com
fsdfdsf@dffsdfs.com
At the end of the day it’s all a little pointless for everybody involved thus – be a bit smarter about it. I’m not actually all that convinced it’s very sophisticated either to be fair, I mean have you seen the close-to-RFC 2822 regexps? And they don’t even tell you if the bit on the end is even slightly legit.
That said it’s all about helping users not make mistakes, if they type @gogglemail.com as opposed to the correct domain, this is why we do input validation at the end of the day – sending a validation email doesn’t fix that, and user wonders why they didn’t get a validation email. Obviously it won’t end that – but it will help.
http://github.com/doctrine/doctrine1/blob/master/lib/Doctrine/Validator/Email.php
This is the best validation for an email address I’ve seen – similar to your thoughts, and the source doc they refer to is a good read as well
– http://iamcal.com/publish/articles/php/parsing_email/pdf/
Email sent to a domain which has only an A record typically gets delivered to that record, doesn’t it? So this isn’t a complete check.
I.e. A only: sent to A
A+MX: sent to MX
According to 2821 sec5 you are correct. The good news is nobody who actually wants email sets up their dns without at least one MX record.
That said it’s probably something to bear in mind.
Learn something new every day I guess