MimeBodyPartとDataHandler

広告

"MimeBodyPart"クラスは各パーツを表し、"BodyPart"クラスのサブクラスです。まず下記のクラス図を見てください。

  • java.lang.Object
  • javax.mail.BodyPart
  • javax.mail.internet.MimeBodyPart
  • public class MimeBodyPart extends BodyPart implements MimePart

親クラスである"BodyPart"はマルチパートに追加するパート部分の基本クラスですが、abstractクラスであり、メソッドもほとんど何も定義されていませんので、"BodyPart"クラスのサブクラスである"MimeBodyPart"クラスについてだけ見ておきます。

コンストラクタも3つありますが、こちらもデフォルトコンストラクタだけ知っていればいいかと思います。

An empty MimeBodyPart object is created. This body part maybe filled 
in by a client constructing a multipart message.

コンストラクタでオブジェクトを使った後で実際の中身をセットします。セットする方法としては2つ用意されており、本文などのテキストをセットするには"setText"メソッド、ファイルなどの添付には"setDataHandler"メソッドが用意されています。

テキストをセットする場合

まずは"setText"の方から見ていきます。

Convenience method that sets the given String as this part's content,
with a MIME type of "text/plain". If the string contains non US-ASCII
characters, it will be encoded using the platform's default charset. 
The charset is also used to set the "charset" parameter. 

Note that there may be a performance penalty if text is large, since 
this method may have to scan all the characters to determine what 
charset to use. 

If the charset is already known, use the setText() version that takes 
the charset parameter.

このメソッドはパート部分に引数で指定したテキストをセットします。MIMEタイプは"text/plan"です。文字コードはOSのデフォルトキャラクターセットになるようです。明示的に文字コードを指定したい場合は下記のメソッドも用意されています。

Convenience method that sets the given String as this part's content, 
with a MIME type of "text/plain" and the specified charset. The given
Unicode string will be charset-encoded using the specified charset. 
The charset is also used to set the "charset" parameter.

日本語も含めて利用するケースが多いと思いますので、実際には下記のように使います。

try {
  String str = "本文のテキストです";

  MimeBodyPart mbp = new MimeBodyPart();
  mbp.setText(str, "ISO-2022-JP");
} catch (MessagingException mex) {
  mex.printStackTrace();
}

ファイルをセットする場合

次はファイルを添付する場合です。

This method provides the mechanism to set this body part's content. The
given DataHandler object should wrap the actual content.

Parameters:
  dh - The DataHandler for the content
Throws:
  IllegalWriteException - if the underlying implementation does not 
    support modification
  IllegalStateException - if this body part is obtained from a 
    READ_ONLY folder.

添付するファイルは画像ファイルだったり圧縮ファイルだったりと様々な形式がありますが、"DataHandler"クラスを使うことで統一的に扱うことができます。

そこで"DataHandler"クラスについても見ておきましょう。("DataHandler"クラスはJavaMailで用意されているクラスではなく、JAFの方で用意されているクラスです)。

  • java.lang.Object
  • javax.activation.DataHandler
  • public class DataHandler extends java.lang.Object implements java.awt.datatransfer.Transferable

詳しくは分からないのですけど、様々な形式でフォーマットされているファイルに対して、それを意識することなく統一的なインターフェースで取り扱えるようにしたものが、この"DataHandler"クラスのようです。

コンストラクタは3つありますが、サンプルで使われていたコンストラクタは下記のものになります。

Create a DataHandler instance referencing the specified DataSource. 
The data exists in a byte stream form. The DataSource will provide 
an InputStream to access the data.

Parameters:
  ds - the DataSource

引数で使われている"DataSource"インターフェースのオブジェクトにて、対象となるファイルを指定します。"DataSource"インターフェースには実装クラスとしてファイルを扱う"FileDataSource"クラスと、URLで指定する"URLDataSource"クラスがありますけど、今回は"FileDataSource"クラスを見てみます。

  • java.lang.Object
  • javax.activation.FileDataSource
  • public class FileDataSource extends java.lang.Object implements DataSource

コンストラクタは2つあります。ファイル名のパスで指定する場合と、"File"クラスのオブジェクトで指定する場合です。両方とも見ておきます。

Creates a FileDataSource from a File object. 
Note: The file will not actually be opened until a method is called 
that requires the file to be opened.

Parameters:
  file - the file
Creates a FileDataSource from the specified path name. 
Note: The file will not actually be opened until a method is called 
that requires the file to be opened.

Parameters:
  name - the system-dependent file name.

どちらも使い方は同じです。ファイルのパスで指定する方法の場合で、例えば"filename.abc"というファイルを添付させたい場合の具体的な記述方法は下記のようになります。

try {
  String filename = "c:¥¥temp¥¥filename.abc";

  MimeBodyPart mbp = new MimeBodyPart();

  FileDataSource fds = new FileDataSource(filename);
  mbp.setDataHandler(new DataHandler(fds));
} catch (MessagingException mex) {
  mex.printStackTrace();
}

上記では絶対パスでファイルの位置を指定していますが、相対パスでも大丈夫だろうと思います。

ファイル名の指定

ファイルを添付した場合には、添付したファイル名を別途指定します。(指定しなくても大丈夫なのかもしれません)。

ファイル名の指定には"MimeBodyPart"クラスの"setFileName"メソッドを使います。

Set the filename associated with this body part, if possible. 

Sets the "filename" parameter of the "Content-Disposition" header 
field of this body part.

Throws:
  IllegalWriteException - if the underlying implementation does not 
    support modification
  IllegalStateException - if this body part is obtained from a 
    READ_ONLY folder.

具体的には下記のようになります。

try {
  String filename = "c:¥¥temp¥¥filename.abc";

  MimeBodyPart mbp = new MimeBodyPart();

  FileDataSource fds = new FileDataSource(filename);
  mbp.setDataHandler(new DataHandler(fds));
  mbp.setFileName("filename.abc");
} catch (MessagingException mex) {
  mex.printStackTrace();
}

ちなみに"FileDataSource"クラスの"getName"メソッドを使うと、ファイルの名前部分だけを取り出すことが出来ます。

Return the name of this object. The FileDataSource will return the file 
name of the object.

Returns:
  the name of the object.

このメソッドを使った場合は下記のようになります。

try {
  String filename = "c:¥¥temp¥¥filename.abc";

  MimeBodyPart mbp = new MimeBodyPart();

  FileDataSource fds = new FileDataSource(filename);
  mbp.setDataHandler(new DataHandler(fds));
  mbp.setFileName(fds.getName());
} catch (MessagingException mex) {
  mex.printStackTrace();
}

( Written by Tatsuo Ikura )