mail_manager 0.0.1

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 (197) hide show
  1. checksums.yaml +15 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +20 -0
  4. data/.rspec +1 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +27 -0
  8. data/Guardfile +24 -0
  9. data/LICENSE.txt +22 -0
  10. data/MIT-LICENSE +20 -0
  11. data/Manifest.txt +141 -0
  12. data/Procfile +4 -0
  13. data/README +243 -0
  14. data/README.md +29 -0
  15. data/README.rdoc +3 -0
  16. data/Rakefile +33 -0
  17. data/app/.DS_Store +0 -0
  18. data/app/assets/javascripts/mail_manager/application.js +15 -0
  19. data/app/assets/stylesheets/mail_manager/application.css +13 -0
  20. data/app/controllers/mail_manager/application_controller.rb +4 -0
  21. data/app/controllers/mail_manager/base_controller.rb +22 -0
  22. data/app/controllers/mail_manager/bounces_controller.rb +32 -0
  23. data/app/controllers/mail_manager/contacts_controller.rb +75 -0
  24. data/app/controllers/mail_manager/mailing_lists_controller.rb +49 -0
  25. data/app/controllers/mail_manager/mailings_controller.rb +102 -0
  26. data/app/controllers/mail_manager/messages_controller.rb +30 -0
  27. data/app/controllers/mail_manager/subscriptions_controller.rb +104 -0
  28. data/app/helpers/mail_manager/application_helper.rb +4 -0
  29. data/app/helpers/mail_manager/subscriptions_helper.rb +8 -0
  30. data/app/models/.DS_Store +0 -0
  31. data/app/models/mail_manager.rb +12 -0
  32. data/app/models/mail_manager/bounce.rb +133 -0
  33. data/app/models/mail_manager/contact.rb +91 -0
  34. data/app/models/mail_manager/contactable_registry.rb +190 -0
  35. data/app/models/mail_manager/mailable_registry.rb +127 -0
  36. data/app/models/mail_manager/mailer.rb +267 -0
  37. data/app/models/mail_manager/mailing.rb +266 -0
  38. data/app/models/mail_manager/mailing_list.rb +36 -0
  39. data/app/models/mail_manager/message.rb +127 -0
  40. data/app/models/mail_manager/subscription.rb +126 -0
  41. data/app/models/mail_manager/test_message.rb +175 -0
  42. data/app/models/status_history.rb +60 -0
  43. data/app/views/layouts/mail_manager/application.html.erb +14 -0
  44. data/app/views/mail_manager/bounces/_email_parts.html.erb +30 -0
  45. data/app/views/mail_manager/bounces/index.html.erb +32 -0
  46. data/app/views/mail_manager/bounces/show.html.erb +38 -0
  47. data/app/views/mail_manager/contacts/_form.html.erb +27 -0
  48. data/app/views/mail_manager/contacts/double_opt_in.html.erb +1 -0
  49. data/app/views/mail_manager/contacts/edit.html.erb +12 -0
  50. data/app/views/mail_manager/contacts/index.html.erb +86 -0
  51. data/app/views/mail_manager/contacts/new.html.erb +9 -0
  52. data/app/views/mail_manager/contacts/show.html.erb +22 -0
  53. data/app/views/mail_manager/contacts/subscribe.html.erb +2 -0
  54. data/app/views/mail_manager/contacts/thank_you.html.erb +12 -0
  55. data/app/views/mail_manager/help/_available_email_substitutions.html.erb +5 -0
  56. data/app/views/mail_manager/mailer/double_opt_in.erb +6 -0
  57. data/app/views/mail_manager/mailer/unsubscribed.erb +5 -0
  58. data/app/views/mail_manager/mailer/unsubscribed.html.erb +5 -0
  59. data/app/views/mail_manager/mailing_lists/_form.html.erb +20 -0
  60. data/app/views/mail_manager/mailing_lists/edit.html.erb +13 -0
  61. data/app/views/mail_manager/mailing_lists/index.html.erb +39 -0
  62. data/app/views/mail_manager/mailing_lists/new.html.erb +9 -0
  63. data/app/views/mail_manager/mailing_lists/show.html.erb +13 -0
  64. data/app/views/mail_manager/mailings/_form.html.erb +81 -0
  65. data/app/views/mail_manager/mailings/edit.html.erb +12 -0
  66. data/app/views/mail_manager/mailings/index.html.erb +52 -0
  67. data/app/views/mail_manager/mailings/new.html.erb +9 -0
  68. data/app/views/mail_manager/mailings/show.html.erb +28 -0
  69. data/app/views/mail_manager/mailings/test.html.erb +12 -0
  70. data/app/views/mail_manager/messages/index.html.erb +37 -0
  71. data/app/views/mail_manager/subscriptions/_form.html.erb +37 -0
  72. data/app/views/mail_manager/subscriptions/_subscriptions.html.erb +13 -0
  73. data/app/views/mail_manager/subscriptions/edit.html.erb +11 -0
  74. data/app/views/mail_manager/subscriptions/index.html.erb +32 -0
  75. data/app/views/mail_manager/subscriptions/new.html.erb +9 -0
  76. data/app/views/mail_manager/subscriptions/show.html.erb +8 -0
  77. data/app/views/mail_manager/subscriptions/unsubscribe.html.erb +2 -0
  78. data/app/views/mail_manager/subscriptions/unsubscribe_by_email_address.html.erb +13 -0
  79. data/config/daemons.yml +5 -0
  80. data/config/routes.rb +43 -0
  81. data/db/migrate/001_mail_mgr_initial.rb +84 -0
  82. data/db/migrate/002_mail_mgr_create_contact.rb +60 -0
  83. data/db/migrate/003_mail_mgr_test_message.rb +23 -0
  84. data/db/migrate/004_add_deleted_at_to_mailing_lists.rb +15 -0
  85. data/db/migrate/005_contacts_deleted_at.rb +15 -0
  86. data/db/migrate/006_mail_mgr_mailing_list_add_defaults_to_active.rb +15 -0
  87. data/db/migrate/007_mail_mgr_message_add_from_email_address.rb +15 -0
  88. data/db/mlm_migrate/001_mlm_initial.rb +67 -0
  89. data/db/mlm_migrate/002_mailable_as_polymorphic.rb +27 -0
  90. data/db/mlm_migrate/003_contact_as_polymorphic.rb +64 -0
  91. data/db/mlm_migrate/004_bounce_mlm_mailing_id.rb +26 -0
  92. data/db/mlm_migrate/005_mlm_to_mail_mgr_scoped.rb +29 -0
  93. data/engine_plan.rb +13 -0
  94. data/features/bounce_management.feature +0 -0
  95. data/features/contact_management.feature +24 -0
  96. data/features/mailable.feature +23 -0
  97. data/features/mailing_management.feature +78 -0
  98. data/features/message.feature +11 -0
  99. data/features/step_definitions/email_steps.rb +50 -0
  100. data/features/step_definitions/mlm_steps.rb +11 -0
  101. data/features/step_definitions/pickle_steps.rb +41 -0
  102. data/features/step_definitions/webrat_steps.rb +115 -0
  103. data/features/subscription_management.feature +17 -0
  104. data/features/support/env.rb +31 -0
  105. data/features/support/paths.rb +44 -0
  106. data/lib/daemons/mail_manager.rb +38 -0
  107. data/lib/daemons/mail_manager_ctl +15 -0
  108. data/lib/deleteable.rb +50 -0
  109. data/lib/lock.rb +36 -0
  110. data/lib/mail_manager.rb +5 -0
  111. data/lib/mail_manager/config.rb +50 -0
  112. data/lib/mail_manager/engine.rb +43 -0
  113. data/lib/mail_manager/version.rb +3 -0
  114. data/lib/tasks/mail_manager.rake +143 -0
  115. data/lib/tasks/mail_manager_tasks.rake +4 -0
  116. data/lib/tasks/rspec.rake +165 -0
  117. data/lib/workers/mail_manager/bounce_job.rb +52 -0
  118. data/lib/workers/mail_manager/mailing_job.rb +30 -0
  119. data/lib/workers/mail_manager/message_job.rb +38 -0
  120. data/lib/workers/mail_manager/test_message_job.rb +37 -0
  121. data/mail_manager.gemspec +29 -0
  122. data/script/rails +8 -0
  123. data/spec/rcov.opts +2 -0
  124. data/spec/spec.opts +4 -0
  125. data/spec/spec_helper.rb +47 -0
  126. data/spec/test_app/README.rdoc +261 -0
  127. data/spec/test_app/Rakefile +7 -0
  128. data/spec/test_app/app/assets/javascripts/application.js +15 -0
  129. data/spec/test_app/app/assets/javascripts/users.js +2 -0
  130. data/spec/test_app/app/assets/stylesheets/application.css +13 -0
  131. data/spec/test_app/app/assets/stylesheets/scaffold.css +56 -0
  132. data/spec/test_app/app/assets/stylesheets/users.css +4 -0
  133. data/spec/test_app/app/controllers/application_controller.rb +3 -0
  134. data/spec/test_app/app/controllers/users_controller.rb +83 -0
  135. data/spec/test_app/app/helpers/application_helper.rb +2 -0
  136. data/spec/test_app/app/helpers/users_helper.rb +2 -0
  137. data/spec/test_app/app/models/user.rb +13 -0
  138. data/spec/test_app/app/views/layouts/application.html.erb +14 -0
  139. data/spec/test_app/app/views/users/_form.html.erb +33 -0
  140. data/spec/test_app/app/views/users/edit.html.erb +6 -0
  141. data/spec/test_app/app/views/users/index.html.erb +29 -0
  142. data/spec/test_app/app/views/users/new.html.erb +5 -0
  143. data/spec/test_app/app/views/users/show.html.erb +25 -0
  144. data/spec/test_app/config.ru +4 -0
  145. data/spec/test_app/config/application.rb +65 -0
  146. data/spec/test_app/config/boot.rb +10 -0
  147. data/spec/test_app/config/database.yml +25 -0
  148. data/spec/test_app/config/environment.rb +14 -0
  149. data/spec/test_app/config/environments/development.rb +37 -0
  150. data/spec/test_app/config/environments/production.rb +67 -0
  151. data/spec/test_app/config/environments/test.rb +37 -0
  152. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  153. data/spec/test_app/config/initializers/inflections.rb +15 -0
  154. data/spec/test_app/config/initializers/mime_types.rb +5 -0
  155. data/spec/test_app/config/initializers/secret_token.rb +7 -0
  156. data/spec/test_app/config/initializers/session_store.rb +8 -0
  157. data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
  158. data/spec/test_app/config/locales/en.yml +5 -0
  159. data/spec/test_app/config/lockable.yml +3 -0
  160. data/spec/test_app/config/mail_manager.yml +21 -0
  161. data/spec/test_app/config/routes.rb +7 -0
  162. data/spec/test_app/db/migrate/20131217101010_create_users.rb +13 -0
  163. data/spec/test_app/db/migrate/20131221064151_mail_mgr_initial.rb +84 -0
  164. data/spec/test_app/db/migrate/20131221064152_mail_mgr_create_contact.rb +60 -0
  165. data/spec/test_app/db/migrate/20131221064153_mail_mgr_test_message.rb +23 -0
  166. data/spec/test_app/db/migrate/20131221064154_add_deleted_at_to_mailing_lists.rb +15 -0
  167. data/spec/test_app/db/migrate/20131221064155_contacts_deleted_at.rb +15 -0
  168. data/spec/test_app/db/migrate/20131221064156_mail_mgr_mailing_list_add_defaults_to_active.rb +15 -0
  169. data/spec/test_app/db/migrate/20131221064157_mail_mgr_message_add_from_email_address.rb +15 -0
  170. data/spec/test_app/db/migrate/20131221072600_create_delayed_jobs.rb +22 -0
  171. data/spec/test_app/db/schema.rb +131 -0
  172. data/spec/test_app/db/structure.sql +31 -0
  173. data/spec/test_app/public/404.html +26 -0
  174. data/spec/test_app/public/422.html +26 -0
  175. data/spec/test_app/public/500.html +25 -0
  176. data/spec/test_app/public/favicon.ico +0 -0
  177. data/spec/test_app/script/delayed_job +5 -0
  178. data/spec/test_app/script/lockable +36 -0
  179. data/spec/test_app/script/rails +6 -0
  180. data/spec/test_app/spec/controllers/users_controller_spec.rb +160 -0
  181. data/spec/test_app/spec/factories/mailing_lists.rb +7 -0
  182. data/spec/test_app/spec/factories/mailings.rb +6 -0
  183. data/spec/test_app/spec/factories/original_factories.rb.txt +107 -0
  184. data/spec/test_app/spec/factories/users.rb +10 -0
  185. data/spec/test_app/spec/models/mail_manager/bounce_spec.rb +17 -0
  186. data/spec/test_app/spec/models/mail_manager/mailing_list_spec.rb +15 -0
  187. data/spec/test_app/spec/models/user_spec.rb +37 -0
  188. data/spec/test_app/spec/requests/users_spec.rb +11 -0
  189. data/spec/test_app/spec/routing/users_routing_spec.rb +35 -0
  190. data/spec/test_app/spec/support/database_cleaner.rb +23 -0
  191. data/spec/test_app/spec/support/files/bad_utf8_chars.eml +32 -0
  192. data/spec/test_app/spec/views/users/edit.html.erb_spec.rb +24 -0
  193. data/spec/test_app/spec/views/users/index.html.erb_spec.rb +29 -0
  194. data/spec/test_app/spec/views/users/new.html.erb_spec.rb +24 -0
  195. data/spec/test_app/spec/views/users/show.html.erb_spec.rb +21 -0
  196. data/zeus.json +22 -0
  197. metadata +424 -0
