mailcannon/mailcannon

View on GitHub
lib/mailcannon/envelope.rb

Summary

Maintainability
A
35 mins
Test Coverage
# Where the magic happens, the Envelope is responsible for keeping the information necessary to send the email(s) and holding the Stamps related to mailing Events.
class MailCannon::Envelope
  include Mongoid::Document
  include Mongoid::Timestamps
  include MailCannon::Adapter::SendgridWeb
  
  belongs_to :envelope_bag, index: true

  embeds_one :mail
  embeds_many :stamps
  has_many :sendgrid_events
  
  field :from, type: String
  field :from_name, type: String
  field :to, type: Array # of hashes. [{email: '', name: ''},...]
  field :substitutions, type: Hash # of hashes
  field :subject, type: String
  field :bcc, type: String
  field :reply_to, type: String
  field :date, type: Date
  field :xsmtpapi, type: Hash # this will mostly be used by MailCannon itself. http://sendgrid.com/docs/API_Reference/SMTP_API/index.html
  field :auth, type: Hash # {user: 'foo', password: 'bar'}, some Adapters might need an token:secret pair, which you can translete into user:password pair.
  field :jid, type: String
  
  validates :from, :to, :subject, presence: true
  validates_associated :mail

  # Post this Envelope!
  def post_envelope!(options = {})
    self.save if self.changed?
    raise "Envelope(#{self.id}) has no mail! Didn't you already send it?" unless self.mail
    if validate_xsmtpapi(self.xsmtpapi)
      jid = schedule_send_job(options[:queue])
      self.save if self.changed?
    else
      raise 'Invalid xsmtpapi hash!'
    end
  end
  alias_method :"post!",:"post_envelope!"

  # Stamp this Envelope with code.
  def stamp!(code,recipient=nil)
    self.class.valid_code_kind?(code)
    unless self.persisted?
      logger.warn "You're trying to save the Stamp with an unsaved Envelope! Auto-saving Envelope."
      self.save
    end
    self.stamps.create(code: MailCannon::Stamp.from_code(code).code, recipient: recipient)
  end
  
  # Callback to be run after the Envelope has been processed.
  def after_sent
    stamp!(MailCannon::Event::Processed.stamp)
    if MailCannon.config['auto_destroy']
      self.mail.destroy
      self.mail=nil # to avoid reload
    end
  end

  def posted?
    if self.stamps.where(code: 0).count > 0
      true
    else
      false
    end
  end

  def processed?
    if self.stamps.where(code: 1).count > 0
      true
    else
      false
    end
  end

  private
  def schedule_send_job(queue)
    queue ||= :mail_delivery

    if MailCannon.config['waiting_time'].to_i > 0
      self.jid = Sidekiq::Client.enqueue_to_in(queue, MailCannon.config['waiting_time'].seconds, MailCannon::Barrel, self.id)
    else
      self.jid = Sidekiq::Client.enqueue_to(queue, MailCannon::Barrel, self.id)
    end
    if self.jid
      self.stamp! MailCannon::Event::Posted.stamp
      return self.jid
    end
  end

  def self.valid_code_kind?(code)
    unless [Fixnum, MailCannon::Stamp].include?(code.class) || MailCannon::Event.constants.include?(code.to_s.camelize.to_sym)
      raise 'code must be an Integer, MailCannon::Event::*, or MailCannon::Stamp !'
    end
  end

  def validate_xsmtpapi(xsmtpapi)
    return true # TODO write tests for this method
    if xsmtpapi['to'].is_a? Array
      true
    else
      false
    end
  end
    
end