narita-lab’s blog

成田ラボ 〜テクノロジーと雑学の観察日記〜

AIと共同で“詐欺メールを潰すプログラム”を設計してみる Day1

最近、Yahooメールを久しぶりに確認したら受信箱が地獄になっていた。

Amazon、楽天、Apple、PayPay、ETC、えきねっと、三井住友カード…。
名だたる企業を名乗るメールがズラッと並んでいる。

もちろん、そのほとんどが詐欺メールだ。

しかも最近の詐欺メールは妙に小賢しい。

「楽天カード」ではフィルタに引っかかるからなのか、

「楽 天 カ ー ド」
「Amazon」
「A m a z o n」

みたいに、わざわざスペースや全角文字を混ぜて送ってくる。

いやもう、そこまでして人を騙したいのかと。

一方で、普段使っているGmail側はかなり平和だった。
おそらくGoogle側の迷惑メールフィルタが強力なのだろう。

ただ、Yahooメール側はどうにも突破されることが多い。

それならもう、自分で対策ツールを作った方が早いのでは?

…という訳で今回は、ChatGPTと相談しながら「詐欺メールを検出・整理するPythonツール」の設計を始めてみることにした。

まだ今回は“設計段階”なので、実際にメールを削除したりする訳ではない。
どちらかと言えば、

「どういう条件なら迷惑メール判定できそうか?」

を考える回になる。

とりあえず現時点で分かっているのは、

“楽 天 カ ー ド”を許してはいけない。

ということだけである。

 

Yahooメールに詐欺メールが多すぎる

そもそも、なぜこんなことを考え始めたのか。

理由は単純で、Yahooメールの受信箱に詐欺メールが普通に入ってくるからだ。

迷惑メールフォルダに入るならまだいい。
でも、普通に受信箱にいる。

しかも内容がだいたい同じ。

「アカウントが停止されます」
「本人確認をしてください」
「支払い方法を更新してください」
「不正利用を検知しました」
「利用制限のお知らせ」

この辺の文言が、もうテンプレのように飛んでくる。

Amazonを名乗るもの。
楽天カードを名乗るもの。
Apple IDを名乗るもの。
ETC利用照会サービスを名乗るもの。

こちらとしては、そもそもYahooメールをそれらのサービスに登録していない。

つまり、Yahoo宛にAmazonや楽天やAppleを名乗るメールが来た時点で、かなり怪しい。

特に私の場合、主要サービスの登録先はGoogleアカウントやAOLメールに移している。
楽天カードも持っていないし、楽天銀行も解約済み。

となると、Yahooメールに届く楽天系メールは、ほぼ迷惑メール判定でいい。

もちろん、これをそのまま他人向けツールにするのは危険だ。
楽天カードを普通に使っている人もいるし、AmazonをYahooメールで登録している人もいる。

だから、自分用なら強気の判定でいい。
でも公開するなら、ユーザーごとに「使っているサービス」を設定できるようにしないといけない。

この辺りが、今回の設計でまず大事になりそうだ。

 

最初は「AIに全部判定させればいいのでは?」と思った

最近はAIの性能もかなり上がっている。

だったら、

「このメールは詐欺っぽいですか?」

をAIに丸投げすれば良いのでは?

…と最初は思った。

例えば、

  • 件名
  • 差出人
  • 本文
  • URL
  • 宛名

この辺をAIに渡して、

「危険度を0〜100で判定してください」

みたいな事をやれば、かなり賢い判定ができそうに見える。

ただ、考えれば考えるほど、AIだけに依存する設計は微妙だった。

まず、メール本文には個人情報が入る。

氏名、住所、注文番号、認証コード…。
そういう物を外部AIに送るのは、普通に怖い。

次に、コスト問題。

ローカルLLMならともかく、クラウドAIを使う場合はAPI料金が発生する可能性がある。
迷惑メールを掃除するたびに課金されるのは、なんか違う。

さらに、AIは“賢いけど不安定”だ。

明らかに怪しいメールを見抜ける時もあれば、逆に普通のメールを危険判定してしまう可能性もある。

特に怖いのが、

「本物のAmazonメールを消してしまう」

みたいな誤判定だ。

これをやると普通に事故になる。

なので、現時点ではAIは“補助”くらいで考えることにした。

メインはあくまでルールベース。

  • 本文にメールアドレスが含まれている
  • 「○○様」ではなく「メールアドレス様」になっている
  • 未登録サービスを名乗っている
  • URLドメインが怪しい
  • 「本人確認」「利用制限」など緊急ワードがある

