Redmineには指定のアドレスに送ったメールからチケットを作ったり、チケットコメントを追記したりする機能があります。そのメールに添付ファイルがある場合は、チケットの添付ファイルにも追加されます。
問題
この添付ファイルがテキストファイルである場合に、文字コードが変わってしまう問題があります。
具体的には、メールにSJISのテキストファイルを添付してRedmineで取り込み、作成されたチケットのページからそのファイルをダウンロードするとファイルのエンコードがUTF-8に変わってしまうことがあります。
添付ファイルは元々のバイナリを維持したままのファイルを保存してほしいところなのですが、この挙動は困ってしまいます。
なお、この問題は必ず起きるわけではありません。メールの生データ中で添付ファイル部分のContent-Typeで「charset」を指定していると、この問題が発生します。
charsetが明記されているために、エンコードができてしまっていることが原因のようです。
メーラによってはここにcharsetを明記しないらしく、Outlookから送ったメールでは問題がおきず、Gmailから送ったメールでは問題がおきました。
問題が起きるメールの添付ファイル部分
--f46d040714391fef6a0510328cb4
Content-Type: text/plain; charset=Shift_JIS; name="text.sjis.txt"
Content-Disposition: attachment; filename="text.sjis.txt"
Content-Transfer-Encoding: base64
CoNUg5ODdoOLg3SDQINDg4tzamlzCgo=
この問題は結構困りそうなのですが、ググった限りではいまいちこの現状について書かれているものがありませんでした。
原因
この問題は、Redmineのメールからチケットを生成する以下の箇所で、attachment.decodedを使っているのが原因のようです。
def add_attachments(obj)
if email.attachments && email.attachments.any?
email.attachments.each do |attachment|
next unless accept_attachment?(attachment)
obj.attachments << Attachment.create(:container => obj,
:file => attachment.decoded,
:filename => attachment.filename,
:author => user,
:content_type => attachment.mime_type)
end
end
end
ここのdecodedメソッドは、MailモジュールのMessage#decodedメソッドで、内容がテキストファイルの場合にはエンコード変換済みの内容を返してしまいます。
このメソッドの代わりにMessage#readメソッドを使えば、元々のバイナリをそのまま取得できそうです。
対処
修正方法が分かったので、そのモンキーパッチをプラグイン形式にして作成しました。
おまけ
ちなみに、Redmineのプラグインは初めて作ったのですが、モンキーパッチをプラグイン化する方法の説明が中々みつからず苦労しました...
以下に公式っぽい文書があるのですが、どうも内容が古いようです。
上記のページで紹介されているinit.rbではDispatcher#to_prepareを使っているのですが、試してみると"dispacher"をrequireできずに使えませんでした。
require 'dispatcher'
Dispatcher.to_prepare :redmine_kanban do
# パッチ設定
end
その代わりに、Rails.configuration.to_prepareを使っている例があったので、それを参考にしています。