Help us understand the problem. What is going on with this article?

angularでdjangoのemail validationを実装しようとして詰まった話

環境

angular 8系
django 2.2系


状況

angularの Validators.email どう見てもメールアドレスじゃないの受け付けてるな、、、弱すぎない?djangoでバックエンドからメール送信する時挙動どうなるんだ、、、エラー吐かれてメール送信行われないと困るんだが、、、

せや!djangoのEmailValidation から正規表現移植したれ!


試行

djangoのバリデーション

validators.py
# '@'以前
user_regex = _lazy_re_compile(
        r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z"  # dot-atom
        r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)',  # quoted-string
        re.IGNORECASE)
# '@'以降
domain_regex = _lazy_re_compile(
        # max length for domain name labels is 63 characters per RFC 1034
        r'((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63}(?<!-))\Z',
        re.IGNORECASE)

うーんなんかいろいろ分けられとるなあ、、、くっつけるか!

regex.py
regex = r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^'([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63})(?<!-))\Z"

これをangular側に移植して、、、こう!

component.ts
validators.patterns(/(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^'([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63})(?<!-))\Z/)

動作かくに、あれ?????全体が動いてない、、、トップページから、、、フォーム以外の部分も、、、(エラーの詳細は後日記載)


何が悪いんやろうか、とりあえず正規表現をここでチェックするか、、、
(?<!-) あーなるほどなるほどlook behindの正規表現js使えないんですか、、、
(look behindの説明はこちら)
chromeなら動くよ!と言う報告もあるけどそれはいかんでしょ(真顔)IE?なんですかそれは
(?<!-): 末尾が-でない


結果

結局以下のような実装を行いました。valueChangedEvent拾ってきてendsWithを行いFormControl.setError()しても良かったのですが、コードの再利用性を意識しました。


validators.ts
export class CustomEmailValidator {
  // prettier-ignore
  // tslint:disable-next-line: max-line-length
  static djangoEmailRegex = new RegExp(/(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^'([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63})$/);
  static djangoEmailValidator(control: FormControl): ValidationErrors | null {
    if (control.value && !control.value.endsWith('-') && CustomEmailValidator.djangoEmailRegex.test(control.value.toUpperCase())) {
      return null;
    }
    return { email: true };
  }
}


まさかpythonとjsの正規表現の仕様の違いとは、、、てかfirefoxつかってなかったらこのエラー気がつかなかったのでは、、、
firefoxとchromeの挙動の違い、時々あるので気をつけましょう(ngZone.run()周りとか)

何か指摘、聞きたいことがあればコメントまでどーぞ


参考リンク一覧
- django EmailValidator
- regex101.com
- 正規表現の先読み・後読み(look ahead、look behind)を活用しよう

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした