JavaScript Tips | 文字列ユーティリティ:検証 - メールアドレス判定

JavaScript JavaScript
スポンサーリンク

「メールアドレス判定」はどこまでやるべきか

最初に一番大事なことを言います。
メールアドレス判定は「完璧」を目指さないほうがいいです。

RFC に完全準拠しようとすると、正規表現が怪物みたいになりますし、
現場で本当に欲しいのは「明らかにおかしいものを弾く」くらいの精度です。

なので、業務ユーティリティとしては、

「パッと見てメールアドレスっぽいか」
「致命的におかしい形式を弾けるか」

このあたりを狙うのがちょうどいいラインです。


まずは「メールアドレスのざっくり構造」を押さえる

メールアドレスは、ざっくりこういう形をしています。

ユーザー名部分 @ ドメイン部分

例としては、

taro@example.com
hanako.sato+news@gmail.com

などですね。

ざっくりチェックしたいポイントはこのあたりです。

@ が1個だけあること。
@ の前後に、最低1文字ずつあること。
ドメイン部分に . が含まれていること(example.com など)。

これだけでも、「明らかにおかしいもの」はかなり弾けます。


シンプルなメールアドレス判定ユーティリティ

実務でよく使うレベルの正規表現

まずは、業務で使いやすい「ほどよい」正規表現からいきます。

function isEmail(value) {
  if (value == null) return false;

  const s = String(value).trim();

  if (s === "") return false;

  const re =
    /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

  return re.test(s);
}
JavaScript

一つずつ噛み砕きます。

null / undefined が来ても落ちないようにしている。
String(value).trim() で文字列化+前後の空白を削っている。
空文字は false(メールアドレスではない)にしている。
正規表現は /^[^\s@]+@[^\s@]+\.[^\s@]+$/ という、かなりシンプルなものにしている。

この正規表現の意味はこうです。

^ … 文字列の先頭
[^\s@]+ … 空白と @ 以外の文字が1文字以上(ユーザー名部分)
@@ が1個
[^\s@]+ … 空白と @ 以外の文字が1文字以上(ドメインの前半)
\. … ドット1個
[^\s@]+ … 空白と @ 以外の文字が1文字以上(ドメインの後半)
$ … 文字列の末尾

つまり、「@ が1個あって、その前後にそれなりの文字があって、ドメインに . が含まれている」ものだけを許可します。

動きの確認

isEmail("taro@example.com");        // true
isEmail("hanako.sato+news@gmail.com"); // true
isEmail("invalid@@example.com");    // false
isEmail("no-at-mark.example.com");  // false
isEmail("taro@localhost");          // false(ドメインに . がない)
isEmail("  taro@example.com  ");    // true(前後の空白は無視)
JavaScript

「完璧ではないけれど、明らかにおかしいものは弾けている」感じがつかめると思います。


どこまで厳しくするかを決める

ローカル用途か、外部ユーザー向けか

例えば、社内ツールで「社内メールアドレスだけ」を扱うなら、
もっと絞った判定にしても構いません。

function isCompanyEmail(value) {
  if (!isEmail(value)) return false;
  return String(value).trim().toLowerCase().endsWith("@example.co.jp");
}
JavaScript

これなら、

taro@example.co.jp は OK
taro@gmail.com は NG

といった判定ができます。

逆に、一般ユーザー向けサービスなら、
「とりあえず形式だけざっくり見て、あとは確認メールを送って検証する」
という設計にするのが現実的です。

「正規表現だけで完璧に判定しようとしない」

メールアドレスが本当に存在するかどうかは、
正規表現では絶対に分かりません。

最終的には、

そのアドレスにメールを送る。
ユーザーに確認リンクを踏んでもらう。

といった「実際の通信」を伴う確認が必要です。

だからこそ、ユーティリティの役割は

「明らかにおかしい形式を弾く」
「入力ミスっぽいものを早めに気づかせる」

くらいにとどめておくのが、バランスの良い落としどころです。


業務での具体的な使いどころ

フロントエンドの入力チェック

フォームの入力チェックで、
「送信ボタンを押す前に、明らかにおかしいメールアドレスを教えてあげる」用途です。

const email = emailInput.value;

if (!isEmail(email)) {
  showError("メールアドレスの形式が正しくありません。");
}
JavaScript

ここでのポイントは、

「形式が正しいからといって、必ず存在するとは限らない」
「形式が少し変でも、実際には有効なアドレスの可能性もある」

ということを理解したうえで、
「ユーザーの入力ミスを減らすためのガイド」として使うことです。

バックエンド側の軽いバリデーション

API でメールアドレスを受け取るときにも、
最低限の形式チェックをしておくと、
明らかにおかしいデータが DB に入るのを防げます。

function validateEmailOrThrow(email) {
  if (!isEmail(email)) {
    throw new Error("Invalid email format");
  }
}
JavaScript

ただし、ここでも「存在確認」は別のレイヤー(確認メールなど)でやる、という意識が大事です。


設計として意識してほしいこと

「メールアドレス判定ユーティリティ」を一箇所にまとめる

プロジェクトのあちこちで、

/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
JavaScript

のような正規表現がコピペされ始めると、
どこか一箇所だけ微妙に違うルールになったり、
後から仕様変更するときに地獄を見ます。

なので、

export function isEmail(value) { ... }
export function isCompanyEmail(value) { ... }
JavaScript

のように、「メールアドレス判定は必ずここを通す」というユーティリティを一つ決めておくと、
コードの一貫性と保守性が一気に上がります。

「判定の責任範囲」を決める

このユーティリティは、

「形式が“それっぽい”かどうか」を見るだけなのか。
「自社ドメインかどうか」まで見るのか。

など、「どこまで責任を持つか」を決めておくと、
関数名や使い方もブレなくなります。

例えば、

isEmail … 形式だけざっくりチェック
isCompanyEmail … 形式+ドメインチェック

のように分けておくと、
呼び出し側も意図を読み取りやすくなります。


ちょっとだけ手を動かしてみる

コンソールで、次のあたりを試してみてください。

isEmail("taro@example.com");
isEmail("hanako.sato+news@gmail.com");
isEmail("invalid@@example.com");
isEmail("no-at-mark.example.com");
isEmail("taro@localhost");
JavaScript

「どこからが true で、どこからが false になるか」を体で感じてみてください。
そのうえで、自分のプロジェクトに

export function isEmail(value) { ... }
JavaScript

を一つ置いて、
「メールアドレスっぽいかどうかを見たいときは、必ずここを通す」
というルールにしてみてください。

それができた瞬間、あなたのバリデーションは
「その場しのぎの正規表現の寄せ集め」から
「意図を持って設計された検証ユーティリティ」に、一段レベルアップします。

タイトルとURLをコピーしました