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.
- checksums.yaml +15 -0
- data/.DS_Store +0 -0
- data/.gitignore +20 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +27 -0
- data/Guardfile +24 -0
- data/LICENSE.txt +22 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +141 -0
- data/Procfile +4 -0
- data/README +243 -0
- data/README.md +29 -0
- data/README.rdoc +3 -0
- data/Rakefile +33 -0
- data/app/.DS_Store +0 -0
- data/app/assets/javascripts/mail_manager/application.js +15 -0
- data/app/assets/stylesheets/mail_manager/application.css +13 -0
- data/app/controllers/mail_manager/application_controller.rb +4 -0
- data/app/controllers/mail_manager/base_controller.rb +22 -0
- data/app/controllers/mail_manager/bounces_controller.rb +32 -0
- data/app/controllers/mail_manager/contacts_controller.rb +75 -0
- data/app/controllers/mail_manager/mailing_lists_controller.rb +49 -0
- data/app/controllers/mail_manager/mailings_controller.rb +102 -0
- data/app/controllers/mail_manager/messages_controller.rb +30 -0
- data/app/controllers/mail_manager/subscriptions_controller.rb +104 -0
- data/app/helpers/mail_manager/application_helper.rb +4 -0
- data/app/helpers/mail_manager/subscriptions_helper.rb +8 -0
- data/app/models/.DS_Store +0 -0
- data/app/models/mail_manager.rb +12 -0
- data/app/models/mail_manager/bounce.rb +133 -0
- data/app/models/mail_manager/contact.rb +91 -0
- data/app/models/mail_manager/contactable_registry.rb +190 -0
- data/app/models/mail_manager/mailable_registry.rb +127 -0
- data/app/models/mail_manager/mailer.rb +267 -0
- data/app/models/mail_manager/mailing.rb +266 -0
- data/app/models/mail_manager/mailing_list.rb +36 -0
- data/app/models/mail_manager/message.rb +127 -0
- data/app/models/mail_manager/subscription.rb +126 -0
- data/app/models/mail_manager/test_message.rb +175 -0
- data/app/models/status_history.rb +60 -0
- data/app/views/layouts/mail_manager/application.html.erb +14 -0
- data/app/views/mail_manager/bounces/_email_parts.html.erb +30 -0
- data/app/views/mail_manager/bounces/index.html.erb +32 -0
- data/app/views/mail_manager/bounces/show.html.erb +38 -0
- data/app/views/mail_manager/contacts/_form.html.erb +27 -0
- data/app/views/mail_manager/contacts/double_opt_in.html.erb +1 -0
- data/app/views/mail_manager/contacts/edit.html.erb +12 -0
- data/app/views/mail_manager/contacts/index.html.erb +86 -0
- data/app/views/mail_manager/contacts/new.html.erb +9 -0
- data/app/views/mail_manager/contacts/show.html.erb +22 -0
- data/app/views/mail_manager/contacts/subscribe.html.erb +2 -0
- data/app/views/mail_manager/contacts/thank_you.html.erb +12 -0
- data/app/views/mail_manager/help/_available_email_substitutions.html.erb +5 -0
- data/app/views/mail_manager/mailer/double_opt_in.erb +6 -0
- data/app/views/mail_manager/mailer/unsubscribed.erb +5 -0
- data/app/views/mail_manager/mailer/unsubscribed.html.erb +5 -0
- data/app/views/mail_manager/mailing_lists/_form.html.erb +20 -0
- data/app/views/mail_manager/mailing_lists/edit.html.erb +13 -0
- data/app/views/mail_manager/mailing_lists/index.html.erb +39 -0
- data/app/views/mail_manager/mailing_lists/new.html.erb +9 -0
- data/app/views/mail_manager/mailing_lists/show.html.erb +13 -0
- data/app/views/mail_manager/mailings/_form.html.erb +81 -0
- data/app/views/mail_manager/mailings/edit.html.erb +12 -0
- data/app/views/mail_manager/mailings/index.html.erb +52 -0
- data/app/views/mail_manager/mailings/new.html.erb +9 -0
- data/app/views/mail_manager/mailings/show.html.erb +28 -0
- data/app/views/mail_manager/mailings/test.html.erb +12 -0
- data/app/views/mail_manager/messages/index.html.erb +37 -0
- data/app/views/mail_manager/subscriptions/_form.html.erb +37 -0
- data/app/views/mail_manager/subscriptions/_subscriptions.html.erb +13 -0
- data/app/views/mail_manager/subscriptions/edit.html.erb +11 -0
- data/app/views/mail_manager/subscriptions/index.html.erb +32 -0
- data/app/views/mail_manager/subscriptions/new.html.erb +9 -0
- data/app/views/mail_manager/subscriptions/show.html.erb +8 -0
- data/app/views/mail_manager/subscriptions/unsubscribe.html.erb +2 -0
- data/app/views/mail_manager/subscriptions/unsubscribe_by_email_address.html.erb +13 -0
- data/config/daemons.yml +5 -0
- data/config/routes.rb +43 -0
- data/db/migrate/001_mail_mgr_initial.rb +84 -0
- data/db/migrate/002_mail_mgr_create_contact.rb +60 -0
- data/db/migrate/003_mail_mgr_test_message.rb +23 -0
- data/db/migrate/004_add_deleted_at_to_mailing_lists.rb +15 -0
- data/db/migrate/005_contacts_deleted_at.rb +15 -0
- data/db/migrate/006_mail_mgr_mailing_list_add_defaults_to_active.rb +15 -0
- data/db/migrate/007_mail_mgr_message_add_from_email_address.rb +15 -0
- data/db/mlm_migrate/001_mlm_initial.rb +67 -0
- data/db/mlm_migrate/002_mailable_as_polymorphic.rb +27 -0
- data/db/mlm_migrate/003_contact_as_polymorphic.rb +64 -0
- data/db/mlm_migrate/004_bounce_mlm_mailing_id.rb +26 -0
- data/db/mlm_migrate/005_mlm_to_mail_mgr_scoped.rb +29 -0
- data/engine_plan.rb +13 -0
- data/features/bounce_management.feature +0 -0
- data/features/contact_management.feature +24 -0
- data/features/mailable.feature +23 -0
- data/features/mailing_management.feature +78 -0
- data/features/message.feature +11 -0
- data/features/step_definitions/email_steps.rb +50 -0
- data/features/step_definitions/mlm_steps.rb +11 -0
- data/features/step_definitions/pickle_steps.rb +41 -0
- data/features/step_definitions/webrat_steps.rb +115 -0
- data/features/subscription_management.feature +17 -0
- data/features/support/env.rb +31 -0
- data/features/support/paths.rb +44 -0
- data/lib/daemons/mail_manager.rb +38 -0
- data/lib/daemons/mail_manager_ctl +15 -0
- data/lib/deleteable.rb +50 -0
- data/lib/lock.rb +36 -0
- data/lib/mail_manager.rb +5 -0
- data/lib/mail_manager/config.rb +50 -0
- data/lib/mail_manager/engine.rb +43 -0
- data/lib/mail_manager/version.rb +3 -0
- data/lib/tasks/mail_manager.rake +143 -0
- data/lib/tasks/mail_manager_tasks.rake +4 -0
- data/lib/tasks/rspec.rake +165 -0
- data/lib/workers/mail_manager/bounce_job.rb +52 -0
- data/lib/workers/mail_manager/mailing_job.rb +30 -0
- data/lib/workers/mail_manager/message_job.rb +38 -0
- data/lib/workers/mail_manager/test_message_job.rb +37 -0
- data/mail_manager.gemspec +29 -0
- data/script/rails +8 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/test_app/README.rdoc +261 -0
- data/spec/test_app/Rakefile +7 -0
- data/spec/test_app/app/assets/javascripts/application.js +15 -0
- data/spec/test_app/app/assets/javascripts/users.js +2 -0
- data/spec/test_app/app/assets/stylesheets/application.css +13 -0
- data/spec/test_app/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/test_app/app/assets/stylesheets/users.css +4 -0
- data/spec/test_app/app/controllers/application_controller.rb +3 -0
- data/spec/test_app/app/controllers/users_controller.rb +83 -0
- data/spec/test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_app/app/helpers/users_helper.rb +2 -0
- data/spec/test_app/app/models/user.rb +13 -0
- data/spec/test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/test_app/app/views/users/_form.html.erb +33 -0
- data/spec/test_app/app/views/users/edit.html.erb +6 -0
- data/spec/test_app/app/views/users/index.html.erb +29 -0
- data/spec/test_app/app/views/users/new.html.erb +5 -0
- data/spec/test_app/app/views/users/show.html.erb +25 -0
- data/spec/test_app/config.ru +4 -0
- data/spec/test_app/config/application.rb +65 -0
- data/spec/test_app/config/boot.rb +10 -0
- data/spec/test_app/config/database.yml +25 -0
- data/spec/test_app/config/environment.rb +14 -0
- data/spec/test_app/config/environments/development.rb +37 -0
- data/spec/test_app/config/environments/production.rb +67 -0
- data/spec/test_app/config/environments/test.rb +37 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/inflections.rb +15 -0
- data/spec/test_app/config/initializers/mime_types.rb +5 -0
- data/spec/test_app/config/initializers/secret_token.rb +7 -0
- data/spec/test_app/config/initializers/session_store.rb +8 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/test_app/config/locales/en.yml +5 -0
- data/spec/test_app/config/lockable.yml +3 -0
- data/spec/test_app/config/mail_manager.yml +21 -0
- data/spec/test_app/config/routes.rb +7 -0
- data/spec/test_app/db/migrate/20131217101010_create_users.rb +13 -0
- data/spec/test_app/db/migrate/20131221064151_mail_mgr_initial.rb +84 -0
- data/spec/test_app/db/migrate/20131221064152_mail_mgr_create_contact.rb +60 -0
- data/spec/test_app/db/migrate/20131221064153_mail_mgr_test_message.rb +23 -0
- data/spec/test_app/db/migrate/20131221064154_add_deleted_at_to_mailing_lists.rb +15 -0
- data/spec/test_app/db/migrate/20131221064155_contacts_deleted_at.rb +15 -0
- data/spec/test_app/db/migrate/20131221064156_mail_mgr_mailing_list_add_defaults_to_active.rb +15 -0
- data/spec/test_app/db/migrate/20131221064157_mail_mgr_message_add_from_email_address.rb +15 -0
- data/spec/test_app/db/migrate/20131221072600_create_delayed_jobs.rb +22 -0
- data/spec/test_app/db/schema.rb +131 -0
- data/spec/test_app/db/structure.sql +31 -0
- data/spec/test_app/public/404.html +26 -0
- data/spec/test_app/public/422.html +26 -0
- data/spec/test_app/public/500.html +25 -0
- data/spec/test_app/public/favicon.ico +0 -0
- data/spec/test_app/script/delayed_job +5 -0
- data/spec/test_app/script/lockable +36 -0
- data/spec/test_app/script/rails +6 -0
- data/spec/test_app/spec/controllers/users_controller_spec.rb +160 -0
- data/spec/test_app/spec/factories/mailing_lists.rb +7 -0
- data/spec/test_app/spec/factories/mailings.rb +6 -0
- data/spec/test_app/spec/factories/original_factories.rb.txt +107 -0
- data/spec/test_app/spec/factories/users.rb +10 -0
- data/spec/test_app/spec/models/mail_manager/bounce_spec.rb +17 -0
- data/spec/test_app/spec/models/mail_manager/mailing_list_spec.rb +15 -0
- data/spec/test_app/spec/models/user_spec.rb +37 -0
- data/spec/test_app/spec/requests/users_spec.rb +11 -0
- data/spec/test_app/spec/routing/users_routing_spec.rb +35 -0
- data/spec/test_app/spec/support/database_cleaner.rb +23 -0
- data/spec/test_app/spec/support/files/bad_utf8_chars.eml +32 -0
- data/spec/test_app/spec/views/users/edit.html.erb_spec.rb +24 -0
- data/spec/test_app/spec/views/users/index.html.erb_spec.rb +29 -0
- data/spec/test_app/spec/views/users/new.html.erb_spec.rb +24 -0
- data/spec/test_app/spec/views/users/show.html.erb_spec.rb +21 -0
- data/zeus.json +22 -0
- metadata +424 -0
|
@@ -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
|