Как да валидирам имейл в PHP?

Как мога да проверя, че въведената стойност е валиден имейл адрес с помощта на php5. Сега използвам този код

function isValidEmail($email){ 
     $pattern = "^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$"; 

     if (eregi($pattern, $email)){ 
        return true; 
     } 
     else { 
        return false; 
     }    
} 

но показва остаряла грешка. Как мога да поправя този проблем. Моля, помогни ми.


person learner    schedule 02.05.2011    source източник
comment
Правилният отговор вече беше даден, но по отношение на проблема с отхвърленото: Използването на POSIX регулярни изрази (на които eregi е функция) е отхвърлено. Вместо това използвайте PCRE.   -  person Felix Kling    schedule 02.05.2011
comment
Между другото, регулярният ви израз е напълно грешен. Някои напълно валидни адреси ще бъдат маркирани като невалидни от вашата функция. Филтрирането на имейл адреси с регулярен израз е кошмар.   -  person Artefact2    schedule 02.05.2011
comment
Трябва да използвате RFC 822 стандарт и ето една добра статия Разбор на имейл адреси в PHP, който го обяснява.   -  person kta    schedule 06.01.2014
comment
Стойте далеч от regex и filter_var() решения за валидиране на имейл. Вижте този отговор: stackoverflow.com/a/42037557/953833   -  person Jabari    schedule 04.02.2017


Отговори (6)


Можете да използвате функцията filter_var(), която ви дава много удобни опции за проверка и дезинфекция.

filter_var($email, FILTER_VALIDATE_EMAIL)

Ако не искате да промените кода си, който разчита на вашата функция, просто направете:

function isValidEmail($email){ 
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

Забележка: За други употреби (където имате нужда от Regex), остарялото семейство функции ereg (функции на POSIX Regex) трябва да бъде заменено от семейството preg (PCRE Regex функции). Има малко разлики, трябва да е достатъчно да прочетете ръководството.

Актуализация 1: Както е посочено от @binaryLV:

PHP 5.3.3 и 5.2.14 имаше бъг, свързан с FILTER_VALIDATE_EMAIL, което доведе до segfault при валидиране на големи стойности . Просто и безопасно решение за това е използването на strlen() преди filter_var(). Не съм сигурен за 5.3.4 final, но е писано, че някои версии 5.3.4-snapshot също са били засегнати.

Този бъг вече е коригиран.

Актуализация 2: Този метод разбира се ще потвърди bazmega@kapa като валиден имейл адрес, защото всъщност това е валиден имейл адрес. Но през повечето време в Интернет вие също искате имейл адресът да има TLD: [email protected]. Както е предложено в тази публикация в блог (връзка, публикувана от @Istiaque Ahmed), можете да увеличите filter_var() с регулярен израз който ще провери за съществуването на точка в частта на домейна (но няма да провери за валиден TLD):

function isValidEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) 
        && preg_match('/@.+\./', $email);
}

Както @Eliseo Ocampos посочи, този проблем само съществува преди PHP 5.3, в тази версия промениха регулярния израз и сега прави тази проверка, така че не е нужно да го правите.

person kapa    schedule 02.05.2011
comment
+1 Все пак може да споменете, че това е налично само в PHP 5.2.x и по-нови версии. :-) - person John Parker; 02.05.2011
comment
@middaparka: Тъй като OP получава отхвърлено съобщение за eregi, изглежда, че той използва PHP 5.3. Но да, важно е да го споменем (за другите)). - person Felix Kling; 02.05.2011
comment
@middaparka Благодаря, добавих го. Пропуснах го поради същата причина, която @Felix обясни, но да, други може да се интересуват. - person kapa; 02.05.2011
comment
PHP 5.3.3 и 5.2.14 имаха грешка (bugs.php.net/52929), свързана с FILTER_VALIDATE_EMAIL, което доведе до segfault при валидиране на големи стойности. Просто и безопасно решение за това е използването на strlen() преди filter_val(). Не съм сигурен за 5.3.4 final, но е писано, че някои версии 5.3.4-snapshot също са били засегнати. - person binaryLV; 02.05.2011
comment
@binaryLV, filter_val или filter_var? - person Istiaque Ahmed; 21.11.2012
comment
@bažmegakapa, имейл адресът трябва да бъде съкратен преди окончателното тестване, мисля. Процесът на валидиране в отговора не проверява наличието на точката в адреса. return filter_var($email, FILTER_VALIDATE_EMAIL) && preg_match('/@.+\./', $email); - тества наличието на точка в частта за име на домейн. Необходимо е също цяло числово преобразуване на върнатата стойност. Намерено тук:electrictoolbox.com/php-email-validation-filter-var-updated. - person Istiaque Ahmed; 21.11.2012
comment
@IstiaqueAhmed Полезен ресурс, ще актуализирам отговора си. Но имате недоразумение: върнатата стойност, разбира се, не трябва да бъде преобразувана в цяло число - блогърът прави това само, за да накара echo да показва правилно булевото значение. - person kapa; 21.11.2012
comment
@Istiaque Ahmed, вероятно печатна грешка от 18 месеца. - person binaryLV; 21.11.2012
comment
@kapa, всъщност не е нужно повече да проверявате за точка в частта за домейна. Вижте svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/filter/ - person Eliseo Ocampos; 10.12.2013
comment
Бих искал само да отбележа, че тази опция е архивирана с проверка на домейн/MX запис, можете да сте почти сигурни, че сървърът наистина може да обработи имейлите, които може да му изпратите. - person sg3s; 03.02.2014
comment
Трябва да върнете filter_var(...) !== false във вашата функция, за да върнете булева стойност (isValidEmail предполага булева върната стойност). - person stofl; 03.01.2016
comment
@stofl Прав си, също така съвпада по-добре с оригиналния подпис на OP. Редактирано. - person kapa; 04.01.2016
comment
Съжалявам, че изрових тази публикация, но този метод покрива ли също SQL инжектиране или подобни методи? - person Norman; 11.01.2016
comment
@Norman Този метод обхваща валидирането на имейл. Той проверява дали даден низ съдържа валиден имейл адрес. Не се споменава база данни, така че няма нищо общо с SQL инжекцията. - person kapa; 11.01.2016
comment
@kapa и към всички: Съжалявам, моя грешка. Някак си помислих, че този метод не работи с htmlspecialchars. Но грешката беше някъде другаде. Благодаря все пак за бързия отговор. - person Norman; 11.01.2016
comment
Това ще потвърди: $email = '"><script>alert(1);</script>"@test.com'; echo filter_var($email, FILTER_VALIDATE_EMAIL) - person sergio; 07.03.2016
comment
@sergio Невалиден имейл адрес ли е? - person kapa; 07.03.2016
comment
@kapa Може да инжектира XSS, но filter_var($email, FILTER_VALIDATE_EMAIL) ще го потвърди като валиден имейл, така че трябва да внимавате - person sergio; 07.03.2016
comment
@sergio Валидатор на имейл валидира имейли. Това му е работата. Не трябва да се интересува от XSS, SQL инжектиране и т.н. Това е различна част от вашето приложение. Когато извеждате HTML, трябва да вземете предпазни мерки срещу XSS. - person kapa; 07.03.2016
comment
Важно забележка - в последната актуализация променихте малко логиката, тъй като премахнахте !== false. - person Tomer Gal; 19.07.2017
comment
тази функция няма да работи за имейли с испански знаци като Sté[email protected] - person Coder anonymous; 26.12.2018

