Development•
2025-06-15
•7 min
•alltools.one Team
RegexEmailValidationJavaScriptDevelopment
用 Regex 驗證電子郵件:真正有效的模式
電子郵件驗證是最常見的 regex 使用案例之一——也是最被誤解的之一。RFC 5321 對電子郵件地址的規範出人意料地複雜,沒有任何單一 regex 能完全驗證它。但能涵蓋 99.9% 真實電子郵件地址的實用模式既可行又實用。
簡單模式(夠用了)
對大多數應用來說,以下模式就能勝任:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
它匹配什麼:一個或多個允許的字元,接著 @,再接著至少有一個點號和 2 個以上字母 TLD 的網域。
JavaScript:
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
emailRegex.test('user@example.com'); // true
emailRegex.test('user@.com'); // false
使用我們的 Regex 測試器來測試這個模式。
為什麼完美的 Regex 驗證不可能
電子郵件規範(RFC 5321/5322)允許一些在技術上有效但幾乎不會在實務中使用的結構:
"john..doe"@example.com // Quoted local part with consecutive dots
user@[192.168.1.1] // IP address as domain
"very.(),:;<>[]".VERY."very@\ "very".unusual"@strange.example.com
能處理所有 RFC 有效地址的 regex 長達數千個字元,而且仍可能無法涵蓋每種邊緣情況。實用的做法是:使用簡單的 regex 進行基本格式驗證,然後透過發送確認信來驗證電子郵件地址是否真正存在。
模式分解
本地部分(@ 之前)
[a-zA-Z0-9._%+-]+
- 字母(大小寫)
- 數字
- 點號、底線、百分號、加號、連字號
- 一個或多個字元
常見錯誤:
- 允許點號出現在開頭或結尾(技術上無效)
- 允許連續的點號(未加引號時技術上無效)
- 過於嚴格(阻擋了 Gmail 別名使用的
+等有效字元)
網域部分(@ 之後)
[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
- 英數字元、點號、連字號
- 至少一個點號
- 2 個以上字母的 TLD
常見錯誤:
- 將 TLD 長度限制為 3-4 個字元(
.museum、.photography是存在的) - 不允許網域名稱中的連字號
- 無法處理子網域(
user@mail.example.co.uk)
更好的模式
HTML5 標準
HTML5 規範為 <input type="email"> 定義了以下模式:
^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
這個模式在本地部分較為寬鬆,但對網域標籤長度更為嚴格。
實用推薦模式
^[^\s@]+@[^\s@]+\.[^\s@]{2,}$
這個最精簡的模式只確保:沒有空格、一個 @、@ 之後至少一個點號、2 個以上字元的 TLD。它故意設計得較為寬鬆——攔截明顯錯誤的輸入,而不會拒絕不常見但有效的地址。
各語言實作
JavaScript
function isValidEmail(email) {
// Basic regex check
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
if (!regex.test(email)) return false;
// Additional checks
if (email.length > 254) return false; // RFC 5321 limit
const [local] = email.split('@');
if (local.length > 64) return false; // RFC 5321 limit
return true;
}
Python
import re
def is_valid_email(email: str) -> bool:
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(pattern, email):
return False
if len(email) > 254:
return False
local, domain = email.rsplit('@', 1)
if len(local) > 64:
return False
return True
超越 Regex:正確的電子郵件驗證
Regex 只是第一道防線。完整的驗證策略:
- 格式檢查(regex):拒絕明顯無效的格式
- 長度檢查:本地部分 ≤ 64 字元,總長度 ≤ 254 字元
- DNS 檢查:驗證網域是否有 MX 記錄
- 拋棄式信箱偵測:如需要,阻擋臨時電子郵件服務
- 確認信:真正驗證電子郵件的唯一方法——寄出一封信並確認使用者收到了
// DNS MX record check (Node.js)
const dns = require('dns');
const [, domain] = email.split('@');
dns.resolveMx(domain, (err, addresses) => {
if (err || !addresses.length) {
console.log('Domain has no email server');
}
});
應避免的常見錯誤
- 過於嚴格的模式:阻擋
user+tag@gmail.com(加號定址)或user@subdomain.example.com - 大小寫敏感性:根據 RFC,電子郵件本地部分可以區分大小寫,但實務上應視為不區分大小寫
- 去除空白:驗證前務必去除空白——
" user@example.com "應該通過驗證 - 國際化網域:
.münchen和用户@例え.jp在國際化電子郵件中是有效的
更多 regex 模式,請參閱我們的 Regex 速查表。
常見問題
應該在客戶端還是伺服器端用 regex 驗證電子郵件?
兩者都要。客戶端驗證提供即時回饋(更好的使用者體驗)。伺服器端驗證是安全性的必要措施(客戶端檢查可以被繞過)。永遠不要只依賴客戶端驗證。
為什麼有些網站會拒絕我有效的電子郵件地址?
通常是過於嚴格的 regex 模式造成的。含有 +(Gmail 別名)、長 TLD(.technology)或子網域的地址經常被拙劣的驗證所拒絕。如果你維護一個網站,請使用寬鬆的 regex,並透過確認信來驗證。
相關資源
- Regex 測試器 — 即時測試電子郵件驗證模式
- Regex 速查表 — 完整的 regex 模式參考
- JSON Schema 驗證 — 在 JSON 中用 format: email 驗證電子郵件欄位