Module: MailSpy::Manager

Included in:
MailSpy
Defined in:
lib/mail_spy/manager.rb

Instance Method Summary collapse

Instance Method Details

#create_email(options) ⇒ Object

——————————————- CREATE EMAIL Adds a instance of a email template to the queue to send



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/mail_spy/manager.rb', line 7

def create_email(options)
  options.to_options!

  required_options = [
    :campaign, :stream, :component, :schedule_at, :subject,
    :template_values, :from, :reply_to]
  to_options = [:to, :cc, :bcc]

  # Ensure that we have the required options
  required_options.each { |ro| raise "create_email call missing #{ro}" unless options.include? ro }

  # Ensure that the campaign, stream and component are not blank
  # These keys are used to define the s3 paths for the templates
  [:campaign, :stream, :component].each { |key| raise "##{key} can't be blank" if options[key].blank? }

  # Make sure we have someone to send to
  # TODO need to test setting the options but filling with nil
  has_sender = to_options.select { |option| options[option].present? }.present?
  raise "Email instance has no sender (to,cc,bcc were all blank)" unless has_sender

  # Make sure that all options passed map to a accessor so we don't errantly
  # think we are passing something correctly and really its getting silently
  # ignored
  options.keys.each do |option|
    unless MailSpy::Email.method_defined? "#{option}=".intern
      raise "MailSpy::Email doesn't have #{option} as a setter '"
    end
  end

  # Ensure that a esp (forced or random) exists for the email
  forced_esp = options[:email_service_provider]
  if forced_esp.present?
    raise "No esp configured with name: #{forced_esp}" if MailSpy.esps[forced_esp].blank?
  else
    raise "No esps configured" if MailSpy.esps.blank?
    esp_key = MailSpy.esps.keys[rand(MailSpy.esps.keys.count)]
    options[:email_service_provider] = esp_key
  end

  # Google Analytics aupport for automatic population of utm_tokens
  esp = MailSpy.esps[options[:email_service_provider]]
  if esp.options[:enable_auto_google_analytics].present?
    options[:utm_source] ||= 'mailspy'
    options[:utm_medium] ||= 'email'
    options[:utm_campaign] ||= options[:campaign]
    options[:utm_term] ||= options[:stream]
    options[:utm_content] ||= options[:component]
  end

  #Create the email
  email = MailSpy::Email.create!(options)

  #Enable sendgrid specific enhancements
  if esp.options[:enable_sendgrid_event_tracking].present?
    header = MailSpy::Sendgrid::SmtpApiHeader.new
    header.setUniqueArgs({:eid => email.id.to_s})
    email.headers = {'X-SMTPAPI' => header.asJSON}.merge(email.headers)
  end

  email.save!
  email
end

#send_outstanding_emails(step = 100, num_threads = 50) ⇒ Object

——————————————- SEND OUTSTANDING EMAILS Batches through all the emails that were scheduled and have come due sends them out (step many at a time)



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mail_spy/manager.rb', line 73

def send_outstanding_emails(step=100, num_threads=50)
  raise "No Email service providers installed" unless MailSpy.esps.present?

  wq = WorkQueue.new(num_threads, step*2)
  current_time = DateTime.now
  offset = 0
  sent = 0

  # Helper function for setting present values
  def set_if_present(email, pony_hash, pony_key, email_key=nil)
    email_key = pony_key if email_key.nil?
    value = email.send("#{email_key}")
    pony_hash[pony_key] = value if value.present?
  end

  while true
    emails = MailSpy::Email.
      limit(step).offset(offset).
      where(:schedule_at.lte => current_time, :sent => false, :failed => false).collect
    break if emails.count <= 0 #returns enumerator which is never blank
    emails.each do |email|
      wq.enqueue_b do
        begin
          MailSpy::CoreMailer.template(email).deliver
          email.update_attribute(:sent, true)
          sent += 1
        rescue Exception => e
          email.failed = true
          email.error_message = e.try(:message)
          email.error_backtrace = e.try(:backtrace)
          email.save!
        end
      end
    end
    # We must join here otherwise the next loop email lookup will be in a
    # race condition with the results of our worker_queue.
    wq.join
    offset += step
  end

  sent
end

#set_if_present(email, pony_hash, pony_key, email_key = nil) ⇒ Object

Helper function for setting present values



82
83
84
85
86
# File 'lib/mail_spy/manager.rb', line 82

def set_if_present(email, pony_hash, pony_key, email_key=nil)
  email_key = pony_key if email_key.nil?
  value = email.send("#{email_key}")
  pony_hash[pony_key] = value if value.present?
end

#track_action(email_id, action_type, details = {}, count = 1) ⇒ Object

——————————————- TRACKING MailSpy will automatically track opens and clicks if the tracking bugs and track_link helpers are used. This action allows tracking of arbitrary actions. Please be careful to standardize on action names email_id: The id from the MailSpy::Email record action_type: String denoting the action that occured details: Hash of any details of that action (again strive for standards) count: how many of this action occurred (defaults to 1)



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/mail_spy/manager.rb', line 125

def track_action(email_id, action_type, details={}, count=1)
  raise "track_action missing email_id" if email_id.blank?
  raise "track_Action missing action_type" if action_type.blank?

  hash ={}
  hash[:action_type] = action_type
  hash[:count] = count
  hash[:details] = details if details.present? && details.kind_of?(Hash)

  # Save it up
  email = MailSpy::Email.find(email_id)
  email.actions.create!(hash)
end