Вижте бележките на http://www.php.net/manual/en/function.ereg.php:

Note:

Считано от PHP 5.3.0, разширението за regex е отхвърлено в полза на PCRE разширението. Извикването на тази функция ще издаде известие E_DEPRECATED. Вижте списъка с разлики за помощ при преобразуване в PCRE .

Note:

preg_match(), който използва синтаксис на регулярен израз, съвместим с Perl , често е по-бърза алтернатива на ereg().

person Sean Kelleher    schedule 02.05.2011

Това е стара публикация, но ще споделя едно мое решение, защото никой не спомена тук нито един проблем преди.

Новият имейл адрес може да съдържа UTF-8 знаци или специални имена на домейни като .live, .news и т.н.

Също така намирам, че някои имейл адреси могат да бъдат на кирилица и във всички случаи стандартният регулярен израз или filter_var() ще се провалят.

Ето защо направих решение за това:

function valid_email($email) 
{
    if(is_array($email) || is_numeric($email) || is_bool($email) || is_float($email) || is_file($email) || is_dir($email) || is_int($email))
        return false;
    else
    {
        $email=trim(strtolower($email));
        if(filter_var($email, FILTER_VALIDATE_EMAIL)!==false) return $email;
        else
        {
            $pattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD';
            return (preg_match($pattern, $email) === 1) ? $email : false;
        }
    }
}

Тази функция работи перфектно за всички случаи и имейл формати.

person Ivijan Stefan Stipić    schedule 10.11.2016

Винаги използвам това:

function validEmail($email){
    // First, we check that there's one @ symbol, and that the lengths are right
    if (!preg_match("/^[^@]{1,64}@[^@]{1,255}$/", $email)) {
        // Email invalid because wrong number of characters in one section, or wrong number of @ symbols.
        return false;
    }
    // Split it into sections to make life easier
    $email_array = explode("@", $email);
    $local_array = explode(".", $email_array[0]);
    for ($i = 0; $i < sizeof($local_array); $i++) {
        if (!preg_match("/^(([A-Za-z0-9!#$%&'*+\/=?^_`{|}~-][A-Za-z0-9!#$%&'*+\/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$/", $local_array[$i])) {
            return false;
        }
    }
    if (!preg_match("/^\[?[0-9\.]+\]?$/", $email_array[1])) { // Check if domain is IP. If not, it should be valid domain name
        $domain_array = explode(".", $email_array[1]);
        if (sizeof($domain_array) < 2) {
            return false; // Not enough parts to domain
        }
        for ($i = 0; $i < sizeof($domain_array); $i++) {
            if (!preg_match("/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$/", $domain_array[$i])) {
                return false;
            }
        }
    }

    return true;
}
person unbreak    schedule 12.02.2016
comment
@unbreak Пробвах вашия код и открих, че ако подадете имейл като alex@., той винаги връща true, когато не е валиден имейл адрес. - person Subhajit; 11.04.2018

Използвайте:

var_dump(filter_var('[email protected]', FILTER_VALIDATE_EMAIL));
$validator = new EmailValidator();
$multipleValidations = new MultipleValidationWithAnd([
    new RFCValidation(),
    new DNSCheckValidation()
]);
$validator->isValid("[email protected]", $multipleValidations); //true
person Roman    schedule 20.03.2019

Потребителските данни са много важни за добрия разработчик, така че не питайте отново и отново за едни и същи данни, използвайте някаква логика, за да коригирате някои основни грешки в данните.

Преди потвърждаване на имейл: Първо трябва да премахнете всички незаконни знаци от имейла.

//This will Remove all illegal characters from email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);

след това потвърдете вашия имейл адрес с тази filter_var() функция.

filter_var($email, FILTER_VALIDATE_EMAIL)) // To Validate the email

За напр.

<?php
$email = "[email protected]";

// Remove all illegal characters from email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);

// Validate email
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo $email." is a valid email address";
} else {
    echo $email." is not a valid email address";
}
?>
person mufazmi    schedule 05.06.2020