จะตรวจสอบอีเมลใน PHP ได้อย่างไร?


120

ฉันจะตรวจสอบค่าที่ป้อนได้อย่างไรว่าเป็นที่อยู่อีเมลที่ถูกต้องโดยใช้ 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; 
     }    
} 

แต่แสดงข้อผิดพลาดที่เลิกใช้แล้ว ฉันจะแก้ไขปัญหานี้ได้อย่างไร โปรดช่วยฉันด้วย


3
มีการให้คำตอบที่ถูกต้องแล้ว แต่เกี่ยวกับปัญหาที่เลิกใช้ : การใช้นิพจน์ทั่วไป POSIX (ซึ่งeregiเป็นฟังก์ชันของ) เลิกใช้แล้ว ใช้PCREแทน
Felix Kling

3
อย่างไรก็ตาม regex ของคุณผิดทั้งหมด ที่อยู่ที่ถูกต้องทั้งหมดจะถูกทำเครื่องหมายว่าไม่ถูกต้องโดยฟังก์ชันของคุณ การกรองที่อยู่อีเมลด้วย regex เป็นฝันร้าย
Artefact2

คุณควรใช้มาตรฐานRFC 822และนี่คือบทความที่ดีในการแยกวิเคราะห์ที่อยู่อีเมลใน PHPที่อธิบาย
kta

คำตอบ:


275

คุณสามารถใช้filter_var()ฟังก์ชันนี้ซึ่งให้ตัวเลือกการตรวจสอบความถูกต้องและการฆ่าเชื้อที่มีประโยชน์มากมาย

filter_var($email, FILTER_VALIDATE_EMAIL)

หากคุณไม่ต้องการเปลี่ยนรหัสที่อาศัยฟังก์ชันของคุณให้ทำดังนี้

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

หมายเหตุ : สำหรับการใช้งานอื่น ๆ (ที่คุณต้องการ Regex) eregตระกูลฟังก์ชันที่เลิกใช้แล้ว(POSIX Regex Functions) ควรถูกแทนที่ด้วยpregตระกูล ( PCRE Regex Functions ) มีความแตกต่างเล็กน้อยการอ่านคู่มือควรเพียงพอ

อัปเดต 1 : ตามที่@binaryLVชี้ให้เห็น:

PHP 5.3.3 และ 5.2.14 มีจุดบกพร่องที่เกี่ยวข้องกับ FILTER_VALIDATE_EMAIL ซึ่งส่งผลให้เกิดการผิดพลาดเมื่อตรวจสอบค่าขนาดใหญ่ วิธีแก้ปัญหาที่ง่ายและปลอดภัยสำหรับการนี้คือการใช้ก่อนstrlen() filter_var()ฉันไม่แน่ใจเกี่ยวกับ 5.3.4 ขั้นสุดท้าย แต่มีเขียนว่าเวอร์ชัน 5.3.4-snapshot บางเวอร์ชันก็ได้รับผลกระทบเช่นกัน

ข้อบกพร่องนี้ได้รับการแก้ไขแล้ว

อัปเดต 2 : แน่นอนว่าวิธีนี้จะตรวจสอบbazmega@kapaว่าเป็นที่อยู่อีเมลที่ถูกต้องเนื่องจากเป็นที่อยู่อีเมลที่ถูกต้อง แต่ส่วนมากของเวลาบนอินเทอร์เน็ตที่คุณยังต้องการที่อยู่อีเมลที่จะมี TLD bazmega@kapa.comนี้: ตามที่แนะนำในบล็อกโพสต์นี้(ลิงก์ที่โพสต์โดย@Istiaque Ahmed ) คุณสามารถเพิ่มfilter_var()regex ที่จะตรวจสอบการมีอยู่ของจุดในส่วนของโดเมน (จะไม่ตรวจสอบTLD ที่ถูกต้อง ):

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

ตามที่@Eliseo Ocamposชี้ให้เห็นปัญหานี้เกิดขึ้นก่อน PHP 5.3 เท่านั้นในเวอร์ชันนั้นพวกเขาเปลี่ยน regexและตอนนี้ก็ทำการตรวจสอบแล้วดังนั้นคุณไม่จำเป็นต้องทำ


