ホームページ バックエンド開発 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)

PHPでの安全なパスワードハッシュ(例:Password_hash、password_verify)を説明します。 MD5またはSHA1を使用してみませんか? PHPでの安全なパスワードハッシュ(例:Password_hash、password_verify)を説明します。 MD5またはSHA1を使用してみませんか? Apr 17, 2025 am 12:06 AM

PHPでは、Password_hashとpassword_verify関数を使用して安全なパスワードハッシュを実装する必要があり、MD5またはSHA1を使用しないでください。 1)password_hashセキュリティを強化するために、塩値を含むハッシュを生成します。 2)password_verifyハッシュ値を比較して、パスワードを確認し、セキュリティを確保します。 3)MD5とSHA1は脆弱であり、塩の値が不足しており、最新のパスワードセキュリティには適していません。

PHPとPython:2つの一般的なプログラミング言語を比較します PHPとPython:2つの一般的なプログラミング言語を比較します Apr 14, 2025 am 12:13 AM

PHPとPythonにはそれぞれ独自の利点があり、プロジェクトの要件に従って選択します。 1.PHPは、特にWebサイトの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンス、機械学習、人工知能に適しており、簡潔な構文を備えており、初心者に適しています。

アクション中のPHP:実際の例とアプリケーション アクション中のPHP:実際の例とアプリケーション Apr 14, 2025 am 12:19 AM

PHPは、電子商取引、コンテンツ管理システム、API開発で広く使用されています。 1)eコマース:ショッピングカート機能と支払い処理に使用。 2)コンテンツ管理システム:動的コンテンツの生成とユーザー管理に使用されます。 3)API開発:RESTFUL API開発とAPIセキュリティに使用されます。パフォーマンスの最適化とベストプラクティスを通じて、PHPアプリケーションの効率と保守性が向上します。

スカラータイプ、リターンタイプ、ユニオンタイプ、ヌル可能なタイプなど、PHPタイプのヒントはどのように機能しますか? スカラータイプ、リターンタイプ、ユニオンタイプ、ヌル可能なタイプなど、PHPタイプのヒントはどのように機能しますか? Apr 17, 2025 am 12:25 AM

PHPタイプは、コードの品質と読みやすさを向上させるためのプロンプトがあります。 1)スカラータイプのヒント:php7.0であるため、基本データ型は、int、floatなどの関数パラメーターで指定できます。 3)ユニオンタイプのプロンプト:PHP8.0であるため、関数パラメーターまたは戻り値で複数のタイプを指定することができます。 4)Nullable Typeプロンプト:null値を含めることができ、null値を返す可能性のある機能を処理できます。

PHPの永続的な関連性:それはまだ生きていますか? PHPの永続的な関連性:それはまだ生きていますか? Apr 14, 2025 am 12:12 AM

PHPは依然として動的であり、現代のプログラミングの分野で重要な位置を占めています。 1)PHPのシンプルさと強力なコミュニティサポートにより、Web開発で広く使用されています。 2)その柔軟性と安定性により、Webフォーム、データベース操作、ファイル処理の処理において顕著になります。 3)PHPは、初心者や経験豊富な開発者に適した、常に進化し、最適化しています。

PHPおよびPython:さまざまなパラダイムが説明されています PHPおよびPython:さまざまなパラダイムが説明されています Apr 18, 2025 am 12:26 AM

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPおよびPython:コードの例と比較 PHPおよびPython:コードの例と比較 Apr 15, 2025 am 12:07 AM

PHPとPythonには独自の利点と短所があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1.PHPは、大規模なWebアプリケーションの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンスと機械学習の分野を支配しています。

PHPでのSQL注入をどのように防止しますか? (準備された声明、PDO) PHPでのSQL注入をどのように防止しますか? (準備された声明、PDO) Apr 15, 2025 am 12:15 AM

PHPで前処理ステートメントとPDOを使用すると、SQL注入攻撃を効果的に防ぐことができます。 1)PDOを使用してデータベースに接続し、エラーモードを設定します。 2)準備方法を使用して前処理ステートメントを作成し、プレースホルダーを使用してデータを渡し、メソッドを実行します。 3)結果のクエリを処理し、コードのセキュリティとパフォーマンスを確保します。

See all articles