Top / Java / JavaMail / 受信メールの解析に使う

JavaMail?をメールの解析に使う、って?

JavaMail?は通常メールを送信したりメールを受信するためのAPI群ですが、メールデータをストリームから受け取って解析する、などの用途にも利用することができます。たとえば受信したメールデータの宛先アドレスを抜き出すとか、本文の中身をサニタイズするとか、そんな場合ですね。ストリームから受け取れるってことは標準入力からのデータも解析できるわけで、たとえば、.forwardでメールをプログラムに転送してそこでなんか処理するときなど、標準入力よりプログラムにメールデータが渡されることになりますが、そこでJavaMail?のAPIを利用することができます。

サンプル

サンプルとして以下のようなメールを扱ってみたいと思います。

From fromaddress@hogehoge.com  Sun May 18 01:13:17 2008
Return-Path: <fromaddress@hogehoge.com>
X-Original-To: toaddress@hogehoge.jp
Delivered-To: toaddress@hogehoge.jp
Received: from fuga.so-net.ne.jp (fuga.so-net.ne.jp [202.238.82.9])
	by mail.hogehoge.jp (Postfix) with ESMTP id A75B1408BE
	for <toaddress@hogehoge.jp>; Sun, 18 May 2008 01:13:12 +0900 (JST)
Received: from [127.0.0.1] 
	by fuga.so-net.ne.jp  with ESMTP id m4HGD9n9027300;
	Sun, 18 May 2008 01:13:09 +0900 (JST)
Date: Sun, 18 May 2008 01:13:10 +0900
From: Hogehoge Com <fromaddress@hogehoge.com>
To: toaddress@hogehoge.jp
Subject: =?ISO-2022-JP?B?GyRCJUYlOSVIJWEhPCVrISobKEI=?=
Message-Id: <20080518011206.8EB1.fromaddress@hogehoge.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding: 7bit
X-Mailer: Becky! ver. 2.31 [ja]

メールのテストです。
end。

このメールをストリームから受信して、JavaMail?で内容を解析してみたいと思います。だいたいの内容は以下の通りですね。

ちなみに

Subject: =?ISO-2022-JP?B?GyRCJUYlOSVIJWEhPCVrISobKEI=?=

ですが "GyRCJUYlOSVIJWEhPCVrISobKEI=" をBase64でデコードしてそのバイナリを上記 ISO-2022-JP でデコードすると「テストメール!」となります。

MIMEでエンコードされたMailのSubjectのデコード、エンコード - 教えて!goo

まずはテキストファイルからメールを読み取る

まずは標準入力からでなくファイルからストリームを作成して、メールを解析してみます。上記ファイルをテキストでJISで保存しておきます。

サンプルは以下の通り。

