mail_manager 3.2.7 → 3.2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +5 -1
- data/app/controllers/mail_manager/mailing_lists_controller.rb +1 -0
- data/app/models/mail_manager/bounce.rb +21 -4
- data/app/models/mail_manager/contact.rb +9 -1
- data/app/models/mail_manager/mailer.rb +5 -2
- data/app/models/mail_manager/mailing.rb +9 -1
- data/app/models/mail_manager/mailing_list.rb +2 -1
- data/app/models/mail_manager/message.rb +1 -1
- data/app/views/mail_manager/bounces/show.html.erb +1 -1
- data/app/views/mail_manager/mailings/_form.html.erb +2 -1
- data/app/views/mail_manager/mailings/show.html.erb +3 -3
- data/app/views/mail_manager/messages/index.html.erb +1 -1
- data/config/locales/mailings.en.yml +4 -0
- data/lib/mail_manager/config.rb +12 -2
- data/lib/mail_manager/version.rb +1 -1
- data/lib/workers/mail_manager/bounce_job.rb +7 -2
- data/mail_manager.gemspec +1 -0
- data/spec/test_app/features/contact_management.feature +2 -2
- data/spec/test_app/spec/models/mail_manager/bounce_spec.rb +54 -0
- data/spec/test_app/spec/models/mail_manager/mailing_spec.rb +24 -0
- data/spec/test_app/spec/support/files/bounce-500-no-from-address.eml +74 -0
- data/spec/test_app/spec/support/files/unsubscribe.txt +29 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e30049959f31c782b245392fadd2f276bd28360
|
4
|
+
data.tar.gz: 3af3e1fc8addf6210f31492e59b7d294c596f1f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f40f462c5dba56692d4d6f51d71ffb0f9dad57f27b689d1059c1ddb58dfff6e42654f70240d078d0c76fd40ab1460691f7fcdcff14cebba896214307bedfd2bc
|
7
|
+
data.tar.gz: 7acb1437d9253247e6eb00e2471a261ea8e7b53d3be37bb8fcea385c42958e9b99bdcc743526e7cf3a9c7738003ae7efd3688c17dd3f6be88a3f34ed0f2d8125
|
data/Gemfile
CHANGED
@@ -4,6 +4,7 @@ source 'https://rubygems.org'
|
|
4
4
|
gem 'dotenv-rails', :require => 'dotenv/rails-now'
|
5
5
|
gemspec
|
6
6
|
|
7
|
+
gem 'xpath', '~>2.1'
|
7
8
|
# jquery-rails is used by the dummy application
|
8
9
|
gem "devise"
|
9
10
|
gem "jquery-rails"
|
@@ -15,7 +16,7 @@ gem 'spring-commands-cucumber'
|
|
15
16
|
gem 'thor', '0.19.1'
|
16
17
|
gem 'delayed_job_active_record'
|
17
18
|
gem 'sqlite3'
|
18
|
-
gem 'mysql2'
|
19
|
+
gem 'mysql2', '~>0.3.21'
|
19
20
|
if ENV['POSTGRES']
|
20
21
|
gem 'pg'
|
21
22
|
end
|
@@ -26,6 +27,8 @@ group :test, :development do
|
|
26
27
|
gem "factory_girl_rails", "~>4.3"
|
27
28
|
gem "faker"
|
28
29
|
gem 'post_office'
|
30
|
+
gem 'brakeman'
|
31
|
+
gem 'bundler-audit'
|
29
32
|
end
|
30
33
|
|
31
34
|
#group :test, :development, :post_office do
|
@@ -42,5 +45,6 @@ group :test do
|
|
42
45
|
gem 'capybara'
|
43
46
|
gem 'poltergeist'
|
44
47
|
gem 'database_cleaner'
|
48
|
+
gem 'cucumber', '~>2.1'
|
45
49
|
gem 'cucumber-rails', require: false
|
46
50
|
end
|
@@ -22,7 +22,7 @@ module MailManager
|
|
22
22
|
belongs_to :message, :class_name => 'MailManager::Message'
|
23
23
|
belongs_to :mailing, :class_name => 'MailManager::Mailing', counter_cache: true
|
24
24
|
include StatusHistory
|
25
|
-
override_statuses(['needs_manual_intervention','unprocessed','dismissed','resolved','invalid','removed','deferred'],'unprocessed')
|
25
|
+
override_statuses(['needs_manual_intervention','unprocessed','dismissed','resolved','invalid','removed','deferred','unsubscribed'],'unprocessed')
|
26
26
|
before_create :set_default_status
|
27
27
|
#default_scope :order => "#{MailManager.table_prefix}contacts.last_name, #{MailManager.table_prefix}contacts.first_name, #{MailManager.table_prefix}contacts.email_address",
|
28
28
|
# :joins =>
|
@@ -43,7 +43,19 @@ module MailManager
|
|
43
43
|
if status.eql?('unprocessed') || force
|
44
44
|
self.message = Message.find_by_guid(bounce_message_guid)
|
45
45
|
self.mailing = message.mailing unless message.nil?
|
46
|
-
if
|
46
|
+
if email.subject.to_s =~ /unsubscribe/i
|
47
|
+
guid = email.subject.to_s.gsub(/unsubscribe from (.*)/,'\1')
|
48
|
+
self.message = Message.find_by_guid(guid)
|
49
|
+
self.mailing = message.mailing unless message.nil?
|
50
|
+
change_status(:unsubscribed)
|
51
|
+
if(message.present?)
|
52
|
+
MailManager::Subscription.unsubscribe_by_email_address(contact_email_address)
|
53
|
+
else
|
54
|
+
email.from.each do |email_address|
|
55
|
+
MailManager::Subscription.unsubscribe_by_email_address(email_address)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
elsif !from_mailer_daemon?
|
47
59
|
change_status(:invalid)
|
48
60
|
elsif delivery_error_code =~ /4\.\d\.\d/ || delivery_error_message.to_s =~ /quota/i
|
49
61
|
update_attribute(:comments, delivery_error_message)
|
@@ -52,8 +64,10 @@ module MailManager
|
|
52
64
|
transaction do
|
53
65
|
update_attribute(:comments, delivery_error_message)
|
54
66
|
change_status(:removed)
|
55
|
-
message.
|
56
|
-
|
67
|
+
if message.present?
|
68
|
+
message.change_status(:failed)
|
69
|
+
message.update_attribute(:result,"Failure Message from Bounce: #{delivery_error_message}")
|
70
|
+
end
|
57
71
|
Subscription.fail_by_email_address(contact_email_address)
|
58
72
|
end
|
59
73
|
else
|
@@ -70,6 +84,9 @@ module MailManager
|
|
70
84
|
|
71
85
|
def from_mailer_daemon?
|
72
86
|
['postmaster','mailer-daemon'].include?(email.from.first.gsub(/\@.*$/,'').downcase)
|
87
|
+
rescue => e
|
88
|
+
# they don't have a proper from email address
|
89
|
+
delivery_error_code.present?
|
73
90
|
end
|
74
91
|
|
75
92
|
def dismiss
|
@@ -10,7 +10,9 @@ module MailManager
|
|
10
10
|
validates_presence_of :email_address
|
11
11
|
#validates_format_of :email_address, :with => Authentication.email_regex,
|
12
12
|
# :message => Authentication.bad_email_message, :allow_nil => true
|
13
|
-
validates_format_of :email_address, :with => /\w
|
13
|
+
validates_format_of :email_address, :with => /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i, :allow_nil => true
|
14
|
+
|
15
|
+
before_validation :trim_fields
|
14
16
|
|
15
17
|
include MailManager::ContactableRegistry::Contactable
|
16
18
|
include Deleteable
|
@@ -20,6 +22,12 @@ module MailManager
|
|
20
22
|
def contact
|
21
23
|
self
|
22
24
|
end
|
25
|
+
|
26
|
+
def trim_fields
|
27
|
+
[:first_name, :last_name, :email_address].each do |field|
|
28
|
+
self[field].gsub!(/\A\s*|\s*\Z/,'') if self[field].present?
|
29
|
+
end
|
30
|
+
end
|
23
31
|
|
24
32
|
scope :search, lambda{|params|
|
25
33
|
conditions = ["deleted_at IS NULL"]
|
@@ -53,7 +53,7 @@ module MailManager
|
|
53
53
|
def deliver_message(message, cached_parts=nil)
|
54
54
|
cached_parts ||= message.parts
|
55
55
|
self.send_mail(message.subject,message.email_address_with_name,message.from_email_address,
|
56
|
-
cached_parts,message.guid,message.mailing.include_images
|
56
|
+
cached_parts,message.guid,message.mailing.include_images?,message.unsubscribe_url)
|
57
57
|
end
|
58
58
|
|
59
59
|
# create mailing; parsing html sources for images to attach/include
|
@@ -108,7 +108,7 @@ module MailManager
|
|
108
108
|
end
|
109
109
|
|
110
110
|
# send the mailing with the given subject, addresses, and parts
|
111
|
-
def send_mail(subject,to_email_address,from_email_address,the_parts,message_id=nil,include_images=true)
|
111
|
+
def send_mail(subject,to_email_address,from_email_address,the_parts,message_id=nil,include_images=true,unsubscribe_url=nil)
|
112
112
|
include_images = (include_images and !MailManager.dont_include_images_domains.detect{|domain|
|
113
113
|
to_email_address.strip =~ /#{domain}>?$/})
|
114
114
|
mail = if include_images
|
@@ -118,6 +118,9 @@ module MailManager
|
|
118
118
|
end
|
119
119
|
mail.header['Return-Path'] = MailManager.bounce['email_address']
|
120
120
|
mail.header['X-Bounce-Guid'] = message_id if message_id
|
121
|
+
unsubscribe_header = "<mailto:#{MailManager.bounce['email_address']}?subject=unsubscribe%20from%20#{message_id}>"
|
122
|
+
unsubscribe_header += ",<#{unsubscribe_url}>" if unsubscribe_url.present?
|
123
|
+
mail.header['List-Unsubscribe'] = unsubscribe_header
|
121
124
|
set_mail_settings(mail)
|
122
125
|
mail.deliver!
|
123
126
|
Rails.logger.info "Sent mail to: #{to_email_address}"
|
@@ -155,7 +155,8 @@ module MailManager
|
|
155
155
|
# creates all of the Messages that will be sent for this mailing
|
156
156
|
def initialize_messages
|
157
157
|
emails_hash = MailManager::Message.email_address_hash_for_mailing_id(self.id)
|
158
|
-
|
158
|
+
# NOTE: the following over-protective line has been removed as per Ken's request 2017-12-21
|
159
|
+
# emails_hash.merge!(MailManager::Subscription.unsubscribed_emails_hash)
|
159
160
|
ids = self.mailing_lists.select('id').map(&:id)
|
160
161
|
active_subscriptions_hash = MailManager::MailingList.
|
161
162
|
active_email_addresses_contact_ids_subscription_ids_for_mailing_list_ids(ids)
|
@@ -168,6 +169,13 @@ module MailManager
|
|
168
169
|
})
|
169
170
|
end
|
170
171
|
end
|
172
|
+
|
173
|
+
def delete
|
174
|
+
transaction do
|
175
|
+
super
|
176
|
+
job.try(:destroy)
|
177
|
+
end
|
178
|
+
end
|
171
179
|
|
172
180
|
# clean up an email address for sending FIXME - maybe do a bit more
|
173
181
|
def self.clean_email_address(email_address)
|
@@ -20,6 +20,7 @@ module MailManager
|
|
20
20
|
validates :name, presence: true
|
21
21
|
|
22
22
|
include StatusHistory
|
23
|
+
include Deleteable if (column_names.include?('deleted_at') rescue false)
|
23
24
|
before_create :set_default_status
|
24
25
|
|
25
26
|
attr_protected :id
|
@@ -32,7 +33,7 @@ module MailManager
|
|
32
33
|
s.id as subscription_id from #{MailManager.table_prefix}contacts c
|
33
34
|
inner join #{MailManager.table_prefix}subscriptions s on c.id=s.contact_id
|
34
35
|
where s.status in ('active') and c.deleted_at is NULL and mailing_list_id in (#{
|
35
|
-
mailing_list_ids.join(',')})|
|
36
|
+
mailing_list_ids.map(&:to_i).uniq.join(',')})|
|
36
37
|
)
|
37
38
|
results = results.map(&:values) if results.first.is_a?(Hash)
|
38
39
|
results.inject(Hash.new){ |h,r|
|
@@ -39,7 +39,7 @@ module MailManager
|
|
39
39
|
%Q|select distinct c.email_address
|
40
40
|
from #{MailManager.table_prefix}contacts c
|
41
41
|
inner join #{MailManager.table_prefix}messages m
|
42
|
-
on c.id=m.contact_id where m.mailing_id=#{mailing_id}|
|
42
|
+
on c.id=m.contact_id where m.mailing_id=#{mailing_id.to_i}|
|
43
43
|
)
|
44
44
|
results = results.map(&:values) if results.first.is_a?(Hash)
|
45
45
|
results.inject(Hash.new){|h,r|h.merge!(r[0].to_s.strip.downcase => true)}
|
@@ -37,7 +37,8 @@
|
|
37
37
|
<p>
|
38
38
|
<% @all_mailing_lists.each do |mailing_list| %>
|
39
39
|
<%= check_box_tag 'mailing[mailing_list_ids][]', mailing_list.id, @mailing.mailing_lists.include?(mailing_list) %>
|
40
|
-
<%= label_tag :mailing_mailing_list_ids_, "#{mailing_list.name}"
|
40
|
+
<%= label_tag :mailing_mailing_list_ids_, "#{mailing_list.name}" %>
|
41
|
+
<div style="clear: left;"></div>
|
41
42
|
<% end %>
|
42
43
|
</p>
|
43
44
|
</div>
|
@@ -10,12 +10,12 @@
|
|
10
10
|
|
11
11
|
<p>
|
12
12
|
<b>Status changed at:</b>
|
13
|
-
<%=
|
13
|
+
<%=l @mailing.status_changed_at %>
|
14
14
|
</p>
|
15
15
|
|
16
16
|
<p>
|
17
17
|
<b>Scheduled at:</b>
|
18
|
-
<%=
|
18
|
+
<%=l @mailing.scheduled_at %>
|
19
19
|
</p>
|
20
20
|
|
21
21
|
<p>
|
@@ -25,4 +25,4 @@
|
|
25
25
|
|
26
26
|
|
27
27
|
<%= link_to 'Edit', mail_manager.edit_mailing_path(@mailing) %> |
|
28
|
-
<%= link_to 'Back', mail_manager.mailings_path %>
|
28
|
+
<%= link_to 'Back', mail_manager.mailings_path %>
|
data/lib/mail_manager/config.rb
CHANGED
@@ -12,10 +12,20 @@ class MailManager::Config
|
|
12
12
|
|
13
13
|
def use_file!(file)
|
14
14
|
begin
|
15
|
-
hash = YAML::load(ERB.new(IO.read(file)).result)
|
16
|
-
|
15
|
+
hash = YAML::load(ERB.new(IO.read(file)).result).with_indifferent_access
|
16
|
+
key = old_val = new_val = nil
|
17
|
+
@sections.merge!(hash) do |key, old_val, new_val|
|
18
|
+
old_val ||= Hash.new.with_indifferent_access
|
19
|
+
new_val ||= Hash.new.with_indifferent_access
|
20
|
+
if old_val.is_a?(Hash) && new_val.is_a?(Hash)
|
21
|
+
old_val.merge(new_val)
|
22
|
+
else
|
23
|
+
new_val
|
24
|
+
end
|
25
|
+
end
|
17
26
|
@params.merge!(@sections['common'])
|
18
27
|
rescue => e
|
28
|
+
Rails.logger.error "Couldn't load config file #{file} #{e.message}"
|
19
29
|
nil
|
20
30
|
end
|
21
31
|
end
|
data/lib/mail_manager/version.rb
CHANGED
@@ -31,13 +31,18 @@ module MailManager
|
|
31
31
|
found_messages = true
|
32
32
|
Rails.logger.info "You have #{pop.mails.length} new bounced messages."
|
33
33
|
Rails.logger.info "Downloading..."
|
34
|
-
|
34
|
+
max_messages = 50
|
35
|
+
num_messages = 0
|
35
36
|
pop.mails.each_with_index do|m,i|
|
36
37
|
bounce = ::MailManager::Bounce.create({
|
37
|
-
|
38
|
+
# ensure encoding will work; we don't really care about invalid characters
|
39
|
+
# PG will explode if utf-8 has invalid chars
|
40
|
+
:bounce_message => m.pop.encode("utf-8", invalid: :replace, undef: :replace)
|
38
41
|
})
|
39
42
|
bounce.process
|
40
43
|
m.delete
|
44
|
+
num_messages += 1
|
45
|
+
break if num_messages > max_messages
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
data/mail_manager.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.homepage = "http://ireachnews.com"
|
15
15
|
|
16
16
|
gem.add_dependency "rails", "~>3.2"
|
17
|
+
gem.add_dependency 'rack-protection', '=2.0.1'
|
17
18
|
gem.add_dependency 'jquery-rails', "~>3.1"
|
18
19
|
gem.add_dependency 'jquery-ui-rails', "~>5.0"
|
19
20
|
gem.add_dependency 'jquery-ui-themes', "~>0.0"
|
@@ -45,7 +45,7 @@ Feature: Manage Contacts
|
|
45
45
|
When I go to the new contact page
|
46
46
|
And I fill in "First name" with "Bobo"
|
47
47
|
And I fill in "Last name" with "Clown"
|
48
|
-
And I fill in "Email address" with "bobo@example.com"
|
48
|
+
And I fill in "Email address" with "bobo@example.com "
|
49
49
|
And I check "Peeps"
|
50
50
|
And I press "Submit"
|
51
51
|
Then contact "Bobo Clown" should exist with email_address "bobo@example.com"
|
@@ -69,7 +69,7 @@ Feature: Manage Contacts
|
|
69
69
|
And I follow "Edit"
|
70
70
|
And I fill in "First name" with "Bobo"
|
71
71
|
And I fill in "Last name" with "Clown"
|
72
|
-
And I fill in "Email address" with "bobo@example.com"
|
72
|
+
And I fill in "Email address" with " bobo@example.com"
|
73
73
|
And I check "Peeps"
|
74
74
|
And I press "Submit"
|
75
75
|
Then contact "Bobo Clown" should exist with email_address "bobo@example.com"
|
@@ -3,6 +3,13 @@ require 'rails_helper'
|
|
3
3
|
|
4
4
|
RSpec.describe MailManager::Bounce do
|
5
5
|
context "when checking pop account" do
|
6
|
+
it "should not blow up when mail has no from address" do
|
7
|
+
bounce = create_bounce_from_file('bounce-500-no-from-address.eml')
|
8
|
+
expect{bounce.process}.not_to raise_exception
|
9
|
+
expect(bounce.message.status).to eq 'failed'
|
10
|
+
expect(bounce.status).to eq 'removed'
|
11
|
+
Delayed::Worker.delay_jobs = false
|
12
|
+
end
|
6
13
|
it "should not blow up when mail contains a bad extended char" do
|
7
14
|
Delayed::Worker.delay_jobs = true
|
8
15
|
send_bounce('bad_utf8_chars.eml')
|
@@ -61,6 +68,45 @@ RSpec.describe MailManager::Bounce do
|
|
61
68
|
expect(sub1.status).to eq 'failed_address'
|
62
69
|
expect(MailManager::Subscription.count).to eq 1
|
63
70
|
end
|
71
|
+
it "unsubscribes an address when a bounce has 'unsubscribe' in its subject" do
|
72
|
+
contact = FactoryGirl.create(:contact, email_address: 'bobo@example.net')
|
73
|
+
mailing_list = FactoryGirl.create(:mailing_list)
|
74
|
+
mailing_list2 = FactoryGirl.create(:mailing_list)
|
75
|
+
sub1=contact.subscribe(mailing_list)
|
76
|
+
|
77
|
+
bounce = MailManager::Bounce.create(
|
78
|
+
bounce_message: File.read('spec/support/files/unsubscribe.txt')
|
79
|
+
)
|
80
|
+
bounce.process
|
81
|
+
|
82
|
+
sub1.reload
|
83
|
+
expect(bounce.status).to eq 'unsubscribed'
|
84
|
+
expect(sub1.status).to eq 'unsubscribed'
|
85
|
+
expect(MailManager::Subscription.count).to eq 1
|
86
|
+
end
|
87
|
+
it "unsubscribes from a messages's contact when it's guid is in the subject" do
|
88
|
+
contact = FactoryGirl.create(:contact, email_address: 'bobo_other@example.net')
|
89
|
+
mailing_list = FactoryGirl.create(:mailing_list)
|
90
|
+
mailing_list2 = FactoryGirl.create(:mailing_list)
|
91
|
+
sub1=contact.subscribe(mailing_list)
|
92
|
+
mailing = FactoryGirl.create(:mailing)
|
93
|
+
message = FactoryGirl.create(:message,
|
94
|
+
mailing_id: mailing.id,
|
95
|
+
contact_id: contact.id
|
96
|
+
)
|
97
|
+
|
98
|
+
bounce = MailManager::Bounce.create(
|
99
|
+
bounce_message: File.read('spec/support/files/unsubscribe.txt').gsub(
|
100
|
+
/Subject: unsubscribe/,"Subject: unsubscribe from #{message.guid}"
|
101
|
+
)
|
102
|
+
)
|
103
|
+
bounce.process
|
104
|
+
|
105
|
+
sub1.reload
|
106
|
+
expect(bounce.status).to eq 'unsubscribed'
|
107
|
+
expect(sub1.status).to eq 'unsubscribed'
|
108
|
+
expect(MailManager::Subscription.count).to eq 1
|
109
|
+
end
|
64
110
|
end
|
65
111
|
def send_bounce(filename)
|
66
112
|
mail = Mail.new(File.read(File.join(Rails.root,'spec','support','files',filename)))
|
@@ -68,4 +114,12 @@ RSpec.describe MailManager::Bounce do
|
|
68
114
|
mail.delivery_method.settings.merge!(ActionMailer::Base.smtp_settings)
|
69
115
|
mail.deliver
|
70
116
|
end
|
117
|
+
def create_bounce_from_file(filename)
|
118
|
+
mail_message = File.read(File.join(Rails.root,'spec','support','files',filename))
|
119
|
+
bounce = MailManager::Bounce.create(bounce_message: mail_message)
|
120
|
+
message = FactoryGirl.create(:message)
|
121
|
+
message.guid = bounce.bounce_message_guid
|
122
|
+
message.save
|
123
|
+
bounce
|
124
|
+
end
|
71
125
|
end
|
@@ -42,6 +42,21 @@ RSpec.describe MailManager::Mailing do
|
|
42
42
|
expect(MailManager::Mailing.count).to eq 0
|
43
43
|
expect(MailManager::Mailing.deleted.count).to eq 1
|
44
44
|
end
|
45
|
+
it "will remove the scheduled job on deletion" do
|
46
|
+
Delayed::Job.delete_all
|
47
|
+
expect(Delayed::Job.count).to eq 0
|
48
|
+
Delayed::Worker.delay_jobs = true
|
49
|
+
mailing = MailManager::Mailing.create(valid_attributes.merge({
|
50
|
+
scheduled_at: 4.hours.from_now
|
51
|
+
}))
|
52
|
+
mailing.schedule
|
53
|
+
expect(Delayed::Job.count).to eq 1
|
54
|
+
expect(mailing.job).to eq Delayed::Job.first
|
55
|
+
mailing.delete
|
56
|
+
expect(MailManager::Mailing.deleted.count).to eq 1
|
57
|
+
expect(Delayed::Job.count).to eq 0
|
58
|
+
Delayed::Worker.delay_jobs = false
|
59
|
+
end
|
45
60
|
it "doesn't include images when configured to not do so for a domain" do
|
46
61
|
# should be in config
|
47
62
|
image_url = "http://www.lone-star.net/graphics/lst_header_logo.png"
|
@@ -147,6 +162,15 @@ RSpec.describe MailManager::Mailing do
|
|
147
162
|
expect(MyMailable.mailable_parts_call_count).to eq 1
|
148
163
|
end
|
149
164
|
|
165
|
+
it "creates its 'List-Unsubscribe' headers correctly" do
|
166
|
+
@mailing.initialize_messages
|
167
|
+
message = @mailing.messages.first
|
168
|
+
message.deliver
|
169
|
+
sent_message = ActionMailer::Base.deliveries.last.to_s
|
170
|
+
unsubscribe_header = "<mailto:#{MailManager.bounce['email_address']}?subject=unsubscribe%20from%20#{message.guid}>,<#{message.unsubscribe_url}>"
|
171
|
+
expect(sent_message.include?(unsubscribe_header)).to be true
|
172
|
+
end
|
173
|
+
|
150
174
|
it "sends a specified number of messages per job" do
|
151
175
|
expect(Delayed::Job.count).to eq 1
|
152
176
|
expect(MailManager.deliveries_per_run).to be > 0
|
@@ -0,0 +1,74 @@
|
|
1
|
+
Return-Path: <MAILER-DAEMON>
|
2
|
+
Received: from zapp.lnstar.com (zapp.lnstar.com [66.45.121.18])
|
3
|
+
by farnsworth.lnstar.com (8.13.8/8.13.8) with ESMTP id t1A0H8kt030070
|
4
|
+
for <bounce@austinflowers.com>; Mon, 9 Feb 2015 18:17:08 -0600
|
5
|
+
Received: by zapp.lnstar.com (Postfix)
|
6
|
+
id EBE6A10E6E2; Mon, 9 Feb 2015 18:17:08 -0600 (CST)
|
7
|
+
Date: Mon, 9 Feb 2015 18:17:08 -0600 (CST)
|
8
|
+
Subject: Undelivered Mail Returned to Sender
|
9
|
+
To: bounce@austinflowers.com
|
10
|
+
Auto-Submitted: auto-replied
|
11
|
+
MIME-Version: 1.0
|
12
|
+
Content-Type: multipart/report; report-type=delivery-status;
|
13
|
+
boundary="6800110E6EE.1423527428/zapp.lnstar.com"
|
14
|
+
Message-Id: <20150210001708.EBE6A10E6E2@zapp.lnstar.com>
|
15
|
+
X-Spam-Status: No, score=-2.9 required=5.0 tests=ALL_TRUSTED,BAYES_00,
|
16
|
+
URIBL_DBL_ABUSE_REDIR autolearn=ham version=3.3.2
|
17
|
+
X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on
|
18
|
+
farnsworth.lnstar.com
|
19
|
+
|
20
|
+
This is a MIME-encapsulated message.
|
21
|
+
|
22
|
+
--6800110E6EE.1423527428/zapp.lnstar.com
|
23
|
+
Content-Description: Notification
|
24
|
+
Content-Type: text/plain; charset=us-ascii
|
25
|
+
|
26
|
+
This is the mail system at host zapp.lnstar.com.
|
27
|
+
|
28
|
+
I'm sorry to have to inform you that your message could not
|
29
|
+
be delivered to one or more recipients. It's attached below.
|
30
|
+
|
31
|
+
For further assistance, please send mail to postmaster.
|
32
|
+
|
33
|
+
If you do so, please include this problem report. You can
|
34
|
+
delete your own text from the attached returned message.
|
35
|
+
|
36
|
+
The mail system
|
37
|
+
|
38
|
+
<roz@gocseevents.com>: host presmtp.ex4.secureserver.net[72.167.238.29] said:
|
39
|
+
550 5.1.1 <roz@gocseevents.com> Recipient not found.
|
40
|
+
<http://x.co/irbounce> (in reply to RCPT TO command)
|
41
|
+
|
42
|
+
--6800110E6EE.1423527428/zapp.lnstar.com
|
43
|
+
Content-Description: Delivery report
|
44
|
+
Content-Type: message/delivery-status
|
45
|
+
|
46
|
+
Reporting-MTA: dns; zapp.lnstar.com
|
47
|
+
X-Postfix-Queue-ID: 6800110E6EE
|
48
|
+
X-Postfix-Sender: rfc822; bounce@austinflowers.com
|
49
|
+
Arrival-Date: Mon, 9 Feb 2015 18:17:07 -0600 (CST)
|
50
|
+
|
51
|
+
Final-Recipient: rfc822; roz@gocseevents.com
|
52
|
+
Action: failed
|
53
|
+
Status: 5.1.1
|
54
|
+
Remote-MTA: dns; presmtp.ex4.secureserver.net
|
55
|
+
Diagnostic-Code: smtp; 550 5.1.1 <roz@gocseevents.com> Recipient not found.
|
56
|
+
<http://x.co/irbounce>
|
57
|
+
|
58
|
+
--6800110E6EE.1423527428/zapp.lnstar.com
|
59
|
+
Content-Description: Undelivered Message Headers
|
60
|
+
Content-Type: text/rfc822-headers
|
61
|
+
|
62
|
+
Return-Path: <bounce@austinflowers.com>
|
63
|
+
Received: by zapp.lnstar.com (Postfix, from userid 65534)
|
64
|
+
id 6800110E6EE; Mon, 9 Feb 2015 18:17:07 -0600 (CST)
|
65
|
+
Date: Mon, 9 Feb 2015 18:17:07 -0600
|
66
|
+
From: "SanAntonioFlowerCo." <news@sanantonioflowers.com>
|
67
|
+
To: roz@gocseevents.com
|
68
|
+
Subject: Valentines Day 2015!
|
69
|
+
Mime-Version: 1.0
|
70
|
+
Content-Type: multipart/alternative; boundary=mimepart_54d94e034d23e_50d9..fdbe370dc1560
|
71
|
+
X-Bounce-Guid: 30-28-11376-fa351cf35e4012d37d8c13df8735fd13edfed563
|
72
|
+
Message-Id: <20150210001707.6800110E6EE@zapp.lnstar.com>
|
73
|
+
|
74
|
+
--6800110E6EE.1423527428/zapp.lnstar.com--
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Return-Path: <chauboldt@lone-star.net>
|
2
|
+
X-Original-To: chris@hauboldt.us
|
3
|
+
Delivered-To: chrisboy@ophanim.hauboldt.us
|
4
|
+
Received: from enoch.hauboldt.us (enoch.hauboldt.us [45.56.75.249])
|
5
|
+
by ophanim.hauboldt.us (Postfix) with ESMTP id 451539CD2C
|
6
|
+
for <chris@hauboldt.us>; Mon, 13 Mar 2017 10:00:11 -0500 (CDT)
|
7
|
+
Received: from mail.lnstar.com (mail.lnstar.com [96.126.122.158])
|
8
|
+
by enoch.hauboldt.us (Postfix) with ESMTPS id B90B22E0A2
|
9
|
+
for <chris@gylo.us>; Mon, 13 Mar 2017 15:00:10 +0000 (UTC)
|
10
|
+
Received: from [20.10.10.11] (r74-193-50-146.gldwcmta01.glwttx.tl.dh.suddenlink.net [74.193.50.146])
|
11
|
+
(authenticated bits=0)
|
12
|
+
by mail.lnstar.com (8.14.4/8.13.8) with ESMTP id v2DF09Ne006687
|
13
|
+
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
|
14
|
+
for <chris@gylo.us>; Mon, 13 Mar 2017 10:00:09 -0500
|
15
|
+
To: bounce@example.net
|
16
|
+
From: Bobo Clown<bobo@example.net>
|
17
|
+
Subject: unsubscribe
|
18
|
+
Message-ID: <e1b39be4-254d-7486-3d36-cf8b583fb0cd@lone-star.net>
|
19
|
+
Date: Mon, 13 Mar 2017 10:00:04 -0500
|
20
|
+
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101
|
21
|
+
Thunderbird/45.7.1
|
22
|
+
MIME-Version: 1.0
|
23
|
+
Content-Type: text/plain; charset=utf-8
|
24
|
+
Content-Transfer-Encoding: 7bit
|
25
|
+
X-Spam-Status: No, score=-1.5 required=5.0 tests=ALL_TRUSTED,BAYES_05,
|
26
|
+
TVD_SPACE_RATIO autolearn=ham version=3.3.2
|
27
|
+
X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on Mail
|
28
|
+
|
29
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mail_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lone Star Internet
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-05-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -25,6 +25,20 @@ dependencies:
|
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '3.2'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rack-protection
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.0.1
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 2.0.1
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: jquery-rails
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -209,6 +223,7 @@ files:
|
|
209
223
|
- ".ruby-gemset"
|
210
224
|
- ".ruby-version"
|
211
225
|
- Gemfile
|
226
|
+
- Gemfile.lock
|
212
227
|
- Guardfile
|
213
228
|
- LICENSE.txt
|
214
229
|
- MIT-LICENSE
|
@@ -485,6 +500,7 @@ files:
|
|
485
500
|
- spec/test_app/spec/support/database_cleaner.rb
|
486
501
|
- spec/test_app/spec/support/files/bad_utf8_chars.eml
|
487
502
|
- spec/test_app/spec/support/files/bounce-400.txt
|
503
|
+
- spec/test_app/spec/support/files/bounce-500-no-from-address.eml
|
488
504
|
- spec/test_app/spec/support/files/bounce-500.txt
|
489
505
|
- spec/test_app/spec/support/files/bounce-invalid-address.txt
|
490
506
|
- spec/test_app/spec/support/files/bounce-invalid.txt
|
@@ -496,6 +512,7 @@ files:
|
|
496
512
|
- spec/test_app/spec/support/files/bounce-unknown_domain.txt
|
497
513
|
- spec/test_app/spec/support/files/mail_manager_empty_table_prefix.yml
|
498
514
|
- spec/test_app/spec/support/files/mail_manager_use_generic_mailables.yml
|
515
|
+
- spec/test_app/spec/support/files/unsubscribe.txt
|
499
516
|
- spec/test_app/spec/views/mail_manager/bounces/index.html.erb_spec.rb
|
500
517
|
- spec/test_app/spec/views/mail_manager/bounces/show.html.erb_spec.rb
|
501
518
|
- spec/test_app/spec/views/users/edit.html.erb_spec.rb
|
@@ -671,6 +688,7 @@ test_files:
|
|
671
688
|
- spec/test_app/spec/support/database_cleaner.rb
|
672
689
|
- spec/test_app/spec/support/files/bad_utf8_chars.eml
|
673
690
|
- spec/test_app/spec/support/files/bounce-400.txt
|
691
|
+
- spec/test_app/spec/support/files/bounce-500-no-from-address.eml
|
674
692
|
- spec/test_app/spec/support/files/bounce-500.txt
|
675
693
|
- spec/test_app/spec/support/files/bounce-invalid-address.txt
|
676
694
|
- spec/test_app/spec/support/files/bounce-invalid.txt
|
@@ -682,6 +700,7 @@ test_files:
|
|
682
700
|
- spec/test_app/spec/support/files/bounce-unknown_domain.txt
|
683
701
|
- spec/test_app/spec/support/files/mail_manager_empty_table_prefix.yml
|
684
702
|
- spec/test_app/spec/support/files/mail_manager_use_generic_mailables.yml
|
703
|
+
- spec/test_app/spec/support/files/unsubscribe.txt
|
685
704
|
- spec/test_app/spec/views/mail_manager/bounces/index.html.erb_spec.rb
|
686
705
|
- spec/test_app/spec/views/mail_manager/bounces/show.html.erb_spec.rb
|
687
706
|
- spec/test_app/spec/views/users/edit.html.erb_spec.rb
|