mail_manager 3.0.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -1
- data/Gemfile +27 -10
- data/LICENSE.txt +2 -2
- data/MIT-LICENSE +1 -1
- data/README.md +97 -15
- data/{features/bounce_management.feature → app/assets/images/mail_manager/.gitkeep} +0 -0
- data/app/assets/images/mail_manager/BottomRight.gif +0 -0
- data/app/assets/images/mail_manager/MidRight.gif +0 -0
- data/app/assets/images/mail_manager/TopCenter.gif +0 -0
- data/app/assets/images/mail_manager/TopRight.gif +0 -0
- data/app/assets/images/mail_manager/calendar_date_select/calendar.gif +0 -0
- data/app/assets/images/mail_manager/iReach_logo.gif +0 -0
- data/app/assets/images/mail_manager/spacer.gif +0 -0
- data/app/assets/images/mail_manager/topMid.gif +0 -0
- data/app/assets/javascripts/mail_manager/application.js +19 -1
- data/app/assets/javascripts/mail_manager/jquery-ui-timepicker-addon.js +2134 -0
- data/app/assets/stylesheets/mail_manager/admin.css +261 -0
- data/app/assets/stylesheets/mail_manager/application.css +3 -1
- data/app/assets/stylesheets/mail_manager/nav.css +68 -0
- data/app/assets/stylesheets/mail_manager/timepicker.css +11 -0
- data/app/controllers/mail_manager/application_controller.rb +7 -2
- data/app/controllers/mail_manager/bounces_controller.rb +5 -10
- data/app/controllers/mail_manager/contacts_controller.rb +42 -20
- data/app/controllers/mail_manager/mailing_lists_controller.rb +5 -12
- data/app/controllers/mail_manager/mailings_controller.rb +18 -18
- data/app/controllers/mail_manager/messages_controller.rb +3 -10
- data/app/controllers/mail_manager/subscriptions_controller.rb +16 -75
- data/app/helpers/mail_manager/layout_helper.rb +43 -0
- data/app/models/mail_manager/bounce.rb +16 -5
- data/app/models/mail_manager/contact.rb +64 -1
- data/app/models/mail_manager/mailable.rb +14 -0
- data/app/models/mail_manager/mailer.rb +48 -81
- data/app/models/mail_manager/mailing.rb +23 -42
- data/app/models/mail_manager/message.rb +52 -8
- data/app/models/mail_manager/subscription.rb +9 -3
- data/app/models/status_history.rb +3 -2
- data/app/views/layouts/mail_manager/application.html.erb +33 -5
- data/app/views/layouts/mail_manager/layout.html.erb +15 -0
- data/app/views/mail_manager/bounces/index.html.erb +6 -4
- data/app/views/mail_manager/bounces/show.html.erb +3 -3
- data/app/views/mail_manager/contacts/_form.html.erb +7 -23
- data/app/views/mail_manager/contacts/edit.html.erb +3 -3
- data/app/views/mail_manager/contacts/index.html.erb +14 -28
- data/app/views/mail_manager/contacts/new.html.erb +2 -2
- data/app/views/mail_manager/contacts/show.html.erb +5 -5
- data/app/views/mail_manager/contacts/subscribe.html.erb +1 -1
- data/app/views/mail_manager/mailer/double_opt_in.erb +1 -1
- data/app/views/mail_manager/mailer/double_opt_in.html.erb +6 -0
- data/app/views/mail_manager/mailer/unsubscribed.erb +1 -1
- data/app/views/mail_manager/mailer/unsubscribed.html.erb +1 -1
- data/app/views/mail_manager/mailing_lists/_form.html.erb +8 -17
- data/app/views/mail_manager/mailing_lists/edit.html.erb +4 -4
- data/app/views/mail_manager/mailing_lists/index.html.erb +6 -5
- data/app/views/mail_manager/mailing_lists/new.html.erb +3 -3
- data/app/views/mail_manager/mailings/_form.html.erb +22 -44
- data/app/views/mail_manager/mailings/edit.html.erb +3 -3
- data/app/views/mail_manager/mailings/index.html.erb +23 -27
- data/app/views/mail_manager/mailings/new.html.erb +2 -2
- data/app/views/mail_manager/mailings/test.html.erb +3 -3
- data/app/views/mail_manager/messages/index.html.erb +2 -2
- data/app/views/mail_manager/subscriptions/_form.html.erb +1 -1
- data/app/views/mail_manager/subscriptions/_subscriptions.html.erb +2 -2
- data/app/views/mail_manager/subscriptions/edit.html.erb +2 -2
- data/app/views/mail_manager/subscriptions/index.html.erb +3 -3
- data/app/views/mail_manager/subscriptions/new.html.erb +1 -1
- data/app/views/mail_manager/subscriptions/unsubscribe.html.erb +1 -1
- data/app/views/mail_manager/subscriptions/unsubscribe_by_email_address.html.erb +3 -3
- data/config/locales/en.yml +13 -0
- data/config/locales/mailings.en.yml +52 -0
- data/config/routes.rb +21 -19
- data/db/migrate/008_add_bounces_count_to_mailings.rb +14 -0
- data/db/migrate/009_add_messages_count_to_mailings.rb +14 -0
- data/db/migrate/010_add_login_token_to_contact.rb +11 -0
- data/db/migrate/011_add_deleted_at_to_mailing.rb +11 -0
- data/lib/delayed/mailer.rb +9 -5
- data/lib/delayed/status.rb +6 -2
- data/lib/delayed_overrides/worker.rb +21 -0
- data/lib/deleteable.rb +13 -14
- data/lib/mail_manager/config.rb +3 -3
- data/lib/mail_manager/engine.rb +136 -7
- data/lib/mail_manager/lock.rb +1 -0
- data/lib/mail_manager/version.rb +1 -1
- data/lib/tasks/mail_manager.rake +92 -56
- data/mail_manager.gemspec +4 -0
- data/spec/rails_helper.rb +50 -0
- data/spec/spec_helper.rb +87 -48
- data/spec/test_app/.env.development +3 -0
- data/spec/test_app/.env.test +2 -0
- data/spec/test_app/.rspec +1 -0
- data/spec/test_app/Procfile +3 -0
- data/spec/test_app/app/controllers/application_controller.rb +4 -0
- data/spec/test_app/app/models/ability.rb +7 -0
- data/spec/test_app/app/models/user.rb +8 -2
- data/spec/test_app/app/models/user_with_role.rb +22 -0
- data/spec/test_app/config/database.postgres.yml +21 -0
- data/spec/test_app/config/database.sqlite.yml +2 -2
- data/spec/test_app/config/environment.rb +2 -2
- data/spec/test_app/config/environments/test.rb +13 -0
- data/spec/test_app/config/mail_manager.yml +66 -2
- data/spec/test_app/config/routes.rb +0 -1
- data/spec/test_app/db/migrate/20150420163235_add_bounces_count_to_mailings.rb +14 -0
- data/spec/test_app/db/migrate/20150420163804_add_messages_count_to_mailings.rb +14 -0
- data/spec/test_app/db/migrate/20150421151457_add_login_token_to_contact.rb +11 -0
- data/spec/test_app/db/migrate/20150423143754_add_deleted_at_to_mailing.rb +11 -0
- data/spec/test_app/db/schema.rb +10 -5
- data/spec/test_app/db/structure.sql +150 -15
- data/spec/test_app/features/bounce_management.feature +11 -0
- data/spec/test_app/features/contact_management.feature +91 -0
- data/{features → spec/test_app/features}/mailable.feature +3 -1
- data/spec/test_app/features/mailing_list_management.feature +39 -0
- data/spec/test_app/features/mailing_management.feature +60 -0
- data/{features → spec/test_app/features}/message.feature +4 -4
- data/spec/test_app/features/message_management.feature +22 -0
- data/spec/test_app/features/step_definitions/bounce_steps.rb +4 -0
- data/spec/test_app/features/step_definitions/contact_steps.rb +63 -0
- data/spec/test_app/features/step_definitions/debugging_steps.rb +3 -0
- data/spec/test_app/features/step_definitions/email_steps.rb +6 -0
- data/spec/test_app/features/step_definitions/job_steps.rb +25 -0
- data/spec/test_app/features/step_definitions/login_steps.rb +4 -0
- data/spec/test_app/features/step_definitions/mailing_list.rb +17 -0
- data/spec/test_app/features/step_definitions/mailing_steps.rb +51 -0
- data/spec/test_app/features/step_definitions/subscription_steps.rb +26 -0
- data/{features → spec/test_app/features}/step_definitions/webrat_steps.rb +10 -6
- data/spec/test_app/features/subscription_management.feature +62 -0
- data/spec/test_app/features/support/env.rb +37 -0
- data/spec/test_app/features/support/paths.rb +36 -0
- data/spec/test_app/lib/debugging.rb +61 -0
- data/spec/test_app/lib/post_office_manager.rb +71 -0
- data/spec/test_app/public/subscribe.html +40 -0
- data/spec/test_app/script/full_suite +50 -0
- data/spec/test_app/script/post_office +25 -0
- data/spec/test_app/script/rails +20 -0
- data/spec/test_app/script/rspec_multi_db +34 -0
- data/spec/test_app/spec/controllers/mail_manager/bounces_controller_spec.rb +59 -0
- data/spec/test_app/spec/controllers/mail_manager/contacts_controller_spec.rb +178 -0
- data/spec/test_app/spec/controllers/mail_manager/mailing_lists_controller_spec.rb +164 -0
- data/spec/test_app/spec/controllers/mail_manager/mailings_controller_spec.rb +184 -0
- data/spec/test_app/spec/controllers/users_controller_spec.rb +47 -46
- data/spec/test_app/spec/factories/_functions.rb +27 -0
- data/spec/test_app/spec/factories/contacts.rb +7 -0
- data/spec/test_app/spec/factories/mail_manager_bounces.rb +13 -0
- data/spec/test_app/spec/factories/mailable.rb +8 -0
- data/spec/test_app/spec/factories/mailings.rb +7 -1
- data/spec/test_app/spec/factories/message.rb +7 -0
- data/spec/test_app/spec/factories/users.rb +19 -7
- data/spec/test_app/spec/features/mail_manager/bounce_spec.rb +73 -0
- data/spec/test_app/spec/features/mail_manager/double_opt_in_spec.rb +62 -0
- data/spec/test_app/spec/features/mail_manager/mailing_spec.rb +46 -0
- data/spec/test_app/spec/features/navigation_spec.rb +9 -0
- data/spec/test_app/spec/helpers/mail_manager/layout_helper_spec.rb +41 -0
- data/spec/test_app/spec/helpers/mail_manager/subscriptions_helper_spec.rb +14 -0
- data/spec/test_app/spec/models/delayed/mailer_spec.rb +27 -0
- data/spec/test_app/spec/models/delayed/status_job_spec.rb +13 -0
- data/spec/test_app/spec/models/delayed/status_spec.rb +37 -0
- data/spec/test_app/spec/models/mail_manager/bounce_spec.rb +23 -3
- data/spec/test_app/spec/models/mail_manager/engine_spec.rb +79 -0
- data/spec/test_app/spec/models/mail_manager/mailable_spec.rb +10 -0
- data/spec/test_app/spec/models/mail_manager/mailer_spec.rb +35 -3
- data/spec/test_app/spec/models/mail_manager/mailing_list_spec.rb +5 -5
- data/spec/test_app/spec/models/mail_manager/mailing_spec.rb +58 -0
- data/spec/test_app/spec/models/mail_manager/message_spec.rb +112 -0
- data/spec/test_app/spec/models/user_spec.rb +10 -8
- data/spec/test_app/spec/rails_helper.rb +86 -0
- data/spec/test_app/spec/requests/users_spec.rb +3 -3
- data/spec/test_app/spec/routing/mail_manager/bounces_routing_spec.rb +27 -0
- data/spec/test_app/spec/routing/mail_manager/contacts_routing_spec.rb +36 -0
- data/spec/test_app/spec/routing/mail_manager/mailing_lists_routing_spec.rb +36 -0
- data/spec/test_app/spec/routing/mail_manager/mailings_routing_spec.rb +36 -0
- data/spec/test_app/spec/spec_helper.rb +82 -32
- data/spec/test_app/spec/support/continuance.rb +18 -0
- data/spec/test_app/spec/support/custom_matchers.rb +17 -0
- data/spec/test_app/spec/support/database_cleaner.rb +10 -1
- data/spec/test_app/spec/views/mail_manager/bounces/index.html.erb_spec.rb +32 -0
- data/spec/test_app/spec/views/mail_manager/bounces/show.html.erb_spec.rb +12 -0
- data/spec/test_app/spec/views/users/edit.html.erb_spec.rb +8 -5
- data/spec/test_app/spec/views/users/index.html.erb_spec.rb +10 -19
- data/spec/test_app/spec/views/users/new.html.erb_spec.rb +9 -6
- data/spec/test_app/spec/views/users/show.html.erb_spec.rb +8 -9
- metadata +231 -75
- data/.DS_Store +0 -0
- data/README.rdoc +0 -3
- data/app/.DS_Store +0 -0
- data/app/controllers/mail_manager/base_controller.rb +0 -22
- data/app/models/.DS_Store +0 -0
- data/features/contact_management.feature +0 -24
- data/features/mailing_management.feature +0 -78
- data/features/step_definitions/email_steps.rb +0 -50
- data/features/step_definitions/mlm_steps.rb +0 -11
- data/features/step_definitions/pickle_steps.rb +0 -41
- data/features/subscription_management.feature +0 -17
- data/features/support/env.rb +0 -11
- data/features/support/paths.rb +0 -44
- data/lib/tasks/mail_manager_tasks.rake +0 -4
- data/lib/tasks/rspec.rake +0 -165
- data/spec/test_app/bin/cucumber +0 -7
- data/spec/test_app/bin/rails +0 -10
- data/spec/test_app/bin/rake +0 -7
- data/spec/test_app/bin/rspec +0 -7
- data/spec/test_app/bin/spring +0 -18
- data/spec/test_app/spec/routing/users_routing_spec.rb +0 -35
- data/spec/test_app/spec/support/post_office.rb +0 -13
@@ -26,25 +26,18 @@ module MailManager
|
|
26
26
|
|
27
27
|
accepts_nested_attributes_for :mailable
|
28
28
|
|
29
|
+
include Deleteable if (column_names.include?('deleted_at') rescue false)
|
30
|
+
|
29
31
|
attr_accessor :bounce_count
|
30
32
|
|
31
33
|
validates_presence_of :subject
|
32
34
|
#validates_presence_of :mailable
|
33
35
|
|
34
|
-
scope :ready, lambda {{:conditions => ["(status='scheduled' AND scheduled_at < ?)
|
36
|
+
scope :ready, lambda {{:conditions => ["(status='scheduled' AND scheduled_at < ?)",Time.now.utc]}}
|
35
37
|
scope :by_statuses, lambda {|*statuses| {:conditions => ["status in (#{statuses.collect{|bindings,status| '?'}.join(",")})",statuses].flatten}}
|
36
38
|
|
37
|
-
def self.with_bounces(bounce_status=nil)
|
38
|
-
bounce_status_condition = bounce_status.present? ? ActiveRecord::Base.send(:sanitize_sql_array,[" WHERE status=?", bounce_status]) : ''
|
39
|
-
bounce_query = "SELECT mailing_id, COUNT(id) AS count from #{MailManager.table_prefix}bounces #{bounce_status_condition} group by mailing_id"
|
40
|
-
bounce_data = Bounce.connection.execute(bounce_query).inject({}){|hash,(mailing_id,count)| hash.merge(mailing_id => count)}
|
41
|
-
mailings = scoped
|
42
|
-
mailings = mailings.where("id in (#{bounce_data.keys.select(&:present?).join(',')})") if bounce_data.keys.select(&:present?).present?
|
43
|
-
mailings.order("created_at desc").map{|mailing| mailing.bounce_count = bounce_data[mailing.id]; mailing}
|
44
|
-
end
|
45
|
-
|
46
39
|
include StatusHistory
|
47
|
-
override_statuses(['pending','scheduled','processing','
|
40
|
+
override_statuses(['pending','scheduled','processing','cancelled','completed'],'pending')
|
48
41
|
before_create :set_default_status
|
49
42
|
|
50
43
|
attr_protected :id
|
@@ -78,9 +71,7 @@ module MailManager
|
|
78
71
|
begin
|
79
72
|
# use the cached mailing parts, set messages mailing to self
|
80
73
|
message.mailing=self
|
81
|
-
message.change_status(:processing)
|
82
74
|
message.deliver
|
83
|
-
message.change_status(:sent)
|
84
75
|
rescue => e
|
85
76
|
message.result = "Error: #{e.message} - #{e.backtrace.join("\n")}"
|
86
77
|
message.change_status(:failed)
|
@@ -212,24 +203,16 @@ module MailManager
|
|
212
203
|
self.mailing_lists = mailing_list_ids.collect{|mailing_list_id| MailingList.find_by_id(mailing_list_id)}
|
213
204
|
end
|
214
205
|
|
215
|
-
def can_pause?
|
216
|
-
['processing'].include?(status.to_s)
|
217
|
-
end
|
218
|
-
|
219
206
|
def can_edit?
|
220
|
-
['pending','scheduled'
|
207
|
+
['pending','scheduled'].include?(status.to_s)
|
221
208
|
end
|
222
209
|
|
223
210
|
def can_cancel?
|
224
|
-
['pending','scheduled','processing'
|
225
|
-
end
|
226
|
-
|
227
|
-
def can_resume?
|
228
|
-
['paused'].include?(status.to_s)
|
211
|
+
['pending','scheduled','processing'].include?(status.to_s)
|
229
212
|
end
|
230
213
|
|
231
214
|
def can_schedule?
|
232
|
-
['pending'].include?(status.to_s)
|
215
|
+
['pending'].include?(status.to_s) && scheduled_at.present?
|
233
216
|
end
|
234
217
|
|
235
218
|
def schedule
|
@@ -237,30 +220,28 @@ module MailManager
|
|
237
220
|
change_status('scheduled')
|
238
221
|
delay(run_at: scheduled_at).deliver
|
239
222
|
end
|
223
|
+
|
224
|
+
def scheduled?
|
225
|
+
status.to_s.eql?('scheduled')
|
226
|
+
end
|
227
|
+
|
228
|
+
def job
|
229
|
+
mailing_jobs.first
|
230
|
+
end
|
240
231
|
|
232
|
+
def mailing_jobs
|
233
|
+
Delayed::Job.where("handler like ?","%MailManager::Mailing%#{subject}%")
|
234
|
+
end
|
235
|
+
|
241
236
|
def cancel
|
242
237
|
raise "Unable to cancel" unless can_cancel?
|
243
238
|
change_status('pending')
|
244
|
-
|
245
|
-
|
246
|
-
#Changing this to return only the jobs that match the id so I don't have to parse with YAML ... seems logical
|
247
|
-
mailing_jobs = Delayed::Job.find(:all, :conditions => ["handler like ?","%MailMgr::Mailing%"] || ["handler like ?", "%id: {job_mailing_id.to_i}\n%"])
|
248
|
-
#mailing_jobs = Delayed::Job.active.find(:all, :conditions => ["handler like ?","%MailMgr::Mailing%"])
|
249
|
-
mailing_jobs.each do |job|
|
250
|
-
#job_mailing_id = YAML::load(job.handler).object.split(':').last
|
251
|
-
#logger.debug "Job mailing id: #{job_mailing_id} - This mailing id: #{self.id} - do they match: #{job_mailing_id.to_i == self.id.to_i}"
|
252
|
-
job.destroy #if job_mailing_id.to_i == self.id.to_i
|
253
|
-
end
|
239
|
+
mailing_jobs.delete_all
|
254
240
|
end
|
255
|
-
|
256
|
-
def
|
257
|
-
|
258
|
-
change_status('resumed')
|
241
|
+
|
242
|
+
def pending?
|
243
|
+
status.to_s.eql?('pending')
|
259
244
|
end
|
260
245
|
|
261
|
-
def pause
|
262
|
-
raise "Unable to pause" unless can_pause?
|
263
|
-
change_status('paused')
|
264
|
-
end
|
265
246
|
end
|
266
247
|
end
|
@@ -15,7 +15,7 @@ failed - either the message couldn't be handed to the Email Server or it has bee
|
|
15
15
|
module MailManager
|
16
16
|
class Message < ActiveRecord::Base
|
17
17
|
self.table_name = "#{MailManager.table_prefix}messages"
|
18
|
-
belongs_to :mailing, :class_name => 'MailManager::Mailing'
|
18
|
+
belongs_to :mailing, :class_name => 'MailManager::Mailing', counter_cache: true
|
19
19
|
belongs_to :subscription, :class_name => 'MailManager::Subscription'
|
20
20
|
has_many :bounces, :class_name => 'MailManager::Bounce'
|
21
21
|
belongs_to :contact, :class_name => 'MailManager::Contact'
|
@@ -28,6 +28,10 @@ module MailManager
|
|
28
28
|
scope :sent, :conditions => ["status=?", 'sent']
|
29
29
|
scope :processing, :conditions => ["status=?", 'processing']
|
30
30
|
|
31
|
+
before_save :fix_counter_cache, if: lambda {|message| !message.new_record? &&
|
32
|
+
message.mailing_id_changed?
|
33
|
+
}
|
34
|
+
|
31
35
|
attr_protected :id
|
32
36
|
|
33
37
|
def initialize(*args)
|
@@ -36,7 +40,7 @@ module MailManager
|
|
36
40
|
end
|
37
41
|
|
38
42
|
scope :search, lambda{|params|
|
39
|
-
conditions = ["1"]
|
43
|
+
conditions = ["1=1"]
|
40
44
|
if params[:mailing_id]
|
41
45
|
conditions[0] += " AND #{MailManager.table_prefix}messages.mailing_id=?"
|
42
46
|
conditions << params[:mailing_id]
|
@@ -56,6 +60,9 @@ module MailManager
|
|
56
60
|
before_create :set_default_status
|
57
61
|
after_create :generate_guid
|
58
62
|
|
63
|
+
# returns a string in the form of "contact name" <email@example.com> if
|
64
|
+
# the contact's full name returns anything ... or simply email@example.com if
|
65
|
+
# there is no name at all
|
59
66
|
def email_address_with_name
|
60
67
|
return %Q|"#{full_name}" <#{email_address}>|.gsub(/\s+/,' ') unless full_name.eql?('')
|
61
68
|
email_address
|
@@ -63,22 +70,50 @@ module MailManager
|
|
63
70
|
|
64
71
|
# sends the message through Mailer
|
65
72
|
def deliver
|
73
|
+
# lock only needed until status is updated
|
74
|
+
Lock.with_lock("deliver_message_#{self.id}") do
|
75
|
+
reload
|
76
|
+
if can_deliver?
|
77
|
+
change_status(:processing)
|
78
|
+
else
|
79
|
+
Rails.logger.warn "Message(#{self.id})'s is no longer suitable to deliver.. staus: #{status}"
|
80
|
+
end
|
81
|
+
end
|
66
82
|
MailManager::Mailer.deliver_message(self)
|
67
83
|
change_status(:sent)
|
84
|
+
# allow other errors to bubble up
|
85
|
+
rescue MailManager::LockException => e
|
86
|
+
Rails.logger.warn "Locking error while trying to send MailManager::Message(#{id}) leaving in #{status} status"
|
87
|
+
end
|
88
|
+
|
89
|
+
# whether or not you can deliver a message
|
90
|
+
def can_deliver?
|
91
|
+
['ready','pending'].include?(status)
|
92
|
+
end
|
93
|
+
|
94
|
+
# return a contact whether its deleted or not
|
95
|
+
def active_or_deleted_contact
|
96
|
+
@active_or_deleted_contact ||= self.contact || MailManager::Contact.unscoped.
|
97
|
+
where(id: self.contact_id).first
|
68
98
|
end
|
69
99
|
|
100
|
+
# returns the contact's full name
|
70
101
|
def full_name
|
71
|
-
|
102
|
+
active_or_deleted_contact.try(:full_name)
|
72
103
|
end
|
73
104
|
|
105
|
+
# returns the contact's email address
|
74
106
|
def email_address
|
75
|
-
|
107
|
+
active_or_deleted_contact.try(:email_address)
|
76
108
|
end
|
77
109
|
|
110
|
+
# returns the mailings subject
|
78
111
|
def subject
|
79
112
|
mailing.subject
|
80
113
|
end
|
81
114
|
|
115
|
+
# the "From: " email address for the email
|
116
|
+
# lazy sets the from email addres if not present from the mailing
|
82
117
|
def from_email_address
|
83
118
|
return self[:from_email_address] if self[:from_email_address].present?
|
84
119
|
self.update_attribute(:from_email_address,mailing.from_email_address)
|
@@ -90,16 +125,18 @@ module MailManager
|
|
90
125
|
@parts ||= mailing.parts(substitutions)
|
91
126
|
end
|
92
127
|
|
128
|
+
# returns the contact's 'contactable' object tied to the contact
|
93
129
|
def contactable
|
94
|
-
|
130
|
+
active_or_deleted_contact.try(:contactable)
|
95
131
|
end
|
96
132
|
|
133
|
+
# returns a hash of substitutions to be used to modify the mailable's html/plaing text
|
97
134
|
def substitutions
|
98
135
|
substitutions_hash = {}
|
99
136
|
MailManager::ContactableRegistry.registered_methods.each do |method|
|
100
137
|
method_key = method.to_s.upcase
|
101
|
-
if
|
102
|
-
substitutions_hash[method_key] =
|
138
|
+
if active_or_deleted_contact.respond_to?(method)
|
139
|
+
substitutions_hash[method_key] = active_or_deleted_contact.send(method)
|
103
140
|
elsif contactable.respond_to?(method)
|
104
141
|
substitutions_hash[method_key] = contactable.send(method)
|
105
142
|
else
|
@@ -109,6 +146,7 @@ module MailManager
|
|
109
146
|
substitutions_hash.merge('UNSUBSCRIBE_URL' => unsubscribe_url)
|
110
147
|
end
|
111
148
|
|
149
|
+
# the full url to unsubscribe based on this message; including site url & guid
|
112
150
|
def unsubscribe_url
|
113
151
|
"#{MailManager.site_url}#{MailManager.unsubscribe_path}/#{guid}"
|
114
152
|
end
|
@@ -116,12 +154,18 @@ module MailManager
|
|
116
154
|
# generated the guid for which the message is identified by in transit
|
117
155
|
def generate_guid
|
118
156
|
update_attribute(:guid,
|
119
|
-
"#{
|
157
|
+
"#{active_or_deleted_contact.try(:id)}-#{subscription.try(:id)}-#{self.id}-#{Digest::SHA1.hexdigest("#{active_or_deleted_contact.try(:id)}-#{subscription.try(:id)}-#{self.id}-#{MailManager.secret}")}")
|
120
158
|
end
|
121
159
|
|
122
160
|
protected
|
161
|
+
# nodoc: set the type on create
|
123
162
|
def set_type
|
124
163
|
self[:type] = self.class.name
|
125
164
|
end
|
165
|
+
|
166
|
+
def fix_counter_cache
|
167
|
+
MailManager::Mailing.decrement_counter(:messages_count, self.mailing_id_was) if self.mailing_id_was.present?
|
168
|
+
MailManager::Mailing.increment_counter(:messages_count, self.mailing_id)
|
169
|
+
end
|
126
170
|
end
|
127
171
|
end
|
@@ -83,6 +83,10 @@ module MailManager
|
|
83
83
|
status.eql?('active')
|
84
84
|
end
|
85
85
|
|
86
|
+
def pending?
|
87
|
+
status.eql?('pending')
|
88
|
+
end
|
89
|
+
|
86
90
|
# unsubscribes a contact from all lists by looking them up through a messages GUID
|
87
91
|
# FIXME: when we add more lists and the ability to have multiple subscriptions, this should
|
88
92
|
# remove only the list that is tied in the GUID and they should be linked to their options
|
@@ -91,8 +95,7 @@ module MailManager
|
|
91
95
|
contact = message.contact
|
92
96
|
if message
|
93
97
|
begin
|
94
|
-
unsubscribed_subscriptions = self.unsubscribe_by_email_address(message.contact.email_address)
|
95
|
-
Mailer.deliver_unsubscribed(message,unsubscribed_subscriptions) unless unsubscribed_subscriptions.empty?
|
98
|
+
unsubscribed_subscriptions = self.unsubscribe_by_email_address(message.contact.email_address, message)
|
96
99
|
return unsubscribed_subscriptions
|
97
100
|
rescue => e
|
98
101
|
Rails.logger.warn "Error Unsubscribing email: #{message.contact.email_address}\n#{e.message}\n #{e.backtrace.join("\n ")}"
|
@@ -112,13 +115,16 @@ module MailManager
|
|
112
115
|
end
|
113
116
|
end
|
114
117
|
|
115
|
-
def self.unsubscribe_by_email_address(email_address)
|
118
|
+
def self.unsubscribe_by_email_address(email_address,message=nil)
|
116
119
|
subscriptions = []
|
117
120
|
Contact.find_all_by_email_address(email_address).each do |contact|
|
118
121
|
subscriptions += contact.active_subscriptions.each do |subscription|
|
119
122
|
subscription.change_status(:unsubscribed)
|
120
123
|
end
|
121
124
|
end
|
125
|
+
Mailer.delay.unsubscribed(subscriptions,email_address,
|
126
|
+
subscriptions.first.contact, message) if \
|
127
|
+
subscriptions.present?
|
122
128
|
subscriptions
|
123
129
|
end
|
124
130
|
end
|
@@ -37,7 +37,8 @@ module StatusHistory
|
|
37
37
|
|
38
38
|
def status
|
39
39
|
return self[:status].to_s unless self[:status].blank?
|
40
|
-
|
40
|
+
set_default_status
|
41
|
+
self[:status]
|
41
42
|
end
|
42
43
|
|
43
44
|
def status=(new_status)
|
@@ -50,7 +51,7 @@ module StatusHistory
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def set_default_status
|
53
|
-
return unless status.blank?
|
54
|
+
return unless self[:status].blank?
|
54
55
|
self[:status_changed_at] = Time.now.utc
|
55
56
|
self[:status] = default_status
|
56
57
|
Rails.logger.debug "Setting Default Status to #{default_status} #{self.name rescue "Not a class?"} #{self.class.name}"
|
@@ -1,14 +1,42 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html>
|
2
|
+
<html lang='en'>
|
3
3
|
<head>
|
4
|
-
|
4
|
+
<!-- iReach application.html.rb -->
|
5
|
+
<title><%= h(yield(:title) || "iReach Newsletter Manager") %></title>
|
5
6
|
<%= stylesheet_link_tag "mail_manager/application", :media => "all" %>
|
7
|
+
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/le-frog/jquery-ui.css" media="screen" rel="stylesheet" type="text/css" />
|
6
8
|
<%= javascript_include_tag "mail_manager/application" %>
|
7
9
|
<%= csrf_meta_tags %>
|
10
|
+
<%= content_for :head %>
|
8
11
|
</head>
|
9
12
|
<body>
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
<div id="top"><%= image_tag "mail_manager/iReach_logo.gif", width: "269", height:"85", style: "float: left;" %><%= image_tag "mail_manager/TopCenter.gif", width: "435", height: "85", style: "float: left;" %><%= image_tag "mail_manager/TopRight.gif", width: "62", height: "85", style: "float: right;" %> </div>
|
14
|
+
<div style="background-color: #fff;">
|
15
|
+
<div id="menu">
|
16
|
+
<ul>
|
17
|
+
<li><span onClick="$('#mailings_submenu').toggle();return false">Mailings</span>
|
18
|
+
<ul id='mailings_submenu' <%= ' style="display:none"' unless request.path =~ %r|/mail_manager| %>>
|
19
|
+
<%= content_tag(:li, link_to('Contacts', mail_manager.contacts_path)) if can?(:manage, MailManager::Contact) %>
|
20
|
+
<%= content_tag(:li, link_to('Mailings', mail_manager.mailings_path)) if can?(:manage, MailManager::Mailing) %>
|
21
|
+
<%= content_tag(:li, link_to('Mailing Lists', mail_manager.mailing_lists_path)) if can?(:manage, MailManager::MailingList) %>
|
22
|
+
<%= content_tag(:li, link_to('Bounces', mail_manager.bounces_path)) if can?(:manage, MailManager::Bounce) %>
|
23
|
+
</ul>
|
24
|
+
</li>
|
25
|
+
</ul>
|
26
|
+
</div>
|
27
|
+
<div id="page_content">
|
28
|
+
<% flash.each do |name, msg| -%>
|
29
|
+
<%= content_tag :div, msg, :id => "flash_#{name}" %>
|
30
|
+
<% end -%>
|
31
|
+
|
32
|
+
<% if show_title? -%>
|
33
|
+
<h1><%=h yield(:title) %></h1>
|
34
|
+
<% end -%>
|
35
|
+
<%= yield %>
|
36
|
+
|
37
|
+
<%= yield :page_navigation %>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
<%= image_tag "mail_manager/BottomRight.gif", width: "62", height: "85", style: "float: right;" %>
|
13
41
|
</body>
|
14
42
|
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang='en'>
|
3
|
+
<head>
|
4
|
+
<title>IReach Newsletter Archive</title>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<div id="top"><%= image_tag "mail_manager/iReach_logo.gif", width: "269", height:"85" %></div>
|
8
|
+
<div id="page_content">
|
9
|
+
<% flash.each do |name, msg| -%>
|
10
|
+
<%= content_tag :div, msg, :id => "flash_#{name}" %>
|
11
|
+
<% end -%>
|
12
|
+
<%= yield %>
|
13
|
+
</div>
|
14
|
+
</body>
|
15
|
+
</html>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
<%= title "Listing Bounces#{"for #{@mailing.subject}" if @mailing.present?}" %>
|
2
2
|
|
3
3
|
|
4
4
|
<%= form_tag mail_manager.bounces_path, :id => 'search_form', :method => 'GET' do %>
|
5
|
-
|
6
|
-
Status
|
5
|
+
<label for="mailing_id">Mailing:</label><%= select_tag "mailing_id", options_for_select(@mailings.collect{|mailing| ["#{mailing.subject} (#{l mailing.status_changed_at if mailing.status_changed_at.present?}) (#{mailing.bounces.size})",mailing.id.to_s]},params[:mailing_id].to_i), :include_blank => true, :onChange => "$('#search_form').submit()" %><br />
|
6
|
+
<label for="bounce_status">Status:</label><%= select_tag "bounce[status]", options_for_select([['Needs Attention','needs_manual_intervention'],['Resolved','resolved']],params[:bounce][:status]), :include_blank => true, :onChange => "$('#search_form').submit()" %><br />
|
7
7
|
<% end %>
|
8
8
|
<% if @bounces.length == 0 %>
|
9
9
|
<h3>No bounces found for the Mailing with given status.</h3>
|
@@ -14,6 +14,7 @@
|
|
14
14
|
<table class="list" cellpadding="1" cellspacing="0">
|
15
15
|
<tr class="title">
|
16
16
|
<td>Contact</td>
|
17
|
+
<td>Status</td>
|
17
18
|
<td>Status changed at</td>
|
18
19
|
<td>Comments</td>
|
19
20
|
<td> </td>
|
@@ -21,9 +22,10 @@
|
|
21
22
|
<% for bounce in @bounces %>
|
22
23
|
<tr class="<%= cycle('odd','even') %>">
|
23
24
|
<td><%=h bounce.contact_full_name %> <%=h bounce.contact_email_address %></td>
|
25
|
+
<td><%=h bounce.status rescue 'N/A' %></td>
|
24
26
|
<td><%=l bounce.status_changed_at rescue nil %></td>
|
25
27
|
<td><%=h bounce.comments %></td>
|
26
|
-
<td><%= link_to "View", bounce, :class => 'button'
|
28
|
+
<td><%= link_to "View", bounce, :id => "view_bounce_#{bounce.id}", :class => 'button' %></td>
|
27
29
|
</tr>
|
28
30
|
<% end %>
|
29
31
|
</table>
|
@@ -3,9 +3,9 @@
|
|
3
3
|
|
4
4
|
<% if @bounce.status.eql?('needs_manual_intervention') %>
|
5
5
|
<div>
|
6
|
-
<%= link_to "Unsubscribe", mail_manager.fail_address_bounce_path(@bounce), :class => 'button'
|
6
|
+
<%= link_to "Unsubscribe", mail_manager.fail_address_bounce_path(@bounce), :class => 'button' %>
|
7
7
|
|
8
|
-
<%= link_to "Dismiss", mail_manager.dismiss_bounce_path(@bounce), :class => 'button'
|
8
|
+
<%= link_to "Dismiss", mail_manager.dismiss_bounce_path(@bounce), :class => 'button' %>
|
9
9
|
</div>
|
10
10
|
<% end %>
|
11
11
|
|
@@ -33,6 +33,6 @@
|
|
33
33
|
<%= content_for :page_navigation do %>
|
34
34
|
<div>
|
35
35
|
<%= link_to "Back", mail_manager.bounces_path(:mailing_id => @mailing.try(:id),
|
36
|
-
:bounce => {:status => @bounce.status}), :class => 'button'
|
36
|
+
:bounce => {:status => @bounce.status}), :class => 'button' %>
|
37
37
|
</div>
|
38
38
|
<% end %>
|
@@ -1,27 +1,11 @@
|
|
1
1
|
<%= form_for @contact do |f| %>
|
2
2
|
<%= f.error_messages %>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
<tr valign='top'>
|
10
|
-
<tr valign="top">
|
11
|
-
<td width='150'><%= f.label :last_name %></td>
|
12
|
-
<td><%= f.text_field :last_name %></td>
|
13
|
-
</tr>
|
14
|
-
<tr valign='top'>
|
15
|
-
<tr valign="top">
|
16
|
-
<td width='150'><%= f.label :email_address %></td>
|
17
|
-
<td><%= f.text_field :email_address %></td>
|
18
|
-
</tr>
|
19
|
-
</table>
|
20
|
-
<table cellspacing='1' cellpadding='0' border='0' width="400">
|
3
|
+
<%= f.label :first_name %>
|
4
|
+
<%= f.text_field :first_name, :style => 'width: 300px;' %><br />
|
5
|
+
<%= f.label :last_name %>
|
6
|
+
<%= f.text_field :last_name, :style => 'width: 300px;' %><br />
|
7
|
+
<%= f.label :email_address %>
|
8
|
+
<%= f.text_field :email_address, :style => 'width: 300px;' %><br />
|
21
9
|
<%= contactable_subscriptions_selector(f) %>
|
22
|
-
|
23
|
-
<td align="right" colspan="2"><%= f.submit "Submit", :class => 'button' %><div class="buttonEnding"></div></td>
|
24
|
-
</tr>
|
25
|
-
</table>
|
26
|
-
|
10
|
+
<div class="submit_button"><%= f.submit "Submit", :class => 'button' %></div>
|
27
11
|
<% end %>
|