2012年7月30日月曜日

メールを送る

今回はメールを送る方法を紹介します。

Gemを追加します。
gem 'delayed_job'
gem 'delayed_job_active_record'
gem 'daemons'
選び方などは省略するとして、モデルでdeliverを作成します。
has_many :destinations, through: :parcels, class_name: "User"

def destination_id_map=(hash)
  hash.each do |user_id, value|
    c = User.find_by_id(user_id)
    self.destinations << c
  end
end

LIMIT = 100

def deliver
  return unless status == "wating"

  log_dir = Rails.root.join('log', 'messages')
  Dir.mkdir(log_dir) unless File.exist?(log_dir)
  filename = sprintf('%06d.log', id)
  logger = Logger.new(Rails.root.join('log', 'messages', filename))

  logger.info('started. ' + Time.current.to_s(:db))
  current_parcels_id = nil
  loop do
    parcels = self.parcels.order('parcels.destination_id ASC').limit(LIMIT).includes(:destination)
    parcels = parcels.where('parcels.id > ?', current_parcels_id) if current_parcel_id
    parcels.each do |parcel|
      next if parcel.destination.deleted?

      begin
        UserMailer.notice(parcel).deliver
        parcel.update_attribute(:status, "sent")
        logger.info(sprintf("06d ok %s %s", parcel.destination_id, parcel.destination_mail))
      rescue Exception => e
        raise e if Rails.env.test?
        parcel.update_attribute(:status "error")
        logger.info(sprintf("%06d NG %s %s", parcel.destination_id, parcel.destination_mail e.to_s))
      end
    end
    break if parcels.size < LIMIT
    current_parcel_id = parcels.last.id
  end
  update_attribute(:status, "sent")
  logger.info('Ended. ' + Time.current.to_s(:db))
end
mailer/user_mailer.rbを作成します
class UserMailer < ActionMailer::Base
  default from: "from@example.com"

  def notice(parcel)
    mail(
      :subject => parcel.message.subject,
      :from => parcel.message.from,
      :to => parcel.destination.mail
    )
  end
end
controllerのcreateで作成して完了です。
def create
  @message = Message.new(params[:message])
  if params[:destinations].kind_of?(Hash)
    @message.destination_id_map = params[:destinations]
    @message.save!
    @message.delay.deliver
    redirect_to action: :index
  end
end
delayed_jobは使い方を学ぶ必要があります。Google先生に聞いて下さい。

0 件のコメント:

コメントを投稿