11

Is there an equivalent to mysql_real_escape_string() for email injection? I have a form where the user submits their email. I am afraid that someone could insert a comma separated list of emails and use my site for spamming.

Brian
  • 26,662
  • 52
  • 135
  • 170

6 Answers6

33

You can use filter_var to validate the e-mail address:

if (!filter_var($address, FILTER_VALIDATE_EMAIL)) {
    // invalid e-mail address
}
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • Will that ensure that there is only one email address? – Brian Jan 27 '10 at 11:23
  • @Brian: Yes, it will return *false* if you test a string like `user-a@example.com,user-b@example.com`. – Gumbo Jan 27 '10 at 11:25
  • 4
    +1 for using a native function – Gordon Jan 27 '10 at 11:25
  • Does filter_var() allows to create custom validation flags? I'm thinking of applying it to check uniqueness of value in DB. Or it is not a good idea? – Kirzilla Jan 27 '10 at 11:30
  • @Kirzilla: You could write a wrapper function that does both use `filter_var` to validate the address and does a database lookup for uniqueness. – Gumbo Jan 27 '10 at 14:09
  • If you are using PHP5... – jasonflaherty Aug 23 '13 at 23:06
  • 1
    Certainly technically the best answer. However FILTER_VALIDATE_EMAIL will tell the follwoing email address is valid: _my$sd/f+sdf@domain.com-com-com-com_ Most of my customers perfer to filter out such addresses, so I still give preg_match a chance. – ESP32 Jan 28 '16 at 10:18
2

Simply validate the field against a commonly found regular expression for single email address

function validate_email($e){
    return (bool)preg_match("`^[a-z0-9!#$%&'*+\/=?^_\`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_\`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$`i", trim($e));
}
mauris
  • 42,982
  • 15
  • 99
  • 131
1

For those with older versions

/*
    # PHP Email Validation for versions LESS than PHP 5.2.0)
*/
$strEmail= mysql_real_escape_string($_POST['email_e']);
if (!eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$", $strEmail)){

        // valid email

        } else {

        // not a valid email
}
TheBlackBenzKid
  • 26,324
  • 41
  • 139
  • 209
0

I found that good email validation is not that simple, so just decided to check if "@" and "." is in the string.

function email_valid($email){
    /* EMAIL VALIDATION, CHECKS IF STRING CONTAINS "@" and "."  */

    if( strpos($email, "@") AND strpos($email, ".") ){
        return TRUE;
    }
    else {
        return FALSE;
    }
}

P.S. if you don't use PDO prepared statements for writing to database, BE SURE to filter out symbols which may cause sql injection

Tomas
  • 1,377
  • 3
  • 17
  • 32
  • You could at least be sure that the '.' position is bigger than the '@'. Still I think it's possible to create a better validation with regex expression. – patricia Jul 24 '13 at 12:06
  • Actually, email may even not contain a ".", e.g. "user@hostname" in intranet should be perfectly usable – Victor Sep 14 '17 at 09:26
  • @Victor that's true. After a few years of programming since I originally answered the question, I came to the conclusion that it's not worth validating email addresses more than ``. What you care about is if the user can receive an email from you which might not be possible even with a valid email address so it's much simpler to just send a confirmation email instead of writing validation code. – Tomas Sep 14 '17 at 10:23
0

It would be simpler to check the total string length - ie local part max 64 + the @ + domain section max 255 characters = 320 characters, but then spamming short addresses would still be possible. I am currently researching email validation for my project and found this interesting article email validation which explains in-depth valid email addresses and the rfc2822. There they suggest a much simpler way to validate that would prevent comma separated lists being an effective form of spamming.

$isValid = true;
$atIndex = strrpos($email, "@");
if (is_bool($atIndex) && !$atIndex)
{
   $isValid = false;
}
else
{
   $domain = substr($email, $atIndex+1);
   $local = substr($email, 0, $atIndex);
   // ... work with domain and local parts
}

This simply breaks the email address down by finding the last @ sign and declares all that passes before it to be the local part of the address which has a limit of 64 characters. If there is no @ sign then strrpos will return a bolean value of false. I will be making use of this in my validation function.

Weedy101
  • 13
  • 1
  • 8
0

If your primary concern is, as the question states, to verify that users have not attempted to trick you into spamming for them by entering a comma-separated list of addresses, then isn't the obvious answer to simply check whether there are any commas in the user's input?

Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102