メールアドレスの正規表現検証:実際に機能するパターン
メール検証は最も一般的な正規表現の使用例の一つであり、最も誤解されているものの一つでもあります。メールアドレスの RFC 5321 仕様は驚くほど複雑で、単一の正規表現で完全に検証することはできません。しかし、実際のメールアドレスの 99.9% をカバーする実用的なパターンは実現可能であり、有用です。
シンプルなパターン(ほとんどの場合に十分)
ほとんどのアプリケーションでは、このパターンが十分に機能します:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
マッチ対象:1つ以上の許可された文字、続いて @、続いて少なくとも1つのドットと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 Tester でテストしてください。
完全な正規表現検証が不可能な理由
メール仕様(RFC 5321/5322)は、技術的には有効ですが実際にはほとんど使用されない構造を許可しています:
"john..doe"@example.com // 連続するドットを含むクォートされたローカルパート
user@[192.168.1.1] // ドメインとしての IP アドレス
"very.(),:;<>[]".VERY."very@\ "very".unusual"@strange.example.com
すべての RFC 有効なアドレスを処理する正規表現は数千文字の長さになり、それでもすべてのエッジケースをカバーできない可能性があります。実用的なアプローチ:基本的なフォーマット検証にはシンプルな正規表現を使用し、確認メールを送信してメールが実際に存在するかを検証します。
パターンの分解
ローカルパート(@ の前)
[a-zA-Z0-9._%+-]+
- 英字(大文字と小文字)
- 数字
- ドット、アンダースコア、パーセント、プラス、ハイフン
- 1文字以上
よくあるミス:
- 先頭または末尾のドットを許可する(技術的に無効)
- 連続するドットを許可する(クォートなしでは技術的に無効)
- 制限が厳しすぎる(Gmail エイリアスで使用される
+などの有効な文字をブロック)
ドメインパート(@ の後)
[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
- 英数字、ドット、ハイフン
- 少なくとも1つのドット
- 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,}$
この最小限のパターンは単純に次を保証します:スペースなし、@ が1つ、@ の後に少なくとも1つのドット、2文字以上の TLD。これは意図的に寛容で、珍しいが有効なアドレスを拒否することなく、明らかに間違った入力をキャッチします。
言語別の実装
JavaScript
function isValidEmail(email) {
// 基本的な正規表現チェック
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
if (!regex.test(email)) return false;
// 追加チェック
if (email.length > 254) return false; // RFC 5321 の制限
const [local] = email.split('@');
if (local.length > 64) return false; // RFC 5321 の制限
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
正規表現を超えて:適切なメール検証
正規表現は防御の最前線にすぎません。完全な検証戦略:
- フォーマットチェック(正規表現):明らかに無効なフォーマットを拒否
- 長さチェック:ローカルパート ≤ 64文字、合計 ≤ 254文字
- DNS チェック:ドメインに MX レコードがあるか検証
- 使い捨てメール検出:必要に応じて一時的なメールサービスをブロック
- 確認メール:メールを真に検証する唯一の方法 — メッセージを送信してユーザーが受信するか確認
// DNS MX レコードチェック (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は国際化メールで有効
その他の正規表現パターンについては、正規表現チートシート をご覧ください。
FAQ
メールの正規表現検証はクライアント側とサーバー側のどちらで行うべきですか?
両方です。クライアント側の検証は即時フィードバックを提供します(より良い UX)。サーバー側の検証はセキュリティのために必須です(クライアントチェックはバイパスできます)。クライアント側の検証だけに頼ってはいけません。
なぜ一部のウェブサイトが有効なメールアドレスを拒否するのですか?
過度に制限的な正規表現パターンが一般的な原因です。+(Gmail エイリアス)、長い TLD(.technology)、またはサブドメインを持つアドレスは、不適切な検証により拒否されることがよくあります。ウェブサイトを運営する場合は、寛容な正規表現を使用し、代わりに確認メールで検証してください。
関連リソース
- Regex Tester — メール検証パターンをリアルタイムでテスト
- 正規表現チートシート — 完全な正規表現パターンリファレンス
- JSON Schema バリデーション — JSON で format: email を使ったメールフィールドの検証