メールアドレス抽出の正規表現

■ Procmailで使えるメールアドレス正規表現

From、Return-Path などからメールアドレスを抽出する正規表現、意外と難しいです。
結論から言えば、正規表現一発ではできません。

例えば、こんな反則的なメールアドレスが実際にあったりして

Return-Path: <a-b-c._.d=efg@hogehoge.com>

例えば、メールアドレスらしきものが2つ含まれていたりして

From: "I-am@office.work" <a-b-c._.d=efg@hogehoge.com>

こんなやつも引っ掛けるには以下のようにします。

echo 変数 | grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1

すると、こう展開されます。

echo '"I-am@office.work" <a-b-c._.d=efg@hogehoge.com>' \
| grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1

結果
a-b-c._.d=efg@hogehoge.com

ProcmailでFromとReturn-Pathの違いからスパムを弾くレシピ

スパムメールでは From はよく詐称されます。
From はあてにならないので From でブラックリスト判定するのは意味ないです。
やるなら Return-Path でブラックリスト判定のほうがマシ。
でも、ブラックリストを追加するのも疲れるしイタチごっこです。
もっとうまい方法がないか・・・

■ ProcmailでFromとReturn-Pathの違いからスパムを弾くレシピ

From と Return-Path が違ったらもう削除してしまうなら以下


# ヘッダからメールアドレス抽出して変数へ

:0
* ^Return-Path:\/.*
RETUERN_PATH=`echo "$MATCH"|grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1`

:0
* ^From:\/.*
ORIGINAL_FROM=`echo "$MATCH"|grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1`

:0
* ^To:\/.*
ORIGINAL_TO=`echo "$MATCH"|grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1`

# スパム判定

# From と Return-Path が違う
:0
*! $ORIGINAL_FROM ?? $ $RETUERN_PATH
/dev/null

でもこれだと、いろんなものが弾かれてしまいすぎ。
いやいや、それはちょっと厳しすぎると思う場合、
From と To が同じときスパム確定にするなら以下


ヘッダからメールアドレス抽出する部分は上記と同じ
・・・

# From と To が同じ (スパム確定) - 削除
:0
* $ORIGINAL_FROM ?? $ $ORIGINAL_TO
/dev/null

# From と Return-Path が違う - 目印を付けるだけ
:0fw
*! $ORIGINAL_FROM ?? $ $RETUERN_PATH
| formail -i "Procmail-Match-From-Return-Path: unmatch!" \
| formail -i "Procmail-Return-Path: $RETUERN_PATH" \
| formail -i "Procmail-From: $ORIGINAL_FROM" \
| formail -i "Procmail-To: $ORIGINAL_TO"

あとは、総務省の迷惑メール対策室へ自動で転送したり
From と Return-Path のドメインも判定したり・・・


######## ヘッダからメールアドレス抽出

:0
* ^Return-Path:\/.*
{
  RETUERN_PATH=`echo "$MATCH"|grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1`
  RETUERN_PATH_DOMAIN=`echo "$RETUERN_PATH"|sed -r "s/.*@([-a-zA-Z0-9_.]+).*/\1/"`
}

:0
* ^From:\/.*
{
  ORIGINAL_FROM=`echo "$MATCH"|grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1`
  ORIGINAL_FROM_DOMAIN=`echo "$ORIGINAL_FROM"|sed -r "s/.*@([-a-zA-Z0-9_.]+).*/\1/"`
}

:0
* ^To:\/.*
{
  ORIGINAL_TO=`echo "$MATCH"|grep -o -E "[-a-zA-Z0-9_.=+]+@[-a-zA-Z0-9_.]+" | tail -n 1`
}

######## スパム判定

# From と To が同じ (スパム確定) - 削除
:0
* $ORIGINAL_FROM ?? $ $ORIGINAL_TO
/dev/null

# From と Return-Path が違う
:0
*! $ORIGINAL_FROM ?? $ $RETUERN_PATH
{
  # Return-Path ドメインが From ドメインを含まない
  :0fw
  *! $RETUERN_PATH_DOMAIN ?? $ $ORIGINAL_FROM_DOMAIN
  | formail -i "Procmail-Match-FromDomain-Return-Path: unmatch!"

  :0Efw
  | formail -i "Procmail-Match-From-Return-Path: unmatch!"

  :0fw
  | formail -i "Procmail-Return-Path: $RETUERN_PATH" \
  | formail -i "Procmail-From: $ORIGINAL_FROM" \
  | formail -i "Procmail-To: $ORIGINAL_TO"
}

# spamassassin
:0fw
*!^X-Spam.* 
| /usr/bin/spamc

:0c
* ^X-Spam-Flag: YES
{
  # 総務省の迷惑メール対策室へ転送
  # これで捨てずに自分も受信する

  SENDMAILFLAGS="-oi -f $RETUERN_PATH"
  ! meiwaku@dekyo.or.jp
}

こんな感じ。