mail_manager 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 %>
|