ホームページ バックエンド開発 PHPチュートリアル PHP は RFC 準拠の電子メール アドレス検証を実装します

PHP は RFC 準拠の電子メール アドレス検証を実装します

Jul 25, 2016 am 08:56 AM

  1. /*

  2. Copyright 2009 Dominic Sayers
  3. (dominic_sayers@hotmail.com)
  4. (http://www.dominicsayers.com)

  5. このソース ファイルは Common Public Attribution License バージョンの対象です1.0 (CPAL) ライセンス。

  6. ライセンス条項は、ワールドワイドウェブ (http://www.opensource.org/licenses/cpal_1.0) から入手できます
  7. */
  8. function is_email ($email, $checkDNS = false) {
  9. // チェックしてください$email は有効なアドレスです
  10. // (http://tools.ietf.org/html/rfc3696)
  11. // (http://tools.ietf.org/html/rfc5322#section-3.4.1)
  12. / / (http://tools.ietf.org/html/rfc5321#section-4.1.3)
  13. // (http://tools.ietf.org/html/rfc4291#section-2.2)
  14. // (http: //tools.ietf.org/html/rfc1123#section-2.1)
  15. // 現在の電子メール アドレスは、
  16. から区切られた「ローカル部分」で構成されます。 // 「ドメイン部分」 (完全修飾ドメイン名) は、アットマーク ("@")。
  17. // (http://tools.ietf.org/html/rfc3696#section-3)
  18. $index = strrpos($email,'@');

  19. if ($index === false) は false を返します。 // アットマークはありません

  20. if ($index === 0) return false; // ローカル部分はありません
  21. if ($index > 64) return false; // ローカル部分が長すぎます

  22. $localPart = substr($email, 0, $index);

  23. $domain = substr($email, $index + 1);
  24. $domainLength = strlen($domain);
  25. if ($domainLength === 0) は false を返します。 // ドメイン部分はありません
  26. if ($domainLength > 255) return false; // ドメイン部分が長すぎます

  27. // RFC に準拠しているかどうかローカル部分を確認してみましょう...

  28. //
  29. // ピリオド (".") は...表示される場合がありますが、
  30. // ローカル部分の開始または終了に使用することはできません。または複数の連続するピリオドが表示されます。
  31. // (http://tools.ietf.org/html/rfc3696#section-3)
  32. if (preg_match('/^\.|\.\.|\.$/', $localPart) > 0 ) false を返します。 // ドットが間違った場所にあります

  33. //

  34. // アットマーク ("@")、バックスラッシュ、二重引用符、カンマ、または角括弧以外の ASCII グラフィック (印刷) 文字は、
  35. // 引用符なしで使用できます。 除外される文字のリスト
  36. // が出現する場合は、引用符で囲む必要があります
  37. // (http://tools.ietf.org/html/rfc3696#section-3)
  38. if (preg_match('/^" (?:.)*"$/', $localPart) > 0) {
  39. // ローカル部分は引用符で囲まれた文字列
  40. if (preg_match('/(?:.)+[^\\]"(?: .)+/', $localPart) > return false // 引用符付き文字列内のエスケープされていない引用符
  41. } else {
  42. if (preg_match('/[ @\[\]\\",]/', $ localPart) > 0)
  43. // 除外された文字がすべてエスケープされていることを確認します
  44. $stripped = preg_replace('/\\[ @\[\]\\",]/', '', $localPart);
  45. if (preg_match ('/[ @\[\]\\",]/', $tripped) > 0) false を返します。 // 引用符で囲まれていない除外文字
  46. }

  47. // 次に、ドメイン部分を確認してみましょう...

  48. // ドメイン名は角かっこ内の IP アドレスに置き換えることもできます

  49. // (http://tools.ietf.org/html/rfc3696#section-3)
  50. // (http://tools.ietf. org/html/rfc5321#section-4.1.3)
  51. // (http://tools.ietf.org/html/rfc4291#section-2.2)
  52. if (preg_match('/^\[(.)+]$ /', $domain) === 1) {
  53. // これはアドレスリテラルです
  54. $addressLiteral = substr($domain, 1, $domainLength - 2);
  55. $matchesIP = array();
  56. // アドレスリテラルの末尾から IPv4 部分を抽出します (存在する場合)
  57. if (preg_match('/\b(?:(?:25[0-5]|2[0-4][ 0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[ 01]?[0-9][0-9]?)$/', $addressLiteral, $matchesIP) > 0) {
  58. $index = strrpos($addressLiteral, $matchesIP[0]);
  59. if ($index === 0) {
  60. // 有効な IPv4 アドレス以外には何もないので...
  61. return true;
  62. }else {
  63. // 混合アドレス (IPv6 + IPv4) での試行であると仮定します
  64. if ($addressLiteral[$index - 1] !== ':') return false; // IPv4 アドレスの前の文字は ':' である必要があります
  65. if (substr($addressLiteral, 0, 5) !== 'IPv6:') return false; // RFC5321 セクション 4.1.3

  66. $IPv6 = substr($addressLiteral, 5, ($index ===7) ? 2 : $index - 6);

  67. $groupMax = 6;
  68. }
  69. } else {
  70. // 純粋な IPv6 での試みである必要があります
  71. if (substr($addressLiteral, 0, 5) !== 'IPv6:') return false; // RFC5321 セクション 4.1.3
  72. $IPv6 = substr($addressLiteral, 5);
  73. $groupMax = 8;
  74. }

  75. $groupCount = preg_match_all('/^[0-9a-fA-F]{0,4}|\:[0-9a-fA-F]{0,4}|(.)/', $IPv6, $ IP に一致します);

  76. $index = strpos($IPv6,'::');

  77. if ($index === false) {

  78. // 正確に正しい数のグループが必要です
  79. if ($groupCount !== $groupMax) return false; // RFC5321 セクション 4.1.3
  80. } else {
  81. if ($index !== strrpos($IPv6,'::')) return false; // 複数の '::'
  82. $groupMax = ($index === 0 || $index === (strlen($IPv6) - 2)) ? $groupMax : $groupMax - 1;
  83. if ($groupCount > $groupMax) は false を返します。 // アドレス内の IPv6 グループが多すぎます
  84. }

  85. // 一致しない文字をチェック

  86. array_multisort($matchesIP[1], SORT_DESC);
  87. if ($matchesIP[1][0] !== '') は false を返します。 // アドレスに不正な文字があります

  88. // これは有効な IPv6 アドレスなので...

  89. return true;
  90. } else {
  91. // これはドメイン名です...

  92. // 正当なインターネット ホスト名の構文は RFC-952 で指定されました

  93. // ホスト名の構文の 1 つの側面が変更されました:
  94. // 最初の文字の制限が緩和され、
  95. // 文字または桁。
  96. // (http://tools.ietf.org/html/rfc1123#section-2.1)
  97. //
  98. // NB RFC 1123 は RFC 1035 を更新しますが、これは現時点では RFC 1035 を読んでも明らかではありません。
  99. //
  100. // 電子メールや Web などの最も一般的なアプリケーションでは、通常、エスケープされた文字列は許可されません
  101. // (http://tools.ietf.org/html/rfc3696#section-2)
  102. //
  103. // 文字アルファベット文字、数字、ハイフンのセット以外をドメイン名に含めてはなりません
  104. // SMTP クライアントまたはサーバーのラベル
  105. // (http://tools.ietf.org/html/rfc5321#section-4.1.2)
  106. //
  107. // RFC5321 では、SMTP 目的でドメイン名の末尾のドットを使用することを禁止しています
  108. // (http://tools.ietf.org/html/rfc5321#section-4.1.2)
  109. $matches = array ();
  110. $groupCount = preg_match_all('/(?:[0-9a-zA-Z][0-9a-zA-Z-]{0,61}[0-9a-zA-Z]|[a-zA- Z])(?:\.|$)|(.)/', $domain, $matches);
  111. $level = count($matches[0]);

  112. if ($level == 1) は false を返します。 // メールホストを TLD にすることはできません

  113. $TLD = $matches[0][$level - 1];

  114. if (substr($TLD, strlen($TLD) - 1, 1) === '.') は false を返します。 // TLD はドットで終わることはできません
  115. if (preg_match('/^[0-9]+$/', $TLD) > 0) return false; // TLD をすべて数値にすることはできません

  116. // 一致しない文字をチェック

  117. array_multisort($matches[1], SORT_DESC);
  118. if ($matches[1][0] !== '') は false を返します。 // ドメイン内の不正な文字、または 63 文字を超えるラベル

  119. // DNSをチェックしますか?

  120. if ($checkDNS && function_exists('checkdnsrr')) {
  121. if (!(checkdnsrr($domain, 'A') || checkdnsrr($domain, 'MX'))) {
  122. false を返します。 // ドメインは実際には存在しません
  123. }
  124. }

  125. // 他の要素をすべて削除し、残ったものが真実でなければなりません。

  126. // (シャーロック ホームズ、The Sign of Four)
  127. return true;
  128. }
  129. }

  130. 関数unitTest ($email, $reason = '') {

  131. $expected = ($reason === '') ?真/偽;
  132. $valid = is_email($email);
  133. $not = ($valid) ? '' : ' ない';
  134. $unexpected = ($valid !== $expected) ? 「 これは予想外でした!」 : '';
  135. $reason = ($reason === '') ? "" : " 理由: $reason";
  136. return "アドレス $email は $無効です。$unexpected$reason
    n";
  137. }

  138. // 電子メール検証テスト ケース (Dominic Sayers、2009 年 1 月)

  139. // 有効なアドレス
  140. echo UnitTest('first.last@example.com');
  141. echounitTest('1234567890123456789012345678901234567890123456789012345678901234@example.com');
  142. echounitTest('"最初と最後"@example.com');
  143. echounitTest('"first\"last"@example.com'); // これが有効かどうか完全にはわかりません
  144. echounitTest('first\@last@example.com');
  145. echounitTest(' "first@last"@example.com');
  146. echounitTest('first\\last@example.com'); // これは一重引用符の文字列でもエスケープされるため、「first\last」をテストしていることに注意してください。 @example.com
  147. echo UnitTest('first.last@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x 23456789.x23456789.x23456789.x23456789.
  148. x23456789.x23456789.x23456789.x23456789。 x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x2345');
  149. echounitTest('first.last@[12.34.56.78]'); first.last@[IPv6:::12.34 .56.78]');
  150. エコーユニットテスト('first.last@[IPv6:1111:2222:3333::4444:12.34.56.78]');
  151. エコーユニットテスト('first.last@[IPv6:1111:2222: 3333:4444:5555:6666:12.34.56.78]');
  152. echounitTest('first.last@[IPv6:::1111:2222:3333:4444:5555:6666]'); .last@[IPv6:1111:2222:3333::4444:5555:6666]');
  153. echounitTest('first.last@[IPv6:1111:2222:3333:4444:5555:6666::]');
  154. echounitTest('first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]');
  155. echounitTest('first.last@x23456789012345678901234567890123456789012345678901234567890123.example.com');
  156. echounitTest('first.last@1xample.com');
  157. echounitTest('first.last@123.example.com');

  158. // 無効なアドレス

  159. echounitTest('first.last', "No @");
  160. echounitTest('@example.com', "ローカル部分がありません");
  161. echo UnitTest('12345678901234567890123456789012345678901234567890123456789012345@example.com', "64 文字を超えるローカル部分");
  162. echounitTest('.first.last@example.com', "ローカル部分はドットで始まります");
  163. echounitTest('first.last.@example.com', "ローカル部分はドットで終わります");
  164. echounitTest('first..last@example.com', "ローカル部分に連続したドットがあります");
  165. echo UnitTest('"first"last"@example.com', "ローカル部分にはエスケープされていない除外文字が含まれています");
  166. echo UnitTest('first\\@last@example.com', "ローカル部分にはエスケープされていない除外文字が含まれています" );
  167. echo unitTest('first.last@', "ドメインなし"); 9.x23456789.x23456789.x23456789。 x23456789.x23456789.x23456789.
  168. x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x2345678 9.x23456789.x23456789.x23456', "ドメインが 255 文字を超えています");
  169. echounitTest('first.last@[ .12.34.56.78]', "IPv4 アドレスの前に付けられる文字は ':' のみです");
  170. echo UnitTest('first.last@[12.34.56.789]', "IPv4 として解釈できないため、IPv6 タグは欠落しています");
  171. echo UnitTest('first.last@[::12.34.56.78]', "IPv6 タグが欠落しています");
  172. echo UnitTest('first.last@[IPv5:::12.34.56.78]', "IPv6 タグが間違っています");
  173. echounitTest('first.last@[IPv6:1111:2222:3333::4444:5555:12.34.56.78]', "IPv6 グループが多すぎます (最大 4 つ)"); echounitTest('first.last@[IPv6:1111:2222:3333:4444:5555:12.34.56.78]', "IPv6 グループが不足しています");
  174. echounitTest('first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:12.34.56.78]', "IPv6 グループが多すぎます (最大 6 つ)");
  175. echounitTest('first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777]', "IPv6 グループが不足しています");
  176. echounitTest('first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]', "IPv6 グループが多すぎます (最大 8 つ)");
  177. echounitTest('first.last@[IPv6:1111:2222::3333::4444:5555:6666]', "「::」が多すぎます (なしまたは 1 つ)");
  178. echounitTest('first.last@[IPv6:1111:2222:3333::4444:5555:6666:7777]', "IPv6 グループが多すぎます (最大 6 つ)");
  179. echounitTest('first.last@[IPv6:1111:2222:333x::4444:5555]', "x は IPv6 アドレスでは無効です");
  180. echounitTest('first.last@[IPv6:1111:2222:33333::4444:5555]', "33333 は IPv6 アドレスの有効なグループではありません");
  181. echounitTest('first.last@example.123', "TLD をすべて数字にすることはできません");
  182. echounitTest('first.last@com', "メールホストは 2 番目以下のレベルである必要があります");
  183. echounitTest('first.last@-xample.com', "ラベルをハイフンで始めることはできません");
  184. echounitTest('first.last@exampl-.com', "ラベルはハイフンで終わることはできません");
  185. echo UnitTest('first.last@x234567890123456789012345678901234567890123456789012345678901234.example.com', "ラベルは 63 オクテットを超えることはできません");

  186. // RFC3696 のテスト ケース (2004 年 2 月、http://tools.ietf.org/html/rfc3696#section-3)

  187. echo UnitTest('Abc\@def@example.com');
  188. echounitTest('Fred\ Bloggs@example.com');
  189. echounitTest('Joe.\\Blow@example.com');
  190. echounitTest('"Abc@def"@example.com');
  191. echounitTest('"Fred Bloggs"@example.com');
  192. echounitTest('user+mailbox@example.com');
  193. echounitTest('customer/Department=shipping@example.com');
  194. echounitTest('$A12345@example.com');
  195. echounitTest('!def!xyz%abc@example.com');
  196. echo UnitTest('_somename@example.com');

  197. // Doug Lovell のテスト ケース (LinuxJournal、2007 年 6 月、http://www.linuxjournal.com/article/9585)

  198. echounitTest("dclo@us.ibm.com");
  199. echounitTest("abc\@def@example.com");
  200. echounitTest("abc\\@example.com");
  201. echounitTest("Fred\ Bloggs@example.com");
  202. echounitTest("Joe.\\Blow@example.com");
  203. echounitTest(""Abc@def"@example.com");
  204. echounitTest(""Fred Bloggs"@example.com");
  205. echounitTest("customer/Department=shipping@example.com");
  206. echounitTest("$A12345@example.com");
  207. echounitTest("!def!xyz%abc@example.com");
  208. echounitTest("_somename@example.com");
  209. echounitTest("user+mailbox@example.com");
  210. echounitTest("peter.piper@example.com");
  211. echo UnitTest("Doug\ \"Ace\"\ Lovell@example.com");
  212. echounitTest(""Doug \"Ace\" L."@example.com");
  213. echo UnitTest("abc@def@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  214. echounitTest("abc\\@def@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  215. echounitTest("abc\@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  216. echounitTest("@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  217. echounitTest("doug@", "Doug Lovell はこれは失敗するはずだと言います");
  218. echo UnitTest(""qu@example.com", "Doug Lovell 氏はこれは失敗するはずだと言います");
  219. echo UnitTest("ote"@example.com", "Doug Lovell 氏はこれは失敗するはずだと言います");
  220. echounitTest(".dot@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  221. echo UnitTest("dot.@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  222. echo UnitTest("two..dot@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  223. echounitTest(""Doug "Ace" L."@example.com", "Doug Lovell はこれは失敗するはずと言っています");
  224. echounitTest("Doug\ \"Ace\"\ L\.@example.com", "Doug Lovell はこれは失敗するはずと言っています");
  225. echounitTest("hello world@example.com", "Doug Lovell 氏は、これは失敗するはずだと言っています");
  226. echounitTest("gatsby@f.sc.ot.t.f.i.tzg.era.l.d.", "Doug Lovell はこれは失敗するはずと言っています");
  227. ?>

复制帽


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

セッションのハイジャックはどのように機能し、どのようにPHPでそれを軽減できますか? セッションのハイジャックはどのように機能し、どのようにPHPでそれを軽減できますか? Apr 06, 2025 am 12:02 AM

セッションハイジャックは、次の手順で達成できます。1。セッションIDを取得します。2。セッションIDを使用します。3。セッションをアクティブに保ちます。 PHPでのセッションハイジャックを防ぐための方法には次のものが含まれます。1。セッション_regenerate_id()関数を使用して、セッションIDを再生します。2。データベースを介してストアセッションデータを3。

確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 Apr 03, 2025 am 12:04 AM

PHP開発における固体原理の適用には、次のものが含まれます。1。単一責任原則(SRP):各クラスは1つの機能のみを担当します。 2。オープンおよびクローズ原理(OCP):変更は、変更ではなく拡張によって達成されます。 3。Lischの代替原則(LSP):サブクラスは、プログラムの精度に影響を与えることなく、基本クラスを置き換えることができます。 4。インターフェイス分離原理(ISP):依存関係や未使用の方法を避けるために、細粒インターフェイスを使用します。 5。依存関係の反転原理(DIP):高レベルのモジュールと低レベルのモジュールは抽象化に依存し、依存関係噴射を通じて実装されます。

システムの再起動後にUnixSocketの権限を自動的に設定する方法は? システムの再起動後にUnixSocketの権限を自動的に設定する方法は? Mar 31, 2025 pm 11:54 PM

システムが再起動した後、UnixSocketの権限を自動的に設定する方法。システムが再起動するたびに、UnixSocketの許可を変更するために次のコマンドを実行する必要があります:sudo ...

phpstormでCLIモードをデバッグする方法は? phpstormでCLIモードをデバッグする方法は? Apr 01, 2025 pm 02:57 PM

phpstormでCLIモードをデバッグする方法は? PHPStormで開発するときは、PHPをコマンドラインインターフェイス(CLI)モードでデバッグする必要がある場合があります。

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? Apr 01, 2025 pm 03:12 PM

PHP開発でPHPのCurlライブラリを使用してJSONデータを送信すると、外部APIと対話する必要があることがよくあります。一般的な方法の1つは、Curlライブラリを使用して投稿を送信することです。

See all articles