Hatena::ブログ(Diary)

いとうまさしのカチャカチャTODAY

2010-02-19

file_columnで受信メールの添付画像を保存する方法

| 16:48

前提

Statusモデルにimageというフィールドがあって、そこがfile_columnを採用している。

メールを受信したら添付ファイルをstatus.imageに格納したい。


(1)file_columnの一部を拡張します。

vendor/plugins/file_column/lib/file_compat.rb

を以下のように変えます。

(- で始まる行が元々のコード、+ ではじまるのが変更後のコードです。)


   module FileCompat # :nodoc:
     def original_filename
-      File.basename(path)
+      @original_filename || File.basename(path)
     end
+
+    def original_filename=(name)
+      @original_filename = name
+    end


(2)StatusMailerというActionMailerを作る

メールを受信するためのクラスです。

中身はこんな感じ。

class StatusMailer < ActionMailer::Base  
  def receive(email)
    Status.parse_mail(email)
  end
end

メールを受信するための.forwardファイルは下記のような感じ。

| RAILS_ROOT/script/runner -e production 'Status.receive(STDIN.read)'

(3)Statusモデルの中に本体を実装

  def self.parse_mail(email)

    # email.to を解析して 対象の status を割り出す。
    status = ....

    # 添付画像を取得する
    if email.multipart?
      email.parts.each do |m|
        if m.main_type == 'image'
          # file_columnへの引き渡し
          status.save_image_from_mail m
          break
        end
      end
    end
    status
  end

  def save_image_from_mail(mail_part)
    # ランダムな文字列に拡張子を付けた形でファイル名を作る
    tmp_filename = Digest::SHA1.hexdigest( rand.to_s ).slice(1..10) + '.' + mail_part.sub_type

    # Tempfileを作って、データを格納する
    tmp = Tempfile::new tmp_filename
    tmp.puts mail_part.body

    # file_columnへの引き渡し準備
    tmp.extend FileColumn::FileCompat
    tmp.original_filename = tmp_filename

    self.image = tmp
    self.save

    # 後片付け
    tmp.close
  end

(4)動作確認

メーラーの適当なメールを.emlとかテキストフォーマットで保存する。

script/consoleを起動

・以下を実行

$ f = open '.emlファイルのパス'
$ StatusMailer.receive(f.read)
トラックバック - http://d.hatena.ne.jp/itmsc/20100219/1266565729
Connection: close