@@ -0,0 +1,36 @@
1
+ =begin rdoc
2
+ Author:: Chris Hauboldt (mailto:biz@lnstar.com)
3
+ Copyright:: 2009 Lone Star Internet Inc.
4
+
5
+ MailingList simply defines the available lists for subscriptions in the system. See Subscription for more information.
6
+
7
+ =end
8
+ module MailManager
9
+ class MailingList < ActiveRecord::Base
10
+
11
+ self.table_name = "#{MailManager.table_prefix}mailing_lists"
12
+
13
+ # associations get stupid when ActiveRecord is scoped for some horrible reason
14
+ has_many :subscriptions, :class_name => 'MailManager::Subscription'
15
+ has_and_belongs_to_many :mailings, :class_name => 'MailManager::Mailing',
16
+ :join_table => "#{MailManager.table_prefix}mailing_lists_#{MailManager.table_prefix}mailings"
17
+
18
+ scope :active, {:conditions => {:status => 'active',:deleted_at => nil}}
19
+
20
+ validates :name, presence: true
21
+
22
+ include StatusHistory
23
+ before_create :set_default_status
24
+
25
+ attr_protected :id
26
+
27
+ def active?
28
+ deleted_at.nil?
29
+ end
30
+
31
+ def inactive?
32
+ !active?
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,127 @@
1
+ =begin rdoc
2
+ Author:: Chris Hauboldt (mailto:biz@lnstar.com)
3
+ Copyright:: 2009 Lone Star Internet Inc.
4
+
5
+ Message is used in sending a message from an Mailing and keeping state of the message. Generates a "GUID" which is sent in the email and used to identify it in bounces.
6
+
7
+ Statuses:
8
+ pending - MailingJob has created the message but it has not yet been sent
9
+ processing - MailingJob is in process of sending the message
10
+ sent - MailingJob has successfully sent the message to the Email Server
11
+ failed - either the message couldn't be handed to the Email Server or it has been bounced as a permanent failure
12
+
13
+ =end
14
+
15
+ module MailManager
16
+ class Message < ActiveRecord::Base
17
+ self.table_name = "#{MailManager.table_prefix}messages"
18
+ belongs_to :mailing, :class_name => 'MailManager::Mailing'
19
+ belongs_to :subscription, :class_name => 'MailManager::Subscription'
20
+ has_many :bounces, :class_name => 'MailManager::Bounce'
21
+ belongs_to :contact, :class_name => 'MailManager::Contact'
22
+ #FIXME: if we add more types ... change the base message to be MailingMessage or something and don't use
23
+ #me as a message type
24
+ default_scope :conditions => {:type => "MailManager::#{(self.class.name.eql?('Class') ? self.name : self.class.name).gsub(/^MailManager::/,'')}" }
25
+
26
+ scope :pending, {:conditions => {:status => 'pending'}}
27
+ scope :ready, :conditions => ["status=?", 'ready']
28
+ scope :sent, :conditions => ["status=?", 'sent']
29
+ scope :processing, :conditions => ["status=?", 'processing']
30
+
31
+ attr_protected :id
32
+
33
+ def initialize(*args)
34
+ super
35
+ set_type
36
+ end
37
+
38
+ scope :search, lambda{|params|
39
+ conditions = ["1"]
40
+ if params[:mailing_id]
41
+ conditions[0] += " AND #{MailManager.table_prefix}messages.mailing_id=?"
42
+ conditions << params[:mailing_id]
43
+ end
44
+ if params[:status]
45
+ conditions[0] += " AND #{MailManager.table_prefix}messages.status=?"
46
+ conditions << params[:status]
47
+ end
48
+ {
49
+ :conditions => conditions,
50
+ :order => "#{MailManager.table_prefix}contacts.last_name, #{MailManager.table_prefix}contacts.first_name, #{MailManager.table_prefix}contacts.email_address",
51
+ :joins => " INNER JOIN #{MailManager.table_prefix}contacts on #{MailManager.table_prefix}messages.contact_id=#{MailManager.table_prefix}contacts.id"
52
+ }}
53
+
54
+ include StatusHistory
55
+ override_statuses(['pending','processing','sent','failed','ready'], 'pending')
56
+ before_create :set_default_status
57
+ after_create :generate_guid
58
+
59
+ def email_address_with_name
60
+ return %Q|"#{full_name}" <#{email_address}>|.gsub(/\s+/,' ') unless full_name.eql?('')
61
+ email_address
62
+ end
63
+
64
+ # sends the message through Mailer
65
+ def deliver
66
+ MailManager::Mailer.deliver_message(self)
67
+ change_status(:sent)
68
+ end
69
+
70
+ def full_name
71
+ contact.full_name
72
+ end
73
+
74
+ def email_address
75
+ contact.email_address
76
+ end
77
+
78
+ def subject
79
+ mailing.subject
80
+ end
81
+
82
+ def from_email_address
83
+ return self[:from_email_address] if self[:from_email_address].present?
84
+ self.update_attribute(:from_email_address,mailing.from_email_address)
85
+ self[:from_email_address]
86
+ end
87
+
88
+ # returns the separate mime parts of the message's Mailable
89
+ def parts
90
+ @parts ||= mailing.parts(substitutions)
91
+ end
92
+
93
+ def contactable
94
+ contact.try(:contactable)
95
+ end
96
+
97
+ def substitutions
98
+ substitutions_hash = {}
99
+ MailManager::ContactableRegistry.registered_methods.each do |method|
100
+ method_key = method.to_s.upcase
101
+ if contact.respond_to?(method)
102
+ substitutions_hash[method_key] = contact.send(method)
103
+ elsif contactable.respond_to?(method)
104
+ substitutions_hash[method_key] = contactable.send(method)
105
+ else
106
+ substitutions_hash[method_key] = ''
107
+ end
108
+ end
109
+ substitutions_hash.merge('UNSUBSCRIBE_URL' => unsubscribe_url)
110
+ end
111
+
112
+ def unsubscribe_url
113
+ "#{MailManager.site_url}#{MailManager.unsubscribe_path}/#{guid}"
114
+ end
115
+
116
+ # generated the guid for which the message is identified by in transit
117
+ def generate_guid
118
+ update_attribute(:guid,
119
+ "#{contact.id}-#{subscription.try(:id)}-#{self.id}-#{Digest::SHA1.hexdigest("#{contact.id}-#{subscription.try(:id)}-#{self.id}-#{MailManager.secret}")}")
120
+ end
121
+
122
+ protected
123
+ def set_type
124
+ self[:type] = self.class.name
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,126 @@
1
+ =begin rdoc
2
+ Author:: Chris Hauboldt (mailto:biz@lnstar.com)
3
+ Copyright:: 2009 Lone Star Internet Inc.
4
+
5
+ Subscription ties Contacts to MailingLists and keeps track of subscription preferences or 'status'
6
+
7
+ Statuses:
8
+ 'active' - user has an active subscription to list
9
+ 'pending' - awaiting user approval through email
10
+ 'unsubscribed' - user or admin has unsubscribe user from list
11
+ 'failed_address' - BounceJob has detected a 'permanently' fatal email failure - like the account or domain doesn't exist
12
+
13
+ FIXME: currently tied to users table
14
+ =end
15
+
16
+ module MailManager
17
+ class Subscription < ActiveRecord::Base
18
+ self.table_name = "#{MailManager.table_prefix}subscriptions"
19
+ belongs_to :contact, :class_name => 'MailManager::Contact'
20
+ belongs_to :mailing_list, :class_name => 'MailManager::MailingList'
21
+ has_many :messages, :class_name => 'MailManager::Message'
22
+
23
+ validates_presence_of :mailing_list_id
24
+ validates_associated :mailing_list
25
+
26
+ scope :active, :conditions => {:status => 'active'},
27
+ :joins => "INNER JOIN #{MailManager.table_prefix}contacts ON
28
+ #{MailManager.table_prefix}subscriptions.contact_id = #{MailManager.table_prefix}contacts.id
29
+ and #{MailManager.table_prefix}contacts.deleted_at IS NULL"
30
+
31
+ scope :unsubscribed, :conditions => {:status => 'unsubscribed'},
32
+ :joins => "INNER JOIN #{MailManager.table_prefix}contacts ON
33
+ #{MailManager.table_prefix}subscriptions.contact_id = #{MailManager.table_prefix}contacts.id
34
+ and #{MailManager.table_prefix}contacts.deleted_at IS NULL"
35
+
36
+ scope :failed_address, :conditions => {:status => 'failed_address'},
37
+ :joins => "INNER JOIN #{MailManager.table_prefix}contacts ON
38
+ #{MailManager.table_prefix}subscriptions.contact_id = #{MailManager.table_prefix}contacts.id
39
+ and #{MailManager.table_prefix}contacts.deleted_at IS NULL"
40
+
41
+ scope :pending, :conditions => {:status => 'pending'},
42
+ :joins => "INNER JOIN #{MailManager.table_prefix}contacts ON
43
+ #{MailManager.table_prefix}subscriptions.contact_id = #{MailManager.table_prefix}contacts.id
44
+ and #{MailManager.table_prefix}contacts.deleted_at IS NULL"
45
+
46
+ include StatusHistory
47
+ override_statuses(['active','unsubscribed','failed_address','pending','duplicate','admin_unsubscribed'],'pending')
48
+ before_create :set_default_status
49
+
50
+ attr_protected :id
51
+
52
+ #acts_as_audited rescue Rails.logger.warn "Audit Table not defined!"
53
+
54
+ def contact_full_name
55
+ contact.full_name
56
+ end
57
+
58
+ # changes or creates a subscription for the given contact and list and assigns the given status
59
+ def self.change_subscription_status(contact, mailing_list, status)
60
+ subscription = self.find_by_contact_id_and_mailing_list_id(contact.id, mailing_list.id)
61
+ return subscription.change_status(status) if subscription
62
+ subscription = Subscription.new
63
+ subscription.contact = contact
64
+ subscription.mailing_list = mailing_list
65
+ subscription.change_status(status)
66
+ end
67
+
68
+ # subscribes the contact to the list
69
+ def self.subscribe(contact, mailing_list)
70
+ change_subscription_status(contact, mailing_list, 'active')
71
+ end
72
+
73
+ # unsubscribes the contact from the list
74
+ def self.unsubscribe(contact, mailing_list)
75
+ change_subscription_status(contact, mailing_list, 'unsubscribed')
76
+ end
77
+
78
+ def mailing_list_name
79
+ mailing_list.try(:name)
80
+ end
81
+
82
+ def active?
83
+ status.eql?('active')
84
+ end
85
+
86
+ # unsubscribes a contact from all lists by looking them up through a messages GUID
87
+ # FIXME: when we add more lists and the ability to have multiple subscriptions, this should
88
+ # remove only the list that is tied in the GUID and they should be linked to their options
89
+ def self.unsubscribe_by_message_guid(guid)
90
+ message = Message.find_by_guid(guid)
91
+ contact = message.contact
92
+ if message
93
+ begin
94
+ unsubscribed_subscriptions = self.unsubscribe_by_email_address(message.contact.email_address)
95
+ Mailer.deliver_unsubscribed(message,unsubscribed_subscriptions) unless unsubscribed_subscriptions.empty?
96
+ return unsubscribed_subscriptions
97
+ rescue => e
98
+ Rails.logger.warn "Error Unsubscribing email: #{message.contact.email_address}\n#{e.message}\n #{e.backtrace.join("\n ")}"
99
+ raise "An error occured."
100
+ end
101
+ else
102
+ raise "Could not find your subscription!"
103
+ end
104
+ nil
105
+ end
106
+
107
+ def self.fail_by_email_address(email_address)
108
+ Contact.find_all_by_email_address(email_address).each do |contact|
109
+ contact.active_subscriptions.each do |subscription|
110
+ subscription.change_status(:failed_address)
111
+ end
112
+ end
113
+ end
114
+
115
+ def self.unsubscribe_by_email_address(email_address)
116
+ subscriptions = []
117
+ Contact.find_all_by_email_address(email_address).each do |contact|
118
+ subscriptions += contact.active_subscriptions.each do |subscription|
119
+ subscription.change_status(:unsubscribed)
120
+ end
121
+ end
122
+ subscriptions
123
+ end
124
+ end
125
+ end
126
+
@@ -0,0 +1,175 @@
1
+ module MailManager
2
+ class TestMessage < ActiveRecord::Base
3
+ self.table_name = "#{MailManager.table_prefix}messages"
4
+ belongs_to :mailing, :class_name => 'MailManager::Mailing'
5
+ belongs_to :subscription, :class_name => 'MailManager::Subscription'
6
+ has_many :bounces, :class_name => 'MailManager::Bounce'
7
+ belongs_to :contact, :class_name => 'MailManager::Contact'
8
+ #FIXME: if we add more types ... change the base message to be MailingMessage or something and don't use
9
+ #me as a message type
10
+ default_scope :conditions => {:type => "MailManager::#{(self.class.name.eql?('Class') ? self.name : self.class.name).gsub(/^MailManager::/,'')}" }
11
+
12
+ scope :pending, {:conditions => {:status => 'pending'}}
13
+ scope :ready, :conditions => ["status=?", 'ready']
14
+
15
+ def initialize(*args)
16
+ super
17
+ set_type
18
+ end
19
+
20
+ include StatusHistory
21
+ override_statuses(['pending','processing','sent','failed','ready'], 'pending')
22
+
23
+ attr_protected :id
24
+
25
+ scope :search, lambda{|params|
26
+ conditions = ["1"]
27
+ if params[:mailing_id]
28
+ conditions[0] += " AND #{MailManager.table_prefix}messages.mailing_id=?"
29
+ conditions << params[:mailing_id]
30
+ end
31
+ if params[:status]
32
+ conditions[0] += " AND #{MailManager.table_prefix}messages.status=?"
33
+ conditions << params[:status]
34
+ end
35
+ {
36
+ :conditions => conditions,
37
+ :order => "#{MailManager.table_prefix}contacts.last_name, #{MailManager.table_prefix}contacts.first_name, #{MailManager.table_prefix}contacts.email_address",
38
+ :joins => " INNER JOIN #{MailManager.table_prefix}contacts on #{MailManager.table_prefix}messages.contact_id=#{MailManager.table_prefix}contacts.id"
39
+ }}
40
+
41
+ before_create :set_default_status
42
+ after_create :generate_guid
43
+
44
+ def email_address_with_name
45
+ return %Q|"#{full_name}" <#{email_address}>|.gsub(/\s+/,' ') unless full_name.eql?('')
46
+ email_address
47
+ end
48
+
49
+ # sends the message through Mailer
50
+ def deliver
51
+ MailManager::Mailer.deliver_message(self)
52
+ change_status(:sent)
53
+ end
54
+
55
+ def full_name
56
+ contact.full_name
57
+ end
58
+
59
+ def email_address
60
+ contact.email_address
61
+ end
62
+
63
+ def subject
64
+ mailing.subject
65
+ end
66
+
67
+ def from_email_address
68
+ return self[:from_email_address] if self[:from_email_address].present?
69
+ self.update_attribute(:from_email_address,mailing.from_email_address)
70
+ self[:from_email_address]
71
+ end
72
+
73
+ # returns the separate mime parts of the message's Mailable
74
+ def parts
75
+ @parts ||= mailing.parts(substitutions)
76
+ end
77
+
78
+ def contactable
79
+ contact.try(:contactable)
80
+ end
81
+
82
+ def substitutions
83
+ substitutions_hash = {}
84
+ MailManager::ContactableRegistry.registered_methods.each do |method|
85
+ method_key = method.to_s.upcase
86
+ if contact.respond_to?(method)
87
+ substitutions_hash[method_key] = contact.send(method)
88
+ elsif contactable.respond_to?(method)
89
+ substitutions_hash[method_key] = contactable.send(method)
90
+ else
91
+ substitutions_hash[method_key] = ''
92
+ end
93
+ end
94
+ substitutions_hash.merge('UNSUBSCRIBE_URL' => unsubscribe_url)
95
+ end
96
+
97
+ def unsubscribe_url
98
+ "#{MailManager.site_url}#{MailManager.unsubscribe_path}/#{guid}"
99
+ end
100
+
101
+ def self.valid_statuses
102
+ ['pending','processing','sent','failed','ready']
103
+ end
104
+
105
+ def valid_statuses
106
+ ['pending','processing','sent','failed','ready']
107
+ end
108
+
109
+ # generated the guid for which the message is identified by in transit
110
+ def generate_guid
111
+ update_attribute(:guid,
112
+ "#{contact.id}-#{subscription.try(:id)}-#{self.id}-#{Digest::SHA1.hexdigest("#{contact.id}-#{subscription.try(:id)}-#{self.id}-#{MailManager.secret}")}")
113
+ end
114
+
115
+ def default_status
116
+ 'pending'
117
+ end
118
+
119
+ default_scope :conditions => {:type => "MailManager::#{(self.class.name.eql?('Class') ? self.name : self.class.name).gsub(/^MailManager::/,'')}" }
120
+
121
+ scope :ready, :conditions => ["status=?", 'ready']
122
+ def email_address
123
+ self[:test_email_address]
124
+ end
125
+
126
+ def email_address_with_name
127
+ "\"Test Guy\" <#{email_address}>"
128
+ end
129
+
130
+ def default_status
131
+ 'ready'
132
+ end
133
+ def generate_guid
134
+ update_attribute(:guid,
135
+ "test-#{self.id}-#{Digest::SHA1.hexdigest("test-#{self.id}-#{MailManager.secret}")}")
136
+ end
137
+
138
+ def subscription
139
+ Subscription.new(self)
140
+ end
141
+
142
+ def valid_statuses
143
+ ['ready'] + super
144
+ end
145
+ class Subscription
146
+ def initialize(test_message)
147
+ @test_message = test_message
148
+ end
149
+ def contact
150
+ Contact.new(@test_message)
151
+ end
152
+ end
153
+ class Contact
154
+ def initialize(test_message)
155
+ @test_message = test_message
156
+ end
157
+ def full_name
158
+ "#{first_name} #{last_name}".strip
159
+ end
160
+ def first_name
161
+ 'Test'
162
+ end
163
+ def last_name
164
+ 'Guy'
165
+ end
166
+ def email_address
167
+ @test_message.email_address
168
+ end
169
+ end
170
+ protected
171
+ def set_type
172
+ self[:type] = self.class.name
173
+ end
174
+ end
175
+ end