【#PowerApps Tip's】正規表現と定義済みパターン（弱点回避もあるヨ）

メールアドレスの入力を求めたいコトって多いですよね？
今回は、問題になりがちなメールアドレスに関する「入力チェック」の話題です。

結論から言うと「Power Apps で事前に準備されているチェック機構では、Office 365 のメールアドレス禁則事項に抵触した値が検知できない」のです。その問題を解決する方法とあわせてお送りいたします。

# メアドのチェックといえば正規表現
C# や Java 等の開発言語経験がある方はピンときたかもしれませんね。“一定のルール”に従って「文字列が特定パターンでかくあるべき」と定義されているメールアドレスなどのチェックを実施する、といえば「正規表現」を利用するコトが多いです。

[正規表現](https://ja.wikipedia.org/wiki/正規表現) 出典: フリー百科事典 ウィキペディア（Wikipedia）

所謂「ISMatch」ってヤツですね。

# Power Apps の IsMatch
勿論、Power Apps にも検証対象が正規表現に合致するか否かを判定してくれる「IsMatch」関数が存在します。

[Power Apps の IsMatch、Match、および MatchAll 関数](docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-ismatch)

しかも、ご丁寧に『事前定義済みのパターン』が準備されています。長ったらしくて解読し辛い正規表現をワザワザ自分で作成しなくても、準備されている定義済みのパターンを利用することで簡単にチェックが可能、というコトです。

[事前定義済みのパターン](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-ismatch#predefined-patterns)

メールアドレスの場合「Email」という定義済みのパターンを利用すれば問題なさそうです。

```
IsMatch(比較するテキスト, Match.Email)
```

| 一致列挙型 | 説明                                                          | 正規表現                |
|-------|-------------------------------------------------------------|---------------------|
| Email | ピリオド (".") が付いたドメイン名と "at" 記号 ("@") が含まれている電子メール アドレスと一致します | .+\@.+\\.[^\\.]{2,} |

# 定義済みのパターン Match.Email の問題点
では、その Match.Email を利用すれば全てがオールオッケーなのか？というと、そうではありません。Match.Email 定義済みパターンでは“Office 365 で作成できないメールアドレス”が検知できません。Office 365（Exchange Online）のルールとしてNGのメールアドレスが検出できない、ということです。

Office 365 でNGなルールは下記になります。RFC 準拠に基づくようです。（RFC ＝ IETF (インターネット技術標準化委員会) により公開されているインターネットの技術に関する標準仕様文書）

[Office 365 で特殊文字を含むユーザー名を作成しようとすると、"無効なユーザー名" が表示される](https://docs.microsoft.com/ja-jp/office/troubleshoot/error-messages/username-contains-special-character)

よく問題になるのがピリオド（.）が連続していたり、アドレスの先頭、ないしアットマークの直前に登場するメールアドレスです。これは、特定の携帯キャリアでは利用可能なのですが、[RFC に準拠していない](https://ja.wikipedia.org/wiki/メールアドレス)のです。

# 回避方法
回避方法は簡単です。より RFC に準拠した正規表現を利用すればよいのです。なお ***『可能な限り準拠した正規表現』*** が限界らしいです。調べた限りだと、完全に RFC 準拠したメールアドレスチェック用の正規表現は非常に難しいらしい・・・

そうですヨ、正規表現って難しいですよね。なので、ググ・・・Bingちゃいましょう。当方が参考にしたサイト様はこちら。

[可能な限りRFCに準拠したEメールアドレス検証用正規表現](https://qiita.com/shimataro999/items/b24bf4def5c4c8fe8ae9)

```
^([\w!#$%&'*+\-\/=?^`{|}~]+(\.[\w!#$%&'*+\-\/=?^`{|}~]+)*|"([\w!#$%&'*+\-\/=?^`{|}~. ()<>\[\]:;@,]|\\[\\"])+")@(([a-zA-Z\d\-]+\.)+[a-zA-Z]+|\[(\d{1,3}(\.\d{1,3}){3}|IPv6:[\da-fA-F]{0,4}(:[\da-fA-F]{0,4}){1,5}(:\d{1,3}(\.\d{1,3}){3}|(:[\da-fA-F]{0,4}){0,2}))\])$
```

残念ながら、上記のままでは Power Apps の IsMatch 関数に利用できません。ダブルコーテーション（”）が文字列を表す記号として利用されているので、エスケープ（”””／ダブルコーテーション3つ）してやらないとダメなんです。ただ、それだと非常に可読性が落ちますよね（そもそも正規表現ムズカシーネー）。て、コトで、当方は下記のような対策を実施しています。

ダブルコーテーション ＝ Char(34) なのですね。ソレで文字列連結するのです。

```
^([\w!#$%&'*+\-\/=?^`{|}~]+(\.[\w!#$%&'*+\-\/=?^`{|}~]+)*|" & Char(34) &"([\w!#$%&'*+\-\/=?^`{|}~. ()<>\[\]:;@,]|\\[\\" & Char(34) &"])+" & Char(34) &")@(([a-zA-Z\d\-]+\.)+[a-zA-Z]+|\[(\d{1,3}(\.\d{1,3}){3}|IPv6:[\da-fA-F]{0,4}(:[\da-fA-F]{0,4}){1,5}(:\d{1,3}(\.\d{1,3}){3}|(:[\da-fA-F]{0,4}){0,2}))\])$
```

# 動作イメージ
<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/PowerApps?src=hash&amp;ref_src=twsrc%5Etfw">#PowerApps</a> IsMatch &quot;Predefined patterns&quot; vs custom &quot;regular expression&quot; <a href="https://t.co/LuI39WWxT6">pic.twitter.com/LuI39WWxT6</a></p>&mdash; やま (Yama) (@yamad365) <a href="https://twitter.com/yamad365/status/1251510425855750144?ref_src=twsrc%5Etfw">April 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

上段が Match.Email 定義済みパターン。
下段が、IsMatch関数に、上記の”なるべくRFC準拠した正規表現 ※Power Apps対応版”です。

下段は、ピリオドが先頭やアットマーク直前にあっても False になってますよね？

# まとめ
- Power Apps の正規表現チェックは IsMatch 関数
- Match.Email のような事前定義済みパターンが準備されている
  - とはいえ、目的に合致しない場合もあるから要注意
  - ちゃんと定義済みパターンの正規表現はチェックすべき
- 事前定義済みパターンが適用不可の場合は、自分で正規表現を書く必要がある！
- Office 365 のメールアドレスは RFC準拠らしい

メールアドレスって、結構厳しいルールがあるんですよね。そして、利用しているサービスによってチョッとずつルールが違う…。ルールが異なるのは、ホントは良くないコトなんですが、利用者の立場では従わざるを得ないコトも多々あります。そんな時は知恵と工夫で乗り越えましょう。

それでは、皆さま、素晴らしい Power Platform Life を！