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,4 @@
1
+ module MailManager
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,8 @@
1
+ module MailManager
2
+ module SubscriptionsHelper
3
+ def contactable_subscriptions_selector(contactable_form, default_unsubscribe_status="unsubscribed")
4
+ render :partial => 'mail_manager/subscriptions/subscriptions', :locals => {:contactable_form => contactable_form,
5
+ :unsubscribed_status => default_unsubscribe_status}
6
+ end
7
+ end
8
+ end
Binary file
@@ -0,0 +1,12 @@
1
+ module MailManager
2
+ end
3
+
4
+ require 'mail_manager/bounce'
5
+ require 'mail_manager/mailable_registry'
6
+ require 'mail_manager/mailer'
7
+ require 'mail_manager/mailing'
8
+ require 'mail_manager/mailing_list'
9
+ require 'mail_manager/message'
10
+ require 'mail_manager/contactable_registry'
11
+ require 'mail_manager/subscription'
12
+ require 'mail_manager/contact'
@@ -0,0 +1,133 @@
1
+ =begin rdoc
2
+ Author:: Chris Hauboldt (mailto:biz@lnstar.com)
3
+ Copyright:: 2009 Lone Star Internet Inc.
4
+
5
+ Used to record messages which are returned to the configured account for 'bounce' in the config/config.yml, and pulled by BounceJob. Also responsible for knowing how to process a bounce by pulling diagnostic codes and a message's guid from the bounced email, unsubscribing users when necessary.
6
+
7
+ Diagnostic Codes:
8
+ 5xx - will currently unsubscribe a contact, except when the error contains 'quota'
9
+ 4xx - is ignored, and marked 'resolved' as they are temporary errors
10
+
11
+ Statuses:
12
+ 'unprocessed' - initial status before processing
13
+ 'needs_manual_intervention' - message identified by guid, but message not understood
14
+ 'resolved' - message has been resolved during processing, and appropriate action taken
15
+ 'invalid' - message not identified
16
+ 'dismissed' - bounce has been dismissed by user
17
+ =end
18
+
19
+ module MailManager
20
+ class Bounce < ActiveRecord::Base
21
+ self.table_name = "#{MailManager.table_prefix}bounces"
22
+ belongs_to :message, :class_name => 'MailManager::Message'
23
+ belongs_to :mailing, :class_name => 'MailManager::Mailing'
24
+ include StatusHistory
25
+ override_statuses(['needs_manual_intervention','unprocessed','dismissed','resolved','invalid'],'unprocessed')
26
+ before_create :set_default_status
27
+ default_scope :order => "#{MailManager.table_prefix}contacts.last_name, #{MailManager.table_prefix}contacts.first_name, #{MailManager.table_prefix}contacts.email_address",
28
+ :joins =>
29
+ "LEFT OUTER JOIN #{MailManager.table_prefix}messages on #{MailManager.table_prefix}bounces.message_id=#{MailManager.table_prefix}messages.id "+
30
+ " LEFT OUTER JOIN #{MailManager.table_prefix}contacts on #{MailManager.table_prefix}messages.contact_id=#{MailManager.table_prefix}contacts.id"
31
+ #
32
+ scope :by_mailing_id, lambda {|mailing_id| where(:mailing_id => mailing_id)}
33
+ scope :by_status, lambda {|status| where(:status => status.to_s)}
34
+
35
+ attr_protected :id
36
+ #Parses email contents for bounce resolution
37
+ def process(force=false)
38
+ if status.eql?('unprocessed') || force
39
+ self.message = Message.find_by_guid(bounce_message_guid)
40
+ self.mailing = message.mailing unless message.nil?
41
+ if !from_mailer_daemon?
42
+ change_status(:invalid)
43
+ elsif delivery_error_code =~ /4\.\d\.\d/ || delivery_error_message.to_s =~ /quota/i
44
+ update_attribute(:comments, delivery_error_message)
45
+ change_status(:resolved)
46
+ elsif delivery_error_code =~ /5\.\d\.\d/ && delivery_error_message.present?
47
+ transaction do
48
+ update_attribute(:comments, delivery_error_message)
49
+ change_status(:resolved)
50
+ message.change_status(:failed)
51
+ message.update_attribute(:result,"Failure Message from Bounce: #{delivery_error_message}")
52
+ Subscription.fail_by_email_address(contact_email_address)
53
+ end
54
+ else
55
+ update_attribute(:comments, 'unrecognized diagnostic code')
56
+ change_status(:needs_manual_intervention)
57
+ end
58
+ save
59
+ end
60
+ end
61
+
62
+ def reprocess
63
+ process(true)
64
+ end
65
+
66
+ def from_mailer_daemon?
67
+ ['postmaster','mailer-daemon'].include?(email.from.first.gsub(/\@.*$/,'').downcase)
68
+ end
69
+
70
+ def dismiss
71
+ raise "Status cannot be manually changed unless it needs manual intervention!" unless
72
+ status.eql?('needs_manual_intervention')
73
+ change_status(:dismissed)
74
+ end
75
+
76
+ def fail_address
77
+ raise "Status cannot be manually changed unless it needs manual intervention!" unless
78
+ status.eql?('needs_manual_intervention')
79
+ transaction do
80
+ Subscription.fail_by_email_address(contact_email_address)
81
+ message.result = message.result.to_s + "Failed by Administrator: (bounced, not auto resolved) "
82
+ message.change_status(:failed)
83
+ change_status(:resolved)
84
+ end
85
+ end
86
+
87
+ def mailing_subject
88
+ message.try(:mailing).try(:subject)
89
+ end
90
+
91
+ def subscription
92
+ message.try(:subscription)
93
+ end
94
+
95
+ def contact
96
+ message.try(:contact)
97
+ end
98
+
99
+ def contact_full_name
100
+ contact.try(:full_name)
101
+ end
102
+
103
+ def contact_email_address
104
+ if contact.blank?
105
+ "Contact Deleted"
106
+ else
107
+ contact.email_address
108
+ end
109
+ end
110
+
111
+ def delivery_error_code
112
+ email.error_status
113
+ rescue
114
+ nil
115
+ end
116
+
117
+ def delivery_error_message
118
+ email.diagnostic_code
119
+ rescue
120
+ nil
121
+ end
122
+
123
+ # Returns message guid
124
+ def bounce_message_guid
125
+ email.to_s.gsub(/^.*X-Bounce-GUID:\s*([^\s]+).*$/mi,'\1') if email.to_s.match(/X-Bounce-GUID:\s*([^\s]+)/mi)
126
+ end
127
+
128
+ def email
129
+ return @email if @email
130
+ @email = Mail.new(bounce_message)
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,91 @@
1
+ module MailManager
2
+ class Contact < ActiveRecord::Base
3
+ self.table_name = "#{MailManager.table_prefix}contacts"
4
+ has_many :messages, :class_name => 'MailManager::Message'
5
+
6
+ belongs_to :contactable, :polymorphic => true
7
+ #not working for some reasom
8
+ #accepts_nested_attributes_for :subscriptions
9
+
10
+ validates_presence_of :email_address
11
+ #validates_format_of :email_address, :with => Authentication.email_regex,
12
+ # :message => Authentication.bad_email_message, :allow_nil => true
13
+ validates_format_of :email_address, :with => /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/, :allow_nil => true
14
+
15
+ include MailManager::ContactableRegistry::Contactable
16
+ include Deleteable
17
+
18
+ attr_protected :id
19
+
20
+ def contact
21
+ self
22
+ end
23
+
24
+ scope :search, lambda{|params|
25
+ conditions = ["deleted_at IS NULL"]
26
+ joins = {}
27
+ unless params[:term].blank?
28
+ conditions[0] += " AND (#{params[:term].split(/\s+/).collect{ |term|
29
+ term = "%#{term}%";
30
+ 3.times{conditions << term}
31
+ "(first_name like ? OR last_name like ? OR email_address like ?)"
32
+ }.join(' OR ')})"
33
+ end
34
+
35
+ if params[:mailing_list_id].present?
36
+ joins = {joins: "INNER JOIN #{MailManager.table_prefix}subscriptions s ON
37
+ s.contact_id=#{MailManager.table_prefix}contacts.id AND s.mailing_list_id=#{params[:mailing_list_id].to_i}"}
38
+ end
39
+ unless params[:status].blank? || params[:mailing_list_id].blank?
40
+ conditions[0] += " AND status=?"
41
+ conditions << params[:status]
42
+ end
43
+ conditions = {
44
+ :conditions => conditions,
45
+ :order => 'last_name, first_name, email_address'
46
+ }
47
+ conditions.merge!(joins) if params[:mailing_list_id].present?
48
+ conditions
49
+ }
50
+
51
+ scope :active, lambda {{:conditions => "#{table_name}.deleted_at IS NULL"}}
52
+
53
+ default_scope :order => 'last_name, first_name, email_address'
54
+
55
+ def email_address_with_name
56
+ return %Q|"#{full_name}" <#{email_address}>|.gsub(/\s+/,' ') unless full_name.eql?('')
57
+ email_address
58
+ end
59
+
60
+ def full_name
61
+ "#{first_name} #{last_name}".strip
62
+ end
63
+
64
+ def deleted?
65
+ !deleted_at.nil?
66
+ end
67
+
68
+ def self.signup(params)
69
+ contact = MailManager::Contact.active.find_by_email_address(params['email_address'])
70
+ contact ||= Contact.new
71
+ Rails.logger.debug "Updating contact(#{contact.new_record? ? "New" : contact.id}) params: #{params.inspect}"
72
+ contact.update_attributes(params)
73
+ contact
74
+ end
75
+
76
+ def initialize_subscriptions
77
+ @subscriptions = new_record? ? [] : Subscription.find_all_by_contact_id(self.id)
78
+ MailingList.active.each do |list|
79
+ next if @subscriptions.detect{|subscription| subscription.mailing_list_id.eql?(list.id) }
80
+ Rails.logger.warn "Building Subscription for Mailing List #{list.name}"
81
+ subscription = Subscription.new(:contact => self)
82
+ subscription.mailing_list_id = list.id
83
+ subscription.change_status((self.new_record? and list.defaults_to_active?) ? :active : :pending,false)
84
+ @subscriptions << subscription
85
+ end
86
+ @subscriptions = subscriptions.reject{|subscription| subscription.mailing_list.try(:inactive?) or
87
+ subscription.mailing_list.nil?}.sort_by{|subscription|
88
+ subscription.mailing_list.name.downcase}
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,190 @@
1
+ module MailManager
2
+ class ContactableRegistry
3
+
4
+ @@contactable_things = {}
5
+ def self.register_contactable(classname, methods={})
6
+ @@contactable_things.merge!(classname => methods)
7
+ Rails.logger.warn "Registered Contactable: #{classname}"
8
+ Rails.logger.debug "Current Contactables: #{@@contactable_things.inspect}"
9
+ end
10
+
11
+ def self.registered_methods(classname=nil)
12
+ return @@contactable_things[classname.to_s].keys unless classname.nil?
13
+ all_methods = {}
14
+ @@contactable_things.values.each do |methods|
15
+ all_methods.merge!(methods)
16
+ end
17
+ all_methods.keys.reject{|key| key.to_s.eql?('edit_route')}
18
+ end
19
+
20
+ def self.valid_contactable_substitutions(classname=nil)
21
+ registered_methods(classname).collect{|key| key.to_s.upcase}
22
+ end
23
+
24
+ def self.contactable_method(classname,method)
25
+ @@contactable_things[classname][method] || method
26
+ end
27
+
28
+ def self.edit_route_for(classname)
29
+ return @@contactable_things[classname][:edit_route] if @@contactable_things[classname][:edit_route].present?
30
+ "edit_#{classname.underscore}_path"
31
+ end
32
+
33
+ module Contactable
34
+
35
+ #FIXME: this is NOT secure!!!!
36
+ def update_contactable_data
37
+ set_contactable_data && self.contact.save
38
+ end
39
+ def set_contactable_data
40
+ unless self.is_a?(MailManager::Contact)
41
+ if self.contact.present?
42
+ self.contact.update_attributes(
43
+ :first_name => contactable_value(:first_name).to_s,
44
+ :last_name => contactable_value(:last_name).to_s,
45
+ :email_address => contactable_value(:email_address).to_s)
46
+ else
47
+ self.contact = Contact.new(
48
+ :contactable => self,
49
+ :first_name => contactable_value(:first_name).to_s,
50
+ :last_name => contactable_value(:last_name).to_s,
51
+ :email_address => contactable_value(:email_address).to_s
52
+ )
53
+ end
54
+ end
55
+ self.contact.present? and self.contact.errors.empty?
56
+ end
57
+
58
+ def initialize_subscriptions
59
+ if self.contact.nil?
60
+ self.contact = MailManager::Contact.new(
61
+ :first_name => contactable_value(:first_name).to_s,
62
+ :last_name => contactable_value(:last_name).to_s,
63
+ :email_address => contactable_value(:email_address).to_s)
64
+ end
65
+ self.contact.initialize_subscriptions
66
+ end
67
+
68
+ def subscription_status_for(mailing_list)
69
+ subscriptions.detect{|subscription| subscription.mailing_list_id.eql?(mailing_list.id)}.status
70
+ end
71
+
72
+ def update_subscription_data
73
+ Rails.logger.debug "Updating Subscriptions: #{@subscriptions_attributes.inspect} - #{subscriptions.inspect}"
74
+ subscriptions.each do |subscription|
75
+ Rails.logger.debug "Updating Subscription attributes for: #{subscription.inspect}"
76
+ unless @subscriptions_attributes.nil?
77
+ subscription_attributes = get_subscription_atttributes_for_subscription(subscription)
78
+ if subscription.new_record? and subscription_attributes[:status] != 'active'
79
+ Rails.logger.debug "Skipping new subscription save, since we're not subscribing"
80
+ subscription.change_status(subscription_attributes[:status],false)
81
+ #mucking with the array messes up the each!
82
+ #subscriptions.delete_if{|my_subscription| my_subscription.mailing_list_id == subscription.mailing_list_id}
83
+ elsif subscription_attributes[:status].present?
84
+ Rails.logger.debug "Changing from #{subscription.status} to #{subscription_attributes[:status]}"
85
+ subscription.change_status(subscription_attributes[:status])
86
+ end
87
+ end
88
+ end
89
+ true
90
+ end
91
+
92
+ def get_subscription_atttributes_for_subscription(subscription)
93
+ return {} if @subscriptions_attributes.nil?
94
+ subscriptions_attributes.values.detect{|subscription_attributes|
95
+ subscription_attributes[:mailing_list_id].to_i == subscription.mailing_list_id.to_i} || {}
96
+ end
97
+
98
+ def subscribe(mailing_list)
99
+ set_contactable_data && MailManager::Subscription.subscribe(contact,mailing_list)
100
+ end
101
+
102
+ def unsubscribe(mailing_list)
103
+ set_contactable_data && MailManager::Subscription.unsubscribe(contact,mailing_list)
104
+ end
105
+
106
+ def change_subscription_status(mailing_list,status)
107
+ set_contactable_data && MailManager::Subscription.change_subscription_status(contact,mailing_list,status)
108
+ end
109
+
110
+ def contactable_value(method)
111
+ begin
112
+ send(contactable_method(method.to_sym))
113
+ rescue => e
114
+ nil
115
+ end
116
+ end
117
+
118
+ def contactable_method(method)
119
+ begin
120
+ MailManager::ContactableRegistry.contactable_method(self.class.name,method.to_sym)
121
+ rescue => e
122
+ method
123
+ end
124
+ end
125
+
126
+ def reload
127
+ @subscriptions = nil
128
+ end
129
+
130
+ def subscriptions
131
+ return @subscriptions unless @subscriptions.nil?
132
+ set_contactable_data unless self.contact.present?
133
+ @subscriptions = contact.initialize_subscriptions
134
+ end
135
+
136
+ def active_subscriptions
137
+ subscriptions.select{|subscription| subscription.active?}
138
+ end
139
+
140
+ def save(*args)
141
+ success = true
142
+ if args[0] != false
143
+ begin
144
+ transaction do
145
+ success = success && super
146
+ if self.contactable_value(:email_address).present?
147
+ Rails.logger.debug "User save super success? #{success.inspect}"
148
+ success = update_subscription_data && success
149
+ Rails.logger.debug "User save subscription data success? #{success.inspect}"
150
+ success = update_contactable_data unless (!success or self.is_a?(MailManager::Contact))
151
+ Rails.logger.debug "User save contactable data success? #{success.inspect}"
152
+ end
153
+ raise "Failed to update contactable and/or #{self.class.name} data." unless success
154
+ end
155
+ rescue => e
156
+ Rails.logger.debug "User save failed! #{e.message} #{e.backtrace.join("\n ")}"
157
+ end
158
+ Rails.logger.debug "User save successful? #{success}"
159
+ else
160
+ success = super
161
+ end
162
+ success
163
+ end
164
+
165
+ module Associations
166
+ def self.included(model)
167
+ model.class_eval do
168
+ has_one :contact, :as => :contactable, :class_name => 'MailManager::Contact'
169
+ #overloading with some extra stuff is better than this
170
+ #has_many :subscriptions, :through => :contact, :class_name => 'MailManager::Subscription'
171
+ end
172
+ end
173
+ end
174
+
175
+ module AttrAccessors
176
+ def self.included(model)
177
+ model.class_eval do
178
+ after_create :save
179
+ attr_accessor :subscriptions_attributes
180
+ end
181
+ end
182
+ end
183
+
184
+ def self.included(model)
185
+ model.send(:include, Associations)
186
+ model.send(:include, AttrAccessors)
187
+ end
188
+ end
189
+ end
190
+ end