public class FileMain {
  public static void main(String[] args) throws IOException {
    try {
      InputStream in = new FileInputStream(new File("mail.dummy.txt"));
      Session session = Session.getDefaultInstance(
          new java.util.Properties(), null);
      MimeMessage message = new MimeMessage(session, in);
      print(message);
    } catch (MessagingException e) {
      e.printStackTrace();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  private static void print(MimeMessage message) throws MessagingException,
      IOException {
    System.out.println("---- 全ヘッダをリストします ----");
    Enumeration<Header> allHeaders = message.getAllHeaders();
    while (allHeaders.hasMoreElements()) {
      Header header = allHeaders.nextElement();
      System.out
          .println(header.getName() + " : " + header.getValue());
    }
    System.out.println("---- 全ヘッダ 以上 ----");

    System.out.println("---- ヘッダ名指定で取ってみる(Received) ----");
    String[] headers = message.getHeader("Received");
    for (String header : headers) {
      System.out.println(header);
    }

    System.out.println("---- ヘッダ名指定で取ってみる(Return-Path) ----");
    headers = message.getHeader("Return-Path");
    for (String header : headers) {
      System.out.println(header);
    }

    System.out.println("---- ヘッダ名指定で取ってみる(Subject) ----");
    headers = message.getHeader("Subject");
    for (String header : headers) {
      System.out.println(header);
    }
    System.out.println("デコード↑してくれない");

    System.out.println("---- 専用のメソッドで取ってみる(Subject) ----");
    System.out.println(message.getSubject());
    System.out.println("デコード↑してくれた");

    System.out.println("---- 専用のメソッドで取ってみる(To) ----");
    Address[] allRecipients = message.getAllRecipients();
    for (Address address : allRecipients) {
      System.out.println(address);
    }

    System.out.println("---- メール本体の取得 ----");
    System.out.println(message.getContent());
    System.out.println("--------");
  }
}

結果は以下の通りです

---- 全ヘッダをリストします ----
From fromaddress@hogehoge.com  Sun May 18 01 : 13:17 2008
Return-Path : <fromaddress@hogehoge.com>
X-Original-To : toaddress@hogehoge.jp
Delivered-To : toaddress@hogehoge.jp
Received : from fuga.so-net.ne.jp (fuga.so-net.ne.jp [202.238.82.9])
	by mail.hogehoge.jp (Postfix) with ESMTP id A75B1408BE
	for <toaddress@hogehoge.jp>; Sun, 18 May 2008 01:13:12 +0900 (JST)
Received : from [127.0.0.1] 
	by fuga.so-net.ne.jp  with ESMTP id m4HGD9n9027300;
	Sun, 18 May 2008 01:13:09 +0900 (JST)
Date : Sun, 18 May 2008 01:13:10 +0900
From : Hogehoge Com <fromaddress@hogehoge.com>
To : toaddress@hogehoge.jp
Subject : =?ISO-2022-JP?B?GyRCJUYlOSVIJWEhPCVrISobKEI=?=
Message-Id : <20080518011206.8EB1.fromaddress@hogehoge.com>
MIME-Version : 1.0
Content-Type : text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding : 7bit
X-Mailer : Becky! ver. 2.31 [ja]
---- 全ヘッダ 以上 ----

---- ヘッダ名指定で取ってみる(Received) ----
from fuga.so-net.ne.jp (fuga.so-net.ne.jp [202.238.82.9])
	by mail.hogehoge.jp (Postfix) with ESMTP id A75B1408BE
	for <toaddress@hogehoge.jp>; Sun, 18 May 2008 01:13:12 +0900 (JST)
from [127.0.0.1] 
	by fuga.so-net.ne.jp  with ESMTP id m4HGD9n9027300;
	Sun, 18 May 2008 01:13:09 +0900 (JST)

---- ヘッダ名指定で取ってみる(Return-Path) ----
<fromaddress@hogehoge.com>

---- ヘッダ名指定で取ってみる(Subject) ----
=?ISO-2022-JP?B?GyRCJUYlOSVIJWEhPCVrISobKEI=?=
デコード↑してくれない

---- 専用のメソッドで取ってみる(Subject) ----
テストメール!
デコード↑してくれた

---- 専用のメソッドで取ってみる(To) ----
toaddress@hogehoge.jp

---- メール本体の取得 ----
メールのテストです。
end。
--------

<>とかの微妙な装飾まで細かな解析はしてくれないみたいですが、まあ、自前で解析するよりは良さそうです。

パイプされた標準入力からメールを読み取る

次に実際に標準入力からやってみます。

public static void main(String[] args) {
  try {
    InputStream in = System.in;
    Session session = Session.getDefaultInstance(
        new java.util.Properties(), null);
    MimeMessage message = new MimeMessage(session, in);
    print(message);
  } catch (MessagingException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
}

ストリームとして標準入力を渡しています。では実際にUnix上でパイプで標準入力を渡してみましょう。

[hoge@www Test]$ export CLASSPATH=lib/mail.jar:lib/sample.jar:lib/activation.jar
[hoge@www Test]$ cat mail.dummy.txt | java nu.mine.kino.sample.Main

書きませんが先と同じ結果が得られました。

ちなみにパイプしない場合は入力待ちになります。色々入力後Ctrl+ z で入力終了を指示すれば、プログラムが実行されます*2

関連リンク

メーリングリストの構築と運用(前編)(4/4)


この記事は

選択肢 投票
おもしろかった 43  
そうでもない 13  

Top / Java / JavaMail / 受信メールの解析に使う

現在のアクセス:47852


*1 SMTPをコマンドラインでたたくときの、mail from: xxx のこと。Envelope Fromってやつ
*2 Platform-Specific Details: The End-of-Input Character

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-10-17 (月) 14:21:21 (224d)