4
+1 ที่กล่าวมาคุณอาจต้องการพูดถึงว่ามีให้ใช้งานใน PHP 5.2.x ขึ้นไปเท่านั้น :-)
John Parker

5
@middaparka: เนื่องจาก OP ได้รับข้อความเลิกใช้งานeregiดูเหมือนว่าเขากำลังใช้ PHP 5.3 แต่ใช่เป็นเรื่องสำคัญที่จะต้องพูดถึงเรื่องนี้ (สำหรับคนอื่น ๆ ))
Felix Kling

8
PHP 5.3.3 และ 5.2.14 มีจุดบกพร่อง ( bugs.php.net/52929 ) ที่เกี่ยวข้องFILTER_VALIDATE_EMAILซึ่งส่งผลให้เกิดการผิดพลาดเมื่อตรวจสอบค่าขนาดใหญ่ วิธีแก้ปัญหาที่ง่ายและปลอดภัยสำหรับการนี้คือการใช้ก่อนstrlen() filter_val()ฉันไม่แน่ใจเกี่ยวกับ 5.3.4 ขั้นสุดท้าย แต่มีเขียนว่าเวอร์ชัน 5.3.4-snapshot บางเวอร์ชันก็ได้รับผลกระทบเช่นกัน
binaryLV

1
@binaryLV filter_valหรือfilter_var?
Istiaque Ahmed

3
@kapa จริงๆแล้วคุณไม่จำเป็นต้องตรวจสอบจุดในส่วนโดเมนอีกต่อไป ดูsvn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/filter/…
Eliseo Ocampos

9

ดูบันทึกที่http://www.php.net/manual/en/function.ereg.php :

Note:

ในฐานะของ PHP 5.3.0 ส่วนขยาย regex จะเลิกในความโปรดปรานของการขยาย PCRE การเรียกใช้ฟังก์ชันนี้จะมีการแจ้งเตือน E_DEPRECATED ดูรายการความแตกต่าง สำหรับความช่วยเหลือในการแปลงเป็น PCRE

Note:

preg_match ()ซึ่งใช้ไวยากรณ์นิพจน์ทั่วไปที่เข้ากันได้กับ Perl มักเป็นทางเลือกที่เร็วกว่า ereg ()


7

นี่เป็นโพสต์เก่า แต่ฉันจะแบ่งปันวิธีแก้ปัญหาของฉันเพราะไม่มีใครพูดถึงที่นี่ปัญหาหนึ่งมาก่อน

ที่อยู่อีเมลใหม่สามารถมีอักขระ UTF-8 หรือชื่อโดเมนพิเศษเช่น.live, .newsฯลฯ

นอกจากนี้ฉันพบว่าที่อยู่อีเมลบางส่วนสามารถอยู่ใน Cyrilic และในทุกกรณี regex มาตรฐานหรือ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;
        }
    }
}

ฟังก์ชันนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับทุกกรณีและรูปแบบอีเมล


3

ฉันมักจะใช้สิ่งนี้:

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;
}

1
@unbreak ฉันลองใช้รหัสของคุณแล้วและพบว่าถ้าคุณส่งอีเมลalex@.แล้วมันจะส่งคืนจริงเสมอซึ่งไม่ใช่ที่อยู่อีเมลที่ถูกต้อง
Subhajit


1

ใช้:

var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
$validator = new EmailValidator();
$multipleValidations = new MultipleValidationWithAnd([
    new RFCValidation(),
    new DNSCheckValidation()
]);
$validator->isValid("example@example.com", $multipleValidations); //true

0

ข้อมูลผู้ใช้เป็นสิ่งสำคัญมากสำหรับนักพัฒนาซอฟต์แวร์ที่ดีดังนั้นอย่าถามซ้ำแล้วซ้ำอีกสำหรับข้อมูลเดิมใช้ตรรกะบางอย่างเพื่อแก้ไขข้อผิดพลาดพื้นฐานในข้อมูล

ก่อนการตรวจสอบความถูกต้องของอีเมล:ขั้นแรกคุณต้องลบอักขระที่ผิดกฎหมายทั้งหมดออกจากอีเมล

//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 = "john.doe@example.com";

// 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";
}
?>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.