首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 電子郵件地址驗證完整指南(正則進化史、filter_var、RFC 5322、DNS 檢查)

     編輯:PHP 相關知識

驗證層級與選擇

層級方法準確度效能適用場景
1. 基礎格式filter_var($email, FILTER_VALIDATE_EMAIL)高(符合 RFC 5322 子集)極快大多數表單驗證、註冊、登入
2. 嚴格 RFC 5322完整正則(超過 6000 字元)最高慢郵件系統核心、標準相容性測試
3. DNS MX 記錄checkdnsrr($domain, 'MX')驗證域名可收信網路延遲減少垃圾帳號、API 整合前檢查
4. SMTP 連線驗證RCPT TO 指令驗證信箱真實存在極慢、易被封鎖高價值線索清洗、專業郵件服務

推薦:PHP 內建 filter_var(PHP 5.2+)

function isValidEmail(string $email): bool {
    // 長度限制(RFC 5321: local-part <= 64, domain <= 255, total <= 254)
    if (strlen($email) > 254) return false;
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

// 測試
var_dump(isValidEmail('user@example.com'));        // true
var_dump(isValidEmail('user.name+tag@example.co.uk')); // true
var_dump(isValidEmail('user@126,com'));            // false (逗號非法)
var_dump(isValidEmail('user@[IPv6:2001:db8::1]')); // true (IP 字面域名)

進階:自訂正則(支援國際化域名 IDN、嚴格長度)


function isValidEmailStrict(string $email): bool {
    // 1. 基礎長度
    if (strlen($email) > 254) return false;

    // 2. 分離 local-part @ domain
    $parts = explode('@', $email, 2);
    if (count($parts) !== 2) return false;
    [$local, $domain] = $parts;

    // 3. local-part 長度 (RFC 5321)
    if (strlen($local) > 64) return false;

    // 4. domain 長度
    if (strlen($domain) > 255) return false;

    // 5. domain 格式:支援 IDN (xn--...)、IP 字面、標準域名
    // 簡化版:標準域名 + IDN 已轉換為 ASCII
    $domainRegex = '/^(?=.{1,255}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i';
    if (!preg_match($domainRegex, $domain)) {
        // 嘗試 IDN 轉換
        if (function_exists('idn_to_ascii')) {
            $domainAscii = idn_to_ascii($domain, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
            if ($domainAscii && preg_match($domainRegex, $domainAscii)) return true;
        }
        return false;
    }

    // 6. local-part 格式(簡化:允許字母數字、點、底線、減號、加號,不以點開頭結尾、無連續點)
    $localRegex = '/^[a-z0-9_+-]+(?:\.[a-z0-9_+-]+)*$/i';
    return preg_match($localRegex, $local) === 1;
}

DNS MX 記錄檢查(非同步化建議)


function hasMxRecord(string $domain): bool {
    // 移除可選的 [IPv6:...] 包裝
    $domain = trim($domain, '[]');
    if (str_starts_with($domain, 'IPv6:')) $domain = substr($domain, 5);
    return checkdnsrr($domain, 'MX');
}

// 非同步批次檢查(Swoole/RoadRunner/ReactPHP)
// 生產環境請勿在 HTTP 請求中同步呼叫 checkdnsrr,會阻塞 1-5 秒

常見誤區與避坑

誤區正確認知
用簡單正則 /^.+@.+\..+$/通過 a@b.c 但擋不住 user@domain (無 TLD)、user@-domain.com、user@domain..com
擋住 + 標籤(user+tag@gmail.com)合法且實用(Gmail、Outlook 支援),請勿過濾
要求 TLD 至少 2 字元新頂級域可為 1 字元(理論),但實務極少見,{2,} 通常可接受
不支援國際化域名(中文域名)用 idn_to_ascii() 轉換後驗證
同步 checkdnsrr 在高併發 API會耗盡 PHP-FPM 進程,改用非同步佇列或快取結果

結語

**95% 場景直接用 filter_var($email, FILTER_VALIDATE_EMAIL) 即可**,內建處理 RFC 5322 複雜規則、效能最佳。需嚴格域名可收信驗證時,加上非同步 checkdnsrr。切勿自寫簡單正則,邊界情況極多且難以維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved