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.
Files changed (204) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +5 -0
  3. data/.rspec +1 -0
  4. data/.ruby-version +1 -1
  5. data/Gemfile +27 -10
  6. data/LICENSE.txt +2 -2
  7. data/MIT-LICENSE +1 -1
  8. data/README.md +97 -15
  9. data/{features/bounce_management.feature → app/assets/images/mail_manager/.gitkeep} +0 -0
  10. data/app/assets/images/mail_manager/BottomRight.gif +0 -0
  11. data/app/assets/images/mail_manager/MidRight.gif +0 -0
  12. data/app/assets/images/mail_manager/TopCenter.gif +0 -0
  13. data/app/assets/images/mail_manager/TopRight.gif +0 -0
  14. data/app/assets/images/mail_manager/calendar_date_select/calendar.gif +0 -0
  15. data/app/assets/images/mail_manager/iReach_logo.gif +0 -0
  16. data/app/assets/images/mail_manager/spacer.gif +0 -0
  17. data/app/assets/images/mail_manager/topMid.gif +0 -0
  18. data/app/assets/javascripts/mail_manager/application.js +19 -1
  19. data/app/assets/javascripts/mail_manager/jquery-ui-timepicker-addon.js +2134 -0
  20. data/app/assets/stylesheets/mail_manager/admin.css +261 -0
  21. data/app/assets/stylesheets/mail_manager/application.css +3 -1
  22. data/app/assets/stylesheets/mail_manager/nav.css +68 -0
  23. data/app/assets/stylesheets/mail_manager/timepicker.css +11 -0
  24. data/app/controllers/mail_manager/application_controller.rb +7 -2
  25. data/app/controllers/mail_manager/bounces_controller.rb +5 -10
  26. data/app/controllers/mail_manager/contacts_controller.rb +42 -20
  27. data/app/controllers/mail_manager/mailing_lists_controller.rb +5 -12
  28. data/app/controllers/mail_manager/mailings_controller.rb +18 -18
  29. data/app/controllers/mail_manager/messages_controller.rb +3 -10
  30. data/app/controllers/mail_manager/subscriptions_controller.rb +16 -75
  31. data/app/helpers/mail_manager/layout_helper.rb +43 -0
  32. data/app/models/mail_manager/bounce.rb +16 -5
  33. data/app/models/mail_manager/contact.rb +64 -1
  34. data/app/models/mail_manager/mailable.rb +14 -0
  35. data/app/models/mail_manager/mailer.rb +48 -81
  36. data/app/models/mail_manager/mailing.rb +23 -42
  37. data/app/models/mail_manager/message.rb +52 -8
  38. data/app/models/mail_manager/subscription.rb +9 -3
  39. data/app/models/status_history.rb +3 -2
  40. data/app/views/layouts/mail_manager/application.html.erb +33 -5
  41. data/app/views/layouts/mail_manager/layout.html.erb +15 -0
  42. data/app/views/mail_manager/bounces/index.html.erb +6 -4
  43. data/app/views/mail_manager/bounces/show.html.erb +3 -3
  44. data/app/views/mail_manager/contacts/_form.html.erb +7 -23
  45. data/app/views/mail_manager/contacts/edit.html.erb +3 -3
  46. data/app/views/mail_manager/contacts/index.html.erb +14 -28
  47. data/app/views/mail_manager/contacts/new.html.erb +2 -2
  48. data/app/views/mail_manager/contacts/show.html.erb +5 -5
  49. data/app/views/mail_manager/contacts/subscribe.html.erb +1 -1
  50. data/app/views/mail_manager/mailer/double_opt_in.erb +1 -1
  51. data/app/views/mail_manager/mailer/double_opt_in.html.erb +6 -0
  52. data/app/views/mail_manager/mailer/unsubscribed.erb +1 -1
  53. data/app/views/mail_manager/mailer/unsubscribed.html.erb +1 -1
  54. data/app/views/mail_manager/mailing_lists/_form.html.erb +8 -17
  55. data/app/views/mail_manager/mailing_lists/edit.html.erb +4 -4
  56. data/app/views/mail_manager/mailing_lists/index.html.erb +6 -5
  57. data/app/views/mail_manager/mailing_lists/new.html.erb +3 -3
  58. data/app/views/mail_manager/mailings/_form.html.erb +22 -44
  59. data/app/views/mail_manager/mailings/edit.html.erb +3 -3
  60. data/app/views/mail_manager/mailings/index.html.erb +23 -27
  61. data/app/views/mail_manager/mailings/new.html.erb +2 -2
  62. data/app/views/mail_manager/mailings/test.html.erb +3 -3
  63. data/app/views/mail_manager/messages/index.html.erb +2 -2
  64. data/app/views/mail_manager/subscriptions/_form.html.erb +1 -1
  65. data/app/views/mail_manager/subscriptions/_subscriptions.html.erb +2 -2
  66. data/app/views/mail_manager/subscriptions/edit.html.erb +2 -2
  67. data/app/views/mail_manager/subscriptions/index.html.erb +3 -3
  68. data/app/views/mail_manager/subscriptions/new.html.erb +1 -1
  69. data/app/views/mail_manager/subscriptions/unsubscribe.html.erb +1 -1
  70. data/app/views/mail_manager/subscriptions/unsubscribe_by_email_address.html.erb +3 -3
  71. data/config/locales/en.yml +13 -0
  72. data/config/locales/mailings.en.yml +52 -0
  73. data/config/routes.rb +21 -19
  74. data/db/migrate/008_add_bounces_count_to_mailings.rb +14 -0
  75. data/db/migrate/009_add_messages_count_to_mailings.rb +14 -0
  76. data/db/migrate/010_add_login_token_to_contact.rb +11 -0
  77. data/db/migrate/011_add_deleted_at_to_mailing.rb +11 -0
  78. data/lib/delayed/mailer.rb +9 -5
  79. data/lib/delayed/status.rb +6 -2
  80. data/lib/delayed_overrides/worker.rb +21 -0
  81. data/lib/deleteable.rb +13 -14
  82. data/lib/mail_manager/config.rb +3 -3
  83. data/lib/mail_manager/engine.rb +136 -7
  84. data/lib/mail_manager/lock.rb +1 -0
  85. data/lib/mail_manager/version.rb +1 -1
  86. data/lib/tasks/mail_manager.rake +92 -56
  87. data/mail_manager.gemspec +4 -0
  88. data/spec/rails_helper.rb +50 -0
  89. data/spec/spec_helper.rb +87 -48
  90. data/spec/test_app/.env.development +3 -0
  91. data/spec/test_app/.env.test +2 -0
  92. data/spec/test_app/.rspec +1 -0
  93. data/spec/test_app/Procfile +3 -0
  94. data/spec/test_app/app/controllers/application_controller.rb +4 -0
  95. data/spec/test_app/app/models/ability.rb +7 -0
  96. data/spec/test_app/app/models/user.rb +8 -2
  97. data/spec/test_app/app/models/user_with_role.rb +22 -0
  98. data/spec/test_app/config/database.postgres.yml +21 -0
  99. data/spec/test_app/config/database.sqlite.yml +2 -2
  100. data/spec/test_app/config/environment.rb +2 -2
  101. data/spec/test_app/config/environments/test.rb +13 -0
  102. data/spec/test_app/config/mail_manager.yml +66 -2
  103. data/spec/test_app/config/routes.rb +0 -1
  104. data/spec/test_app/db/migrate/20150420163235_add_bounces_count_to_mailings.rb +14 -0
  105. data/spec/test_app/db/migrate/20150420163804_add_messages_count_to_mailings.rb +14 -0
  106. data/spec/test_app/db/migrate/20150421151457_add_login_token_to_contact.rb +11 -0
  107. data/spec/test_app/db/migrate/20150423143754_add_deleted_at_to_mailing.rb +11 -0
  108. data/spec/test_app/db/schema.rb +10 -5
  109. data/spec/test_app/db/structure.sql +150 -15
  110. data/spec/test_app/features/bounce_management.feature +11 -0
  111. data/spec/test_app/features/contact_management.feature +91 -0
  112. data/{features → spec/test_app/features}/mailable.feature +3 -1
  113. data/spec/test_app/features/mailing_list_management.feature +39 -0
  114. data/spec/test_app/features/mailing_management.feature +60 -0
  115. data/{features → spec/test_app/features}/message.feature +4 -4
  116. data/spec/test_app/features/message_management.feature +22 -0
  117. data/spec/test_app/features/step_definitions/bounce_steps.rb +4 -0
  118. data/spec/test_app/features/step_definitions/contact_steps.rb +63 -0
  119. data/spec/test_app/features/step_definitions/debugging_steps.rb +3 -0
  120. data/spec/test_app/features/step_definitions/email_steps.rb +6 -0
  121. data/spec/test_app/features/step_definitions/job_steps.rb +25 -0
  122. data/spec/test_app/features/step_definitions/login_steps.rb +4 -0
  123. data/spec/test_app/features/step_definitions/mailing_list.rb +17 -0
  124. data/spec/test_app/features/step_definitions/mailing_steps.rb +51 -0
  125. data/spec/test_app/features/step_definitions/subscription_steps.rb +26 -0
  126. data/{features → spec/test_app/features}/step_definitions/webrat_steps.rb +10 -6
  127. data/spec/test_app/features/subscription_management.feature +62 -0
  128. data/spec/test_app/features/support/env.rb +37 -0
  129. data/spec/test_app/features/support/paths.rb +36 -0
  130. data/spec/test_app/lib/debugging.rb +61 -0
  131. data/spec/test_app/lib/post_office_manager.rb +71 -0
  132. data/spec/test_app/public/subscribe.html +40 -0
  133. data/spec/test_app/script/full_suite +50 -0
  134. data/spec/test_app/script/post_office +25 -0
  135. data/spec/test_app/script/rails +20 -0
  136. data/spec/test_app/script/rspec_multi_db +34 -0
  137. data/spec/test_app/spec/controllers/mail_manager/bounces_controller_spec.rb +59 -0
  138. data/spec/test_app/spec/controllers/mail_manager/contacts_controller_spec.rb +178 -0
  139. data/spec/test_app/spec/controllers/mail_manager/mailing_lists_controller_spec.rb +164 -0
  140. data/spec/test_app/spec/controllers/mail_manager/mailings_controller_spec.rb +184 -0
  141. data/spec/test_app/spec/controllers/users_controller_spec.rb +47 -46
  142. data/spec/test_app/spec/factories/_functions.rb +27 -0
  143. data/spec/test_app/spec/factories/contacts.rb +7 -0
  144. data/spec/test_app/spec/factories/mail_manager_bounces.rb +13 -0
  145. data/spec/test_app/spec/factories/mailable.rb +8 -0
  146. data/spec/test_app/spec/factories/mailings.rb +7 -1
  147. data/spec/test_app/spec/factories/message.rb +7 -0
  148. data/spec/test_app/spec/factories/users.rb +19 -7
  149. data/spec/test_app/spec/features/mail_manager/bounce_spec.rb +73 -0
  150. data/spec/test_app/spec/features/mail_manager/double_opt_in_spec.rb +62 -0
  151. data/spec/test_app/spec/features/mail_manager/mailing_spec.rb +46 -0
  152. data/spec/test_app/spec/features/navigation_spec.rb +9 -0
  153. data/spec/test_app/spec/helpers/mail_manager/layout_helper_spec.rb +41 -0
  154. data/spec/test_app/spec/helpers/mail_manager/subscriptions_helper_spec.rb +14 -0
  155. data/spec/test_app/spec/models/delayed/mailer_spec.rb +27 -0
  156. data/spec/test_app/spec/models/delayed/status_job_spec.rb +13 -0
  157. data/spec/test_app/spec/models/delayed/status_spec.rb +37 -0
  158. data/spec/test_app/spec/models/mail_manager/bounce_spec.rb +23 -3
  159. data/spec/test_app/spec/models/mail_manager/engine_spec.rb +79 -0
  160. data/spec/test_app/spec/models/mail_manager/mailable_spec.rb +10 -0
  161. data/spec/test_app/spec/models/mail_manager/mailer_spec.rb +35 -3
  162. data/spec/test_app/spec/models/mail_manager/mailing_list_spec.rb +5 -5
  163. data/spec/test_app/spec/models/mail_manager/mailing_spec.rb +58 -0
  164. data/spec/test_app/spec/models/mail_manager/message_spec.rb +112 -0
  165. data/spec/test_app/spec/models/user_spec.rb +10 -8
  166. data/spec/test_app/spec/rails_helper.rb +86 -0
  167. data/spec/test_app/spec/requests/users_spec.rb +3 -3
  168. data/spec/test_app/spec/routing/mail_manager/bounces_routing_spec.rb +27 -0
  169. data/spec/test_app/spec/routing/mail_manager/contacts_routing_spec.rb +36 -0
  170. data/spec/test_app/spec/routing/mail_manager/mailing_lists_routing_spec.rb +36 -0
  171. data/spec/test_app/spec/routing/mail_manager/mailings_routing_spec.rb +36 -0
  172. data/spec/test_app/spec/spec_helper.rb +82 -32
  173. data/spec/test_app/spec/support/continuance.rb +18 -0
  174. data/spec/test_app/spec/support/custom_matchers.rb +17 -0
  175. data/spec/test_app/spec/support/database_cleaner.rb +10 -1
  176. data/spec/test_app/spec/views/mail_manager/bounces/index.html.erb_spec.rb +32 -0
  177. data/spec/test_app/spec/views/mail_manager/bounces/show.html.erb_spec.rb +12 -0
  178. data/spec/test_app/spec/views/users/edit.html.erb_spec.rb +8 -5
  179. data/spec/test_app/spec/views/users/index.html.erb_spec.rb +10 -19
  180. data/spec/test_app/spec/views/users/new.html.erb_spec.rb +9 -6
  181. data/spec/test_app/spec/views/users/show.html.erb_spec.rb +8 -9
  182. metadata +231 -75
  183. data/.DS_Store +0 -0
  184. data/README.rdoc +0 -3
  185. data/app/.DS_Store +0 -0
  186. data/app/controllers/mail_manager/base_controller.rb +0 -22
  187. data/app/models/.DS_Store +0 -0
  188. data/features/contact_management.feature +0 -24
  189. data/features/mailing_management.feature +0 -78
  190. data/features/step_definitions/email_steps.rb +0 -50
  191. data/features/step_definitions/mlm_steps.rb +0 -11
  192. data/features/step_definitions/pickle_steps.rb +0 -41
  193. data/features/subscription_management.feature +0 -17
  194. data/features/support/env.rb +0 -11
  195. data/features/support/paths.rb +0 -44
  196. data/lib/tasks/mail_manager_tasks.rake +0 -4
  197. data/lib/tasks/rspec.rake +0 -165
  198. data/spec/test_app/bin/cucumber +0 -7
  199. data/spec/test_app/bin/rails +0 -10
  200. data/spec/test_app/bin/rake +0 -7
  201. data/spec/test_app/bin/rspec +0 -7
  202. data/spec/test_app/bin/spring +0 -18
  203. data/spec/test_app/spec/routing/users_routing_spec.rb +0 -35
  204. 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 < ?) OR status='resumed'",Time.now.utc]}}
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','paused','resumed','cancelled','completed'],'pending')
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','paused'].include?(status.to_s)
207
+ ['pending','scheduled'].include?(status.to_s)
221
208
  end