こういう条件をスコア化して判定した方が、シンプルで事故も少なそうだ。

 

実際に考えている判定方法

今回の設計で、一番「これ強そうだな」と思ったのが、

“ユーザーが使っていないサービスを名乗るメール”

を強く疑う方法だ。

例えば私の場合、

  • 楽天カード → 持っていない
  • 楽天銀行 → 解約済み
  • Apple → Yahooでは登録していない
  • Amazon → Yahooでは登録していない

という状態になっている。

つまり、Yahooメール宛に届いた時点でかなり怪しい。

さらに最近の詐欺メールは、本文中にメールアドレスをそのまま書いてくることが多い。

例えば、

hogehoge0912@test.co.jp 様」

みたいな感じだ。

本物の企業メールだと、登録名や本名が入ることが多い。
逆に詐欺メールは本名を知らないので、とりあえずメールアドレスを突っ込んでくる。

ここはかなり重要な判定材料になりそうだった。

なので現時点では、

  • 本文に自分のメールアドレスが含まれている
  • Amazonや楽天などの主要サービス名が含まれている
  • 「本人確認」「利用制限」などの緊急ワードがある

この辺を組み合わせて、スコア式で判定しようと思っている。

しかも厄介なのが、詐欺メール側もフィルタ回避をしてくることだ。

「楽天カード」ではなく、

「楽 天 カ ー ド」

みたいに、わざとスペースを入れてくる。

なので、判定前に文字列を正規化する必要がある。

全角半角を統一したり、スペースを除去したりして、

「楽 天 カ ー ド」

「楽天カード」

として扱えるようにする訳だ。

この辺りはAIというより、昔ながらのルールベース処理の方が強そうだった。

 

公開するなら“削除”より“隔離”が安全そう

ただ、このツールをもし外部公開するなら話は変わってくる。

自分専用なら、

「楽天?使ってないから全部迷惑メールでいいや」

が成立する。

でも、他人はそうではない。

普通に楽天カードを使っている人もいれば、Yahooメールをメインアドレスにしている人もいる。

つまり、“自分基準のルール”をそのまま他人に適用すると危険だ。

なので、もし公開するなら、

「即削除」

ではなく、

「迷惑メール候補フォルダへ移動」

くらいが現実的だと思った。

一旦隔離して、ユーザー側で確認してもらう。

これなら誤判定しても復旧できる。

あと、ユーザーごとに設定できる仕組みは必須になりそうだ。

例えば、

  • Amazon → 使用中
  • 楽天 → 未使用
  • PayPay → 使用中
  • Apple → 未使用

みたいにチェックを入れてもらう。

そして、

“未登録サービスを名乗るメール”

を強めに警戒する。

これならユーザーごとに最適化できる。

さらに、最初からAIをガッツリ使うより、

  • ルールベース判定
  • スコア加算
  • 隔離
  • 最終確認だけユーザー

くらいの方が、実運用では安定しそうだ。

迷惑メール対策で一番怖いのは、

“本物を消してしまうこと”

なので、まずは「賢さ」より「事故らない」を優先したい。

 

Day1時点の結論 ― AIより先に、まずはシンプルに組む

今回色々考えてみて思ったのは、

“AIを使う前に、普通のルールベースだけでもかなり戦えそう”

ということだった。

もちろんAIを使えば、もっと賢い判定はできると思う。

ただ、その代わりに、

  • 個人情報
  • コスト
  • 誤判定
  • API管理
  • 通信
  • 処理速度

みたいな問題も増えてくる。

一方で、

  • 未登録サービス
  • メールアドレス+様
  • 怪しいURL
  • 緊急ワード
  • 正規化処理

この辺だけでも、Yahooメールに届く典型的な詐欺メールにはかなり強そうだった。

特に今回、

「楽 天 カ ー ド」

みたいな回避表現を見て、

“あぁ、こいつらフィルタとの戦いをしてるんだな”

というのを強く感じた。

ならこちらも、スペース除去や文字正規化で対抗すればいい。

結局のところ、派手なAIを使うより、

“地味だけど事故らない設計”

の方が重要なのかもしれない。

という訳で、Day1はここまで。

次回は実際にPythonからYahooメールへIMAP接続し、受信箱のメールを取得できるかを試してみる予定だ。

ちゃんと接続できるのか。
そもそもPython側でどこまで扱いやすいのか。

まずはそこから検証していこうと思う。