class MailEngine::MailSchedule < ActiveRecord::Base validates_presence_of :name, :user_group, :mail_template_id, :period, :count, :first_send_at belongs_to :mail_template scope :available, where("sent_count < count OR count = 0") # list mail log with the same mail_template_path to current mail_template's path def logs(count = 10) MailEngine::MailLog.where(:mail_template_path => self.mail_template.actual_path).order("id desc").limit(count) end # load user info into payload hash used at mail template. def load_payload user payload_hash = {} self.payload.split(",").each do |col| payload_hash[col] = user.send(col) end payload_hash end # send test mail to specific recipient email address, with loading sample_user's data. def send_test_mail_to!(recipient, sample_user_id) raise "Wrong email format." if recipient.blank? or recipient !~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i sample_user = MailEngine::USER_MODEL.find(sample_user_id) I18n.with_locale(mail_template.locale) do MailEngine::MailDispatcher.send( mail_template.template_name.to_sym, :to => recipient, :values => self.load_payload(sample_user) ).deliver end end # If execute sendmail twice very soon(within 14 minutes), it should not be able to send mail again. def ready_to_send? # check if send count reached the total count. return false if (sent_count >= count and count != 0) # only send once. return sent_count < 1 if period == 'once' # why 15 minutes? for tolerance. not_sent_mail_within_15_minutes = last_sent_at.nil? || ((Time.now.to_i - last_sent_at.to_i).abs >= 60*15) ready_to_send = not_sent_mail_within_15_minutes and (Time.now.to_i - first_send_at.to_i).abs < 60*15 result_by_period = case period when 'daily' 1.days.ago.to_i <= last_sent_at.to_i when 'weekly' 1.week.ago.to_i <= last_sent_at.to_i when 'monthly' 1.month.ago.to_i <= last_sent_at.to_i else false end ready_to_send or (not_sent_mail_within_15_minutes and result_by_period) end # used in Rake task, the main mail sending method. def sendmail puts "---> Schedule: '#{self.name}'" if Rails.env != 'test' unless ready_to_send? puts "---> not ready" return false end MailEngine::USER_MODEL.send(self.user_group.to_sym).each do |user| puts "-> sending mail to #{user.email}" ### FIXME user.email, what if user don't have email column. MailEngine::MailDispatcher.send(mail_template.template_name.to_sym, :to => user.email, :values => self.load_payload(user) ).deliver end self.last_sent_at = Time.now self.sent_count += 1 self.save end end