[Java][Windows][Ruby][備忘録].msgファイルをパースして中から添付ファイルを抜き出す
正確にはRubyというには微妙なんですが…。
前回までのあらすじ
- 選んだメール(本文と添付ファイル)をまとめてDLしてくるだけの簡単なお仕事はできるようになった
しかし、社内セキュリティGWの設定? のためかzipとかexeとか怪しい拡張子が付いている添付ファイルは一旦msgファイルに固められるという仕様のためそのままでは添付ファイルが見れない。
こういうメールが
メール
┗添付ファイル.zip
届いた時にはこうなっている
メール
┗ラップ.msg(\あやしいファイルだから注意してDLしてね/)
┗本来の添付ファイル.zip
なんとかRubyからmsgファイル内を解析して添付ファイルを引っこ抜いて保存ができまいか…というのが今回の問題。
結論
以下のライブラリを駆使して実現しました。
- msgparser(Auxiliiという所のJava用msgファイルパースライブラリ)
- jrb(Java Ruby Bridge: RubyからJavaVMを操作できるライブラリ)
一応Rubyでmsgファイルを解析するライブラリも探してみたのですが、あまりないのかな? http://en.sourceforge.jp/projects/sfnet_ssfiledll/downloads/SSFileDLL%20%28MAPI%29/1.0/SSFileDLL-MAPI-1.0-Source.zip/:title こういうdllは見つけたのですが、MAPIがよくわからん上に説明を見る限りHasAttach(添付ファイルを持ってるか持ってないか?)くらいしかわからない? ようなのであきらめました。
あと、msgparserはJavaライブラリなので当初はJRubyで書けば何とかなるかなと思ってました。簡単なサンプルは http://www.rgagnon.com/javadetails/java-0613.html:title このページのような感じ。が、今まで書いたコードをJRubyで実行すると失敗してしまったので方向転換;; RubyからJavaVMを操作できるrjbというライブラリを使う事に。
ダウンロード・インストール
- msgparser
- http://auxilii.com/msgparser/Page.php?id=16000:title よりmsgparserをDL
- distよりmasparser-X.XX.jarを、libよりpoi-X.X-YYYYMMDD.jarとtnef-X.X.X.jarを取得し、同じプロジェクト内にコピー。とりあえずlibフォルダを作ってそこに入れました
- rjb
- gemで。ただし、当然というかJavaが入っていないと失敗する模様。環境変数JAVA_HOMEも設定している必要があるみたい
gem install rjb
ソース
ソース全体は [https://github.com/gosyujin/outlook_for_ruby:title] 。msgParse.rbが本体、ライブラリがlibに入っています。
使い方としてはMsgParseをnewしてinputMsgで.msgファイルのパス指定、saveFileで添付ファイルぶっこぬいて出力先に保存としたい。こんな感じで。
msg = MsgParse.new
msg.inputMsg(MSGFILE)
msg.saveFile(SAVEDIR)
という事でMsgParser[2]クラスを作成。ソースは [https://github.com/gosyujin/outlook_for_ruby/blob/master/msgParse.rb:title] 。まずは初期化から。
include Rjb
# JavaクラスのImport、Jarの読み込み
# 初期化処理を行う
def initialize
#Rjb::load('./')
initJavaClass()
addJar()
@msg = nil
end
# JavaのクラスをImportする
def initJavaClass()
@system = import("java.lang.System")
# @string = import("java.lang.String")
# @list = import("java.util.List")
@fileOutputStream = import("java.io.FileOutputStream")
end
# Jarを読みこむ
def addJar()
Rjb::add_jar(File.expand_path('lib/tnef-1.3.1.jar'))
Rjb::add_jar(File.expand_path('lib/poi-3.2-FINAL-20081019.jar'))
Rjb::add_jar(File.expand_path('lib/msgparser-1.10.jar'))
@msgParser = import("com.auxilii.msgparser.MsgParser")
@fileAttachment = import("com.auxilii.msgparser.attachment.FileAttachment")
end
java.lang.Systemとかjava.lang.Stringとか使う予定のあるクラスは全て明示的にimportしてやる必要がある。今回はjava.lang.Systemとjava.io.FileOutputStreamを使用する。
次にライブラリを読み込む。msgparserをDLしたときのtnef, poi, msgparserを追加する。追加後にcom.auxilii.msgparser.MsgParserとcom.auxilii.msgparser.attachment.FileAttachmentをimportする。※add_jarの順番でエラーになる。-classpathの記述? に順番って関係あるんだっけ?
これで今回使用したいクラスはRuby上から呼び出せるようになりました。次はファイル読み込み。
# .msgファイルを読みこむ
def inputMsg(path)
@msg = @msgParser.new.parseMsg(path)
end
parseMsg(PATH)メソッドを使用し.msgファイルを読み込めるように。最後は.msgファイル内から添付ファイルをぶっこぬく!
# .msgファイルの添付ファイル数をカウントする
def getAttachmentSize()
@msg.getAttachments.size
end
# 添付ファイルをpathに保存する
# 返り値は保存した添付ファイル名(の一つ)
def saveFile(path)
fileName = ""
if getAttachmentSize() != 0 then
for i in 0..getAttachmentSize - 1
file = @msg.getAttachments.get(i)
begin
fileName = file.getLongFilename
rescue => ex
puts "File name is including WAVE DASH?:#{ex}"
fileName = file.getFilename
end
out = @fileOutputStream.new(path + fileName)
out.write(file.getData)
puts "■.msgファイル抽出:#{fileName}"
out.close
end
else
puts "no temp file."
end
return fileName
end
end
はじめにgetAttachments.get(i)で添付ファイルを取得します。次に保存する時のファイル名として添付ファイル名を取得します。ファイル名を取得できるメソッドは2種類あります。getLongFilenameはファイル名をそのまま取得でき、getFilenameはファイル名を短縮して取得できます。[3]
ここまでやったら最後はFileOutputStream#writeにgetDataで取得した添付ファイルのバイト配列を渡してやればOK!
[1] complete package including source code, binaries and third party librariesと書いてあった
[2] ライブラリと同じ名前にしてしまった…。
[3] TODOとして、添付ファイル名に波ダッシュが入っているとエラーになるので要調査…。