222
209
 
223
210
  def can_cancel?
224
- ['pending','scheduled','processing','paused','resumed'].include?(status.to_s)
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
- # Delayed::Job.active.find(:all, :conditions => ["handler like ?","MailMgr::Mailing"])
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 resume
257
- raise "Unable to resume" unless can_resume?
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
- contact.full_name
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
- contact.email_address
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
- contact.try(:contactable)
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 contact.respond_to?(method)
102
- substitutions_hash[method_key] = contact.send(method)
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
- "#{contact.id}-#{subscription.try(:id)}-#{self.id}-#{Digest::SHA1.hexdigest("#{contact.id}-#{subscription.try(:id)}-#{self.id}-#{MailManager.secret}")}")
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
- self[:status] = default_status
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
- <title>MailManager</title>
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
- <%= yield %>
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;" %>&nbsp;</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
- <% title "Listing Bounces for #{@mailing.try(:subject)}" %>
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
- Mailing: <%= select_tag "mailing_id", options_for_select(@mailings.collect{|mailing| ["#{mailing.subject} (#{l mailing.status_changed_at}) (#{mailing.bounce_count})",mailing.id.to_s]},params[:mailing_id].to_i), :include_blank => true, :onChange => "$('#search_form').submit()" %></br>
6
- Status:<%= select_tag "bounce[status]", options_for_select([['Needs Attention','needs_manual_intervention'],['Resolved','resolved']],params[:bounce][:status]), :include_blank => true, :onChange => "$('#search_form').submit()" %>
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>&nbsp;</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' %><div class="linkbuttonEnding"></div></td>
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' %><div class="linkbuttonEnding"></div>
6
+ <%= link_to "Unsubscribe", mail_manager.fail_address_bounce_path(@bounce), :class => 'button' %>
7
7
  &nbsp;
8
- <%= link_to "Dismiss", mail_manager.dismiss_bounce_path(@bounce), :class => 'button' %><div class="linkbuttonEnding"></div>
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' %><div class="linkbuttonEnding"></div>
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
- <table cellspacing='1' cellpadding='0' border='0' width="400">
4
- <tr valign='top'>
5
- <tr valign="top">
6
- <td width='150'><%= f.label :first_name %></td>
7
- <td><%= f.text_field :first_name %></td>
8
- </tr>
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
- <tr valign='top'>
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 %>