mail_spy 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- data/app/models/mail_spy/email.rb +48 -0
- data/app/models/mail_spy/process_log.rb +25 -0
- data/lib/mail_spy/manager.rb +35 -9
- data/lib/mail_spy/version.rb +1 -1
- data/test/dummy/db/seeds.rb +16 -13
- data/test/dummy/log/development.log +724 -0
- data/test/dummy/log/test.log +2372 -0
- data/test/fixtures/mail_spy/process_logs.yml +15 -0
- data/test/functional/mail_spy/tracking_controller_test.rb +13 -1
- data/test/unit/mail_spy/manager_test.rb +25 -12
- data/test/unit/mail_spy/process_log_test.rb +9 -0
- metadata +7 -2
@@ -99,6 +99,54 @@ module MailSpy
|
|
99
99
|
end
|
100
100
|
|
101
101
|
|
102
|
+
|
103
|
+
#var key_hash = {
|
104
|
+
# campaign:this.campaign,
|
105
|
+
# stream:this.stream,
|
106
|
+
# component:this.component,
|
107
|
+
# campaign:this.subject
|
108
|
+
#};
|
109
|
+
#
|
110
|
+
|
111
|
+
|
112
|
+
def self.generate_subject_reports
|
113
|
+
map = <<-eof
|
114
|
+
function(){
|
115
|
+
var action_counts = {};
|
116
|
+
for(var i=0, len = this.actions.length; i < len; i++){
|
117
|
+
var action = this.actions[i];
|
118
|
+
action_counts[action.action_type] = action_counts[action.action_type] || 0;
|
119
|
+
action_counts[action.action_type]++;
|
120
|
+
}
|
121
|
+
|
122
|
+
emit({
|
123
|
+
campaign:this.campaign,
|
124
|
+
stream:this.stream,
|
125
|
+
component:this.component,
|
126
|
+
subject:this.subject
|
127
|
+
}, action_counts);
|
128
|
+
}
|
129
|
+
eof
|
130
|
+
|
131
|
+
reduce = <<-eof
|
132
|
+
function(key, values){
|
133
|
+
var result = {};
|
134
|
+
|
135
|
+
values.forEach(function(hash){
|
136
|
+
for(var key in hash){
|
137
|
+
result[key] = result[key] || 0
|
138
|
+
result[key] += hash[key]
|
139
|
+
}
|
140
|
+
});
|
141
|
+
|
142
|
+
return result;
|
143
|
+
}
|
144
|
+
eof
|
145
|
+
|
146
|
+
results = collection.map_reduce(map, reduce, :out => "test_reports")
|
147
|
+
|
148
|
+
end
|
149
|
+
|
102
150
|
def self.generate_campaign_stats
|
103
151
|
|
104
152
|
map = <<-eof
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MailSpy
|
2
|
+
class ProcessLog
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
|
6
|
+
field :start, :type => Time
|
7
|
+
field :end, :type => Time
|
8
|
+
field :seconds_elapsed, :type => Integer
|
9
|
+
field :success, :type => Boolean, :default => false
|
10
|
+
field :running, :type => Boolean, :default => false
|
11
|
+
|
12
|
+
|
13
|
+
def self.currently_processing?
|
14
|
+
self.where(:running => true).first.present?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Deletes logs after a given date if no date is given we default
|
18
|
+
# to logs that are older that 3 months.
|
19
|
+
def self.delete_stale_logs(date=nil)
|
20
|
+
date = Time.now.advance(:months => -3) if date.nil?
|
21
|
+
self.where("created_at < #{date}").delete_all
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/mail_spy/manager.rb
CHANGED
@@ -19,11 +19,11 @@ module MailSpy
|
|
19
19
|
# These keys are used to define the s3 paths for the templates
|
20
20
|
[:campaign, :stream, :component].each { |key| raise "##{key} can't be blank" if options[key].blank? }
|
21
21
|
|
22
|
-
# Make sure we have someone to send to
|
23
|
-
# TODO need to test setting the options but filling with nil
|
22
|
+
# Make sure we have someone to send to and its not blank
|
24
23
|
has_sender = to_options.select { |option| options[option].present? }.present?
|
25
24
|
raise "Email instance has no sender (to,cc,bcc were all blank)" unless has_sender
|
26
25
|
|
26
|
+
|
27
27
|
# Make sure that all options passed map to a accessor so we don't errantly
|
28
28
|
# think we are passing something correctly and really its getting silently
|
29
29
|
# ignored
|
@@ -54,25 +54,39 @@ module MailSpy
|
|
54
54
|
end
|
55
55
|
|
56
56
|
#Create the email
|
57
|
-
email = MailSpy::Email.
|
57
|
+
email = MailSpy::Email.new(options)
|
58
|
+
|
59
|
+
# Ensure we have the template for the email on s3
|
60
|
+
raise "Missing html template" unless email.html_erb.present?
|
61
|
+
raise "Missing text template" unless email.text_erb.present?
|
58
62
|
|
59
|
-
|
63
|
+
email.save!
|
64
|
+
|
65
|
+
# Enable sendgrid specific enhancements
|
66
|
+
# Must happen after the email has been saved for the id
|
60
67
|
if esp.options[:enable_sendgrid_event_tracking].present?
|
61
68
|
header = MailSpy::Sendgrid::SmtpApiHeader.new
|
62
69
|
header.setUniqueArgs({:eid => email.id.to_s})
|
63
70
|
email.headers = {'X-SMTPAPI' => header.asJSON}.merge(email.headers)
|
64
71
|
end
|
65
|
-
|
66
|
-
email.save!
|
67
72
|
email
|
68
73
|
end
|
69
74
|
|
70
75
|
# ------------------------------------------- SEND OUTSTANDING EMAILS
|
71
76
|
# Batches through all the emails that were scheduled and have come due
|
72
|
-
# sends them out (step many at a time)
|
77
|
+
# sends them out (step many at a time). Don't thread this method, instead
|
78
|
+
# use the parameters to control concurrency
|
73
79
|
def send_outstanding_emails(step=100, num_threads=50)
|
80
|
+
success = false
|
74
81
|
raise "No Email service providers installed" unless MailSpy.esps.present?
|
75
82
|
|
83
|
+
return if MailSpy::ProcessLog.currently_processing?
|
84
|
+
current_process = MailSpy::ProcessLog.create!(
|
85
|
+
{
|
86
|
+
:start => Time.now,
|
87
|
+
:running => true,
|
88
|
+
})
|
89
|
+
|
76
90
|
wq = WorkQueue.new(num_threads, step*2)
|
77
91
|
current_time = DateTime.now
|
78
92
|
offset = 0
|
@@ -87,7 +101,7 @@ module MailSpy
|
|
87
101
|
|
88
102
|
while true
|
89
103
|
emails = MailSpy::Email.
|
90
|
-
limit(step).offset(offset).
|
104
|
+
limit(step).offset(offset).asc(:_id).
|
91
105
|
where(:schedule_at.lte => current_time, :sent => false, :failed => false).collect
|
92
106
|
break if emails.count <= 0 #returns enumerator which is never blank
|
93
107
|
emails.each do |email|
|
@@ -104,13 +118,25 @@ module MailSpy
|
|
104
118
|
end
|
105
119
|
end
|
106
120
|
end
|
121
|
+
|
107
122
|
# We must join here otherwise the next loop email lookup will be in a
|
108
123
|
# race condition with the results of our worker_queue.
|
109
124
|
wq.join
|
110
125
|
offset += step
|
111
126
|
end
|
112
127
|
|
113
|
-
|
128
|
+
success = true
|
129
|
+
return sent
|
130
|
+
|
131
|
+
ensure
|
132
|
+
if current_process
|
133
|
+
end_time = Time.now
|
134
|
+
current_process.end = end_time
|
135
|
+
current_process.seconds_elapsed = end_time.to_i - current_process.start.to_i
|
136
|
+
current_process.running = false
|
137
|
+
current_process.success = success
|
138
|
+
current_process.save!
|
139
|
+
end
|
114
140
|
end
|
115
141
|
|
116
142
|
|
data/lib/mail_spy/version.rb
CHANGED
data/test/dummy/db/seeds.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
(0..10).each do |i|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
2
|
+
3.times.each do
|
3
|
+
MailSpy::Email.create!(
|
4
|
+
{
|
5
|
+
:email_address => "trcarden@gmail.com",
|
6
|
+
:user_id => 1,
|
7
|
+
:campaign => "testCampaign#{i%2}",
|
8
|
+
:stream => "testStream#{i}",
|
9
|
+
:component => "a",
|
10
|
+
:email_service_provider => 'sendgrid',
|
11
|
+
:actions => [
|
12
|
+
{:action_type => "open"},
|
13
|
+
{:action_type => "delivered"}
|
14
|
+
]
|
15
|
+
}
|
16
|
+
)
|
17
|
+
end
|
15
18
|
end
|
16
19
|
|