每天一剂Rails良药之Handling Bounced Email

当Email发送失败时,我们可以捕获bounced messages来notify系统用户邮件发送出错
app/models/reminder.rb
class Reminder < ActionMailer::Base
  def reminder(recipient, text)
    @subject    = 'Automated Reminder!'
    @body       = {:text => text}
    @recipients = recipient
    @from       = '[email protected]'
    @sent_on    = Time.now
    @headers    = {}
  end
end

app/controllers/reminder_controller.rb
class ReminderController < ApplicationController
  def deliver
    mail = Reminder.deliver_reminder(params[:recipient], params[:text])
    Delivery.create(:message_id => mail.messsage_id,
                    :recipient => params[:recipient],
                    :content => params[:text],
                    :status => 'Sent')
    render :text => "Message id #{mail.message_id} sent."
  end
end

app/models/bounce_receiver.rb
class BounceReceiver < ActionMailer::Base 
  
  class BouncedDelivery
    attr_accessor :status_info, :original_message_id
    def self.from_email(email)
      returning(bounce = self.new) do
        status_part = email.parts.detect do |part| 
          part.content_type == "message/delivery-status"
        end 
        statuses = status_part.body.split(/\n/)
        bounce.status_info =  statuses.inject({}) do |hash, line| 
          key, value = line.split(/:/)
          hash[key] = value.strip rescue nil
          hash
        end
        original_message_part = email.parts.detect do |part|
          part.content_type == "message/rfc822"
        end
        parsed_msg = TMail::Mail.parse(original_message_part.body) 
        bounce.original_message_id = parsed_msg.message_id 
      end                             
    end  
    def status
      case status_info['Status']
      when /^5/
        'Failure'
      when /^4/ 
        'Temporary Failure'
      when /^2/            
        'Success'
      end
    end
  end
  
  
  def receive(email)
    return unless email.content_type == "multipart/report"
    bounce = BouncedDelivery.from_email(email)
    msg    = Delivery.find_by_message_id(bounce.original_message_id)
    msg.update_attribute(:status, bounce.status)
  end
  
end

其中Status 2.X.X表示发送成功,4.X.X表示暂时错误,等会将重试,5.X.X表示发送失败

BTW:《Rails Recipes》终于读完了,我们对Rails的View/Controller/Database/Test等等都有不少深入的探讨
下一步我们来看看一些常用或有用的插件,继续每天一剂Rails良药的学习。

你可能感兴趣的:(Rails)