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。 関連リンク †この記事は 現在のアクセス:66696 |