7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

zodのemail()は日本語が入力できるよ

Last updated at Posted at 2023-02-26

こちらの記事で説明した「zodemail()で日本語が含まれる場合もバリデーションエラーとならない」はバージョン3.22.0以降でエラーとなるように変更されました。

const schema = z.string().email();
console.log(schema.parse("あいうえお@example.com"));

// ~ 3.21.4
// あいうえお@example.comと出力される

// 3.22.0 ~
/*
ZodError: [
  {
    "validation": "email",
    "code": "invalid_string",
    "message": "Invalid email",
    "path": []
  }
]
*/

そのため、以降の本文はzodのバージョンが3.21.4までの場合に当てはまることをご留意ください。

zodの小ネタです。

タイトルで全部言っちゃっているんですけどね:neutral_face:
ここで言う日本語とはひらがな、カタカナ、漢字を指しています。

今回利用しているバージョンは以下です。

"zod": "^3.20.6"

zodのemail()を検証する

ではどういった場合にemail()でエラーとなるのか検証します。

以下test@example.comという値はメールアドレスとして適切と判定されました。

const schema = z.string().email();
console.log(schema.parse("test@example.com")); // test@example.comと出力

testという値はメールアドレスとして不適切と判定されました。
これはメールアドレスとして用いる値ではないので想定通りです。

const schema = z.string().email();
console.log(schema.parse("test")); // errorがthrowされる

/*
Error: [
{
"validation": "email",
"code": "invalid_string",
"message": "Invalid email",
"path": []
}
]
*/

日本語入力した場合でも弾いてくれるのかどうか確認します(なおタイトルでお察し)。
あいうえお@example.comという値はメールアドレスとして適切と判定され...るんかい!

const schema = z.string().email();
console.log(schema.parse("あいうえお@example.com")); // あいうえお@example.comと出力

これは想定外だなと思いつつも、Laravelのemailバリデーションも場合によっては日本語入力できたな...ということを思い出しました:rolling_eyes:

zodのemailバリデーションルールを確認してみる

zodのemailバリデーションルールを確認します。

ソースコードを見るとメールアドレスバリデーションは正規表現を用いているようです。また、その正規表現はいくらか変遷があったようですが、現行は以下のようです。

const emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|([^-]([a-zA-Z0-9-]*\.)+[a-zA-Z]{2,}))$/;

たしかに @以降は入力可能なものを半角英数字.に限定していることが見てとれますが、 @以前は入力してはいけない記号類と入力していはいけないパターンが指定されているだけのようです。

メールアドレスのバリデーションを正規表現だけで完璧にやるのは難しいので、zodでは最低限x@x.xxの形式であることを担保しているのかな、という推測をしています。

とは言え、メールアドレス(@以前)にも日本語の入力は許可せず、半角英数字記号のみを許可したいです。どうすればよいでしょうか?

email()に正規表現を組み合わせて半角英数字記号のみ許可する

自分はUnicodeの正規表現1を用いて、半角英数字、ならびに主要な(よく使う)記号類のみを許可するようにしています。

const pattern = /^[\u0021-\u007e]+$/u; // 半角英数字記号のみ
const schema = z.string().email().regex(pattern); // 上記正規表現をルールに追加
console.log(schema.parse('あいうえお@example.com'));

/*
Error: [
{
"validation": "regex",
"code": "invalid_string",
"message": "Invalid",
"path": []
}
]

*/

エラーのvalidationを見ると、あいうえお@example.comregexのルールに抵触してくれたようです:grinning:

入力したものがx@x.xxの形式であることは.email()の方で担保してくれるため、.regex()の方では入力値が半角英数字記号であるかどうかをチェックするだけで良さそうです(ありがたい)。

バリデーションルールを提供してくれるライブラリやフレームワークにはメールアドレスのバリデーションで日本語が入力できてしまう場合もあるので、気をつけねばという話でした。

  1. このUnicodeの範囲にどういったものが含まれるのかは以下サイトを参照しました。
    https://tools.m-bsys.com/ex/unicode_table.php

7
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?