mlist 0.1.18 → 0.1.19
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.
- data/CHANGELOG +4 -0
- data/VERSION.yml +1 -1
- data/lib/mlist/email_subscriber.rb +3 -3
- data/lib/mlist/list.rb +30 -30
- data/lib/mlist/mail_list.rb +1 -1
- data/lib/mlist/manager/database.rb +13 -13
- data/lib/mlist/manager/notifier.rb +6 -6
- data/lib/mlist/message.rb +22 -22
- data/lib/mlist/util/email_helpers.rb +1 -1
- data/spec/fixtures/schema.rb +14 -14
- data/spec/integration/mlist_spec.rb +35 -35
- data/spec/models/mail_list_spec.rb +2 -2
- metadata +3 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
*0.1.19 [Enhancement] (2010-08-12)
|
2
|
+
|
3
|
+
* Requiring subscriber instances to respond to 'rfc5322_email' instead of 'email_address' in order to allow the latter name to be used in associations. [aiwilliams]
|
4
|
+
|
1
5
|
*0.1.18 [Enhancement] (2010-06-11)
|
2
6
|
|
3
7
|
* Moving mail that has no rfc822 content into a settings[:failure_folder], if that setting is provided. [aiwilliams]
|
data/VERSION.yml
CHANGED
data/lib/mlist/list.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
module MList
|
2
|
-
|
2
|
+
|
3
3
|
# Represents the interface of the lists that a list manager must answer.
|
4
4
|
# This is distinct from the MList::MailList to allow for greater flexibility
|
5
5
|
# in processing email coming to a list - that is, whatever you include this
|
6
6
|
# into may re-define behavior appropriately.
|
7
7
|
#
|
8
|
-
# Your 'subscriber' instances MUST respond to :
|
9
|
-
# optionally respond to :display_name.
|
8
|
+
# Your 'subscriber' instances MUST respond to :rfc5322_email. They
|
9
|
+
# may optionally respond to :display_name.
|
10
10
|
#
|
11
11
|
module List
|
12
|
-
|
12
|
+
|
13
13
|
# Answers whether this list is active or not. All lists are active all the
|
14
14
|
# time by default.
|
15
15
|
#
|
16
16
|
def active?
|
17
17
|
true
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
# Answers whether the email has been to this list before. The simplest
|
21
21
|
# test is whether the email has an X-BeenThere header that matches this
|
22
22
|
# list's address.
|
@@ -24,28 +24,28 @@ module MList
|
|
24
24
|
def been_here?(email)
|
25
25
|
email.been_there_addresses.include?(address.downcase)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
# Answers whether the subscriber is blocked from posting or not. This will
|
29
29
|
# not be asked when the list is not active (answers _active?_ as false).
|
30
30
|
#
|
31
31
|
def blocked?(subscriber)
|
32
32
|
false
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# Answers the footer content for this list. Default implementation is very
|
36
36
|
# simple.
|
37
37
|
#
|
38
38
|
def footer_content(message)
|
39
39
|
%Q{The "#{label}" mailing list\nPost messages: #{post_url}}
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
# Answer a suitable label for the list, which will be used in various
|
43
43
|
# parts of content that is delivered to subscribers, etc.
|
44
44
|
#
|
45
45
|
def label
|
46
46
|
raise 'answer the list label'
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
# Answers the headers that are to be included in the emails delivered for
|
50
50
|
# this list. Any entries that have a nil value will not be included in the
|
51
51
|
# delivered email.
|
@@ -61,20 +61,20 @@ module MList
|
|
61
61
|
'list-post' => post_url
|
62
62
|
}
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
# Answers a unique, never changing value for this list.
|
66
66
|
#
|
67
67
|
def list_id
|
68
68
|
raise 'answer a unique, never changing value'
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
# The web address where an archive of this list may be found, nil if there
|
72
72
|
# is no archive.
|
73
73
|
#
|
74
74
|
def archive_url
|
75
75
|
nil
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
# Should the sender of an email be copied in the publication? Defaults to
|
79
79
|
# false. If _recipients_ includes the sender email address, it will be
|
80
80
|
# removed if this answers false.
|
@@ -84,47 +84,47 @@ module MList
|
|
84
84
|
def copy_sender?(subscriber)
|
85
85
|
false
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
# The web address of the list help site, nil if this is not supported.
|
89
89
|
#
|
90
90
|
def help_url
|
91
91
|
nil
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
# The email address of the list owner, nil if this is not supported.
|
95
95
|
#
|
96
96
|
def owner_url
|
97
97
|
nil
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
# The email address where posts should be sent. Defaults to the address of
|
101
101
|
# the list.
|
102
102
|
#
|
103
103
|
def post_url
|
104
104
|
address
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
# Should the reply-to header be set to the list's address? Defaults to
|
108
108
|
# true. If false is returned, the reply-to will be the subscriber address.
|
109
109
|
#
|
110
110
|
def reply_to_list?
|
111
111
|
true
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
# The web url where subscriptions to this list may be created, nil if this
|
115
115
|
# is not supported.
|
116
116
|
#
|
117
117
|
def subscribe_url
|
118
118
|
nil
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
# The web url where subscriptions to this list may be deleted, nil if this
|
122
122
|
# is not supported.
|
123
123
|
#
|
124
124
|
def unsubscribe_url
|
125
125
|
nil
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
# A list is responsible for answering the recipient subscribers. The
|
129
129
|
# answer may or may not include the subscriber; _copy_sender?_ will be
|
130
130
|
# invoked and the subscriber will be added or removed from the Array.
|
@@ -135,16 +135,16 @@ module MList
|
|
135
135
|
def recipients(subscriber)
|
136
136
|
subscribers
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
# A list must answer the subscriber who's email address is that of the one
|
140
140
|
# provided. The default implementation will pick the first instance that
|
141
|
-
# answers subscriber.
|
141
|
+
# answers subscriber.rfc5322_email == email_address. Your implementation
|
142
142
|
# should probably select just one record.
|
143
143
|
#
|
144
144
|
def subscriber(email_address)
|
145
|
-
subscribers.detect {|s| s.
|
145
|
+
subscribers.detect {|s| s.rfc5322_email == email_address}
|
146
146
|
end
|
147
|
-
|
147
|
+
|
148
148
|
# A list must answer whether there is a subscriber who's email address is
|
149
149
|
# that of the one provided. This is checked before the subscriber is
|
150
150
|
# requested in order to allow for the lightest weight check possible; that
|
@@ -154,12 +154,12 @@ module MList
|
|
154
154
|
def subscriber?(email_address)
|
155
155
|
!subscriber(email_address).nil?
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
# Methods that will be invoked on your implementation of Mlist::List when
|
159
159
|
# certain events occur during the processing of email sent to a list.
|
160
160
|
#
|
161
161
|
module Callbacks
|
162
|
-
|
162
|
+
|
163
163
|
# Called when an email is a post to the list by a subscriber whom the
|
164
164
|
# list claims is blocked (answers true to _blocked?(subscriber)_). This
|
165
165
|
# will not be called if the list is inactive (answers false to
|
@@ -167,10 +167,10 @@ module MList
|
|
167
167
|
#
|
168
168
|
def blocked_subscriber_post(email, subscriber)
|
169
169
|
end
|
170
|
-
|
170
|
+
|
171
171
|
def bounce(email)
|
172
172
|
end
|
173
|
-
|
173
|
+
|
174
174
|
# Called when an email is a post to the list while the list is inactive
|
175
175
|
# (answers false to _active?_). This will not be called if the email is
|
176
176
|
# from a non-subscribed sender. Instead, _non_subscriber_post_ will be
|
@@ -178,7 +178,7 @@ module MList
|
|
178
178
|
#
|
179
179
|
def inactive_post(email)
|
180
180
|
end
|
181
|
-
|
181
|
+
|
182
182
|
# Called when an email is a post to the list from a non-subscribed
|
183
183
|
# sender. This will be called even if the list is inactive.
|
184
184
|
#
|
@@ -186,6 +186,6 @@ module MList
|
|
186
186
|
end
|
187
187
|
end
|
188
188
|
include Callbacks
|
189
|
-
|
189
|
+
|
190
190
|
end
|
191
|
-
end
|
191
|
+
end
|
data/lib/mlist/mail_list.rb
CHANGED
@@ -209,7 +209,7 @@ module MList
|
|
209
209
|
message.subject = clean_subject(message.subject)
|
210
210
|
|
211
211
|
recipient_addresses = message.recipient_addresses
|
212
|
-
sender_address = message.subscriber.
|
212
|
+
sender_address = message.subscriber.rfc5322_email
|
213
213
|
if options[:copy_sender]
|
214
214
|
recipient_addresses << sender_address unless recipient_addresses.include?(sender_address)
|
215
215
|
else
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module MList
|
2
2
|
module Manager
|
3
|
-
|
3
|
+
|
4
4
|
class Database
|
5
5
|
include ::MList::Manager
|
6
|
-
|
6
|
+
|
7
7
|
def create_list(address, attributes = {})
|
8
8
|
attributes = {
|
9
9
|
:address => address,
|
@@ -11,38 +11,38 @@ module MList
|
|
11
11
|
}.merge(attributes)
|
12
12
|
List.create!(attributes)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def lists(email)
|
16
16
|
lists = List.find_all_by_address(email.list_addresses)
|
17
17
|
email.list_addresses.map { |a| lists.detect {|l| l.address == a} }.compact
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def no_lists_found(email)
|
21
21
|
# TODO: Move to notifier
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
class List < ActiveRecord::Base
|
25
25
|
include ::MList::List
|
26
|
-
|
26
|
+
|
27
27
|
has_many :subscribers, :dependent => :delete_all
|
28
|
-
|
28
|
+
|
29
29
|
def label
|
30
30
|
self[:label]
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def list_id
|
34
34
|
"#{self.class.name}#{id}"
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def subscribe(address)
|
38
|
-
subscribers.
|
38
|
+
subscribers.find_or_create_by_rfc5322_email(address)
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
class Subscriber < ActiveRecord::Base
|
43
43
|
belongs_to :list
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
end
|
48
|
-
end
|
48
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module MList
|
2
2
|
module Manager
|
3
|
-
|
3
|
+
|
4
4
|
# Constructs the notices that are sent to list subscribers. Applications
|
5
5
|
# may subclass this to customize the content of a notice delivery.
|
6
6
|
#
|
7
7
|
class Notifier
|
8
|
-
|
8
|
+
|
9
9
|
# Answers the delivery that will be sent to a subscriber when an
|
10
10
|
# MList::List indicates that the distribution of an email from that
|
11
11
|
# subscriber has been blocked.
|
@@ -14,18 +14,18 @@ module MList
|
|
14
14
|
delivery = MList::Util::TMailBuilder.new(TMail::Mail.new)
|
15
15
|
delivery.write_header('x-mlist-loop', 'notice')
|
16
16
|
delivery.write_header('x-mlist-notice', 'subscriber_blocked')
|
17
|
-
delivery.to = subscriber.
|
17
|
+
delivery.to = subscriber.rfc5322_email
|
18
18
|
delivery.from = "mlist-#{list.address}"
|
19
19
|
prepare_subscriber_blocked_content(list, email, subscriber, delivery)
|
20
20
|
delivery
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
protected
|
24
24
|
def prepare_subscriber_blocked_content(list, email, subscriber, delivery)
|
25
25
|
delivery.set_content_type('text/plain')
|
26
26
|
delivery.body = %{Although you are a subscriber to this list, your message cannot be posted at this time. Please contact the administrator of the list.}
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
data/lib/mlist/message.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
module MList
|
2
|
-
|
2
|
+
|
3
3
|
class Message < ActiveRecord::Base
|
4
4
|
set_table_name 'mlist_messages'
|
5
|
-
|
5
|
+
|
6
6
|
include MList::Util::EmailHelpers
|
7
|
-
|
7
|
+
|
8
8
|
belongs_to :email, :class_name => 'MList::Email'
|
9
9
|
belongs_to :parent, :class_name => 'MList::Message'
|
10
10
|
belongs_to :mail_list, :class_name => 'MList::MailList', :counter_cache => :messages_count
|
11
11
|
belongs_to :thread, :class_name => 'MList::Thread', :counter_cache => :messages_count
|
12
|
-
|
12
|
+
|
13
13
|
after_destroy :delete_unreferenced_email
|
14
|
-
|
14
|
+
|
15
15
|
# A temporary storage of recipient subscribers, obtained from
|
16
16
|
# MList::Lists. This list is not available when a message is reloaded.
|
17
17
|
#
|
18
18
|
attr_accessor :recipients
|
19
|
-
|
19
|
+
|
20
20
|
# Answers an MList::TMailBuilder for assembling the TMail::Mail object
|
21
21
|
# that will be fit for delivery. If this is not a new message, the
|
22
22
|
# delivery will be updated to reflect the message-id, x-mailer, etc. of
|
@@ -33,26 +33,26 @@ module MList
|
|
33
33
|
d
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def email_with_capture=(email)
|
38
38
|
self.subject = email.subject
|
39
39
|
self.mailer = email.mailer
|
40
40
|
self.email_without_capture = email
|
41
41
|
end
|
42
42
|
alias_method_chain :email=, :capture
|
43
|
-
|
43
|
+
|
44
44
|
# Answers the html content of the message.
|
45
45
|
#
|
46
46
|
def html
|
47
47
|
email.html
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# Answers the text content of the message.
|
51
51
|
#
|
52
52
|
def text
|
53
53
|
email.text
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
# Answers the text content of the message as HTML. The structure of this
|
57
57
|
# output is very simple. For examples of what it can handle, please check
|
58
58
|
# out the spec documents for MList::Util::EmailHelpers.
|
@@ -60,21 +60,21 @@ module MList
|
|
60
60
|
def text_html
|
61
61
|
text_to_html(text)
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# Answers text suitable for creating a reply message.
|
65
65
|
#
|
66
66
|
def text_for_reply
|
67
67
|
timestamp = email.date.to_s(:mlist_reply_timestamp)
|
68
68
|
"On #{timestamp}, #{email.from} wrote:\n#{text_to_quoted(text)}"
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
# Answers text suitable for creating a reply message, converted to the
|
72
72
|
# same simple html of _text_html_.
|
73
73
|
#
|
74
74
|
def html_for_reply
|
75
75
|
text_to_html(text_for_reply)
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def parent_with_identifier_capture=(parent)
|
79
79
|
if parent
|
80
80
|
self.parent_without_identifier_capture = parent
|
@@ -85,7 +85,7 @@ module MList
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
alias_method_chain :parent=, :identifier_capture
|
88
|
-
|
88
|
+
|
89
89
|
# Answers the recipient email addresses from the MList::List recipient
|
90
90
|
# subscribers, except those that are in the email TO or CC fields as
|
91
91
|
# placed there by the sending MUA. It is assumed that those addresses have
|
@@ -93,9 +93,9 @@ module MList
|
|
93
93
|
# we would cause them to receive two copies of the message.
|
94
94
|
#
|
95
95
|
def recipient_addresses
|
96
|
-
@recipients.collect(&:
|
96
|
+
@recipients.collect(&:rfc5322_email).collect(&:downcase) - email.recipient_addresses
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
# Answers the subject with 'Re:' prefixed. Note that it is the
|
100
100
|
# responsibility of the MList::MailList to perform any processing of the
|
101
101
|
# persisted subject (ie, cleaning up labels, etc).
|
@@ -109,7 +109,7 @@ module MList
|
|
109
109
|
def subject_for_reply
|
110
110
|
subject =~ REGARD_RE ? subject : "Re: #{subject}"
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
# Answers the subscriber from which this message comes.
|
114
114
|
#
|
115
115
|
def subscriber
|
@@ -121,19 +121,19 @@ module MList
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
# Assigns the subscriber from which this message comes.
|
126
126
|
#
|
127
127
|
def subscriber=(subscriber)
|
128
128
|
case subscriber
|
129
129
|
when ActiveRecord::Base
|
130
130
|
@subscriber = subscriber
|
131
|
-
self.subscriber_address = subscriber.
|
131
|
+
self.subscriber_address = subscriber.rfc5322_email
|
132
132
|
self.subscriber_type = subscriber.class.base_class.name
|
133
133
|
self.subscriber_id = subscriber.id
|
134
134
|
when MList::EmailSubscriber
|
135
135
|
@subscriber = subscriber
|
136
|
-
self.subscriber_address = subscriber.
|
136
|
+
self.subscriber_address = subscriber.rfc5322_email
|
137
137
|
self.subscriber_type = self.subscriber_id = nil
|
138
138
|
when String
|
139
139
|
self.subscriber = MList::EmailSubscriber.new(subscriber)
|
@@ -141,10 +141,10 @@ module MList
|
|
141
141
|
@subscriber = self.subscriber_address = self.subscriber_type = self.subscriber_id = nil
|
142
142
|
end
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
private
|
146
146
|
def delete_unreferenced_email
|
147
147
|
email.destroy unless MList::Message.count(:conditions => "email_id = #{email_id} and id != #{id}") > 0
|
148
148
|
end
|
149
149
|
end
|
150
|
-
end
|
150
|
+
end
|
data/spec/fixtures/schema.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
ActiveRecord::Schema.define(:version => 20081126181722) do
|
2
|
-
|
2
|
+
|
3
3
|
# All MList required tables are prefixed with 'mlist_' to ease integration
|
4
4
|
# into other systems' databases.
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
|
7
7
|
# The table in which email content is stored.
|
8
|
-
#
|
8
|
+
#
|
9
9
|
create_table :mlist_emails, :force => true do |t|
|
10
10
|
t.column :source, :text
|
11
11
|
t.column :created_at, :datetime
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# The table in which MList will store MList::Messages.
|
15
15
|
#
|
16
16
|
# The identifier is the 'message-id' header value of the finally delivered
|
@@ -18,9 +18,9 @@ ActiveRecord::Schema.define(:version => 20081126181722) do
|
|
18
18
|
#
|
19
19
|
# An MList::Message will store a reference to your application's subscriber
|
20
20
|
# instance if it is an ActiveRecord subclass. That subclass must respond to
|
21
|
-
# :
|
22
|
-
# an email address. Either way, that email address will be stored with
|
23
|
-
# MList::Message, providing a way for you to associate messages by
|
21
|
+
# :rfc5322_email. If your subscriber is just a string, it is assumed
|
22
|
+
# to be an email address. Either way, that email address will be stored with
|
23
|
+
# the MList::Message, providing a way for you to associate messages by
|
24
24
|
# subscriber_address. This is less ideal, as you may allow subscribers to
|
25
25
|
# change their email addresses over time.
|
26
26
|
#
|
@@ -46,7 +46,7 @@ ActiveRecord::Schema.define(:version => 20081126181722) do
|
|
46
46
|
add_index :mlist_messages, :subject
|
47
47
|
add_index :mlist_messages, :subscriber_address
|
48
48
|
add_index :mlist_messages, [:subscriber_type, :subscriber_id]
|
49
|
-
|
49
|
+
|
50
50
|
# Every MList::Message is associated with an MList::Thread.
|
51
51
|
#
|
52
52
|
create_table :mlist_threads, :force => true do |t|
|
@@ -55,7 +55,7 @@ ActiveRecord::Schema.define(:version => 20081126181722) do
|
|
55
55
|
t.timestamps
|
56
56
|
end
|
57
57
|
add_index :mlist_threads, :mail_list_id
|
58
|
-
|
58
|
+
|
59
59
|
# The table in which MList will store MList::MailLists.
|
60
60
|
#
|
61
61
|
# The manager_list_identifier column stores the MList::List#list_id value.
|
@@ -76,8 +76,8 @@ ActiveRecord::Schema.define(:version => 20081126181722) do
|
|
76
76
|
add_index :mlist_mail_lists, :manager_list_identifier
|
77
77
|
add_index :mlist_mail_lists, [:manager_list_identifier, :manager_list_type, :manager_list_id],
|
78
78
|
:name => :index_mlist_mail_lists_on_manager_association
|
79
|
-
|
80
|
-
|
79
|
+
|
80
|
+
|
81
81
|
# Database list manager tables, used for testing purposes.
|
82
82
|
#
|
83
83
|
create_table :lists, :force => true do |t|
|
@@ -85,10 +85,10 @@ ActiveRecord::Schema.define(:version => 20081126181722) do
|
|
85
85
|
t.column :label, :string
|
86
86
|
t.column :created_at, :datetime
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
create_table :subscribers, :force => true do |t|
|
90
90
|
t.column :list_id, :integer
|
91
|
-
t.column :
|
91
|
+
t.column :rfc5322_email, :string
|
92
92
|
t.column :created_at, :datetime
|
93
93
|
end
|
94
94
|
end
|
@@ -12,7 +12,7 @@ describe MList do
|
|
12
12
|
end.should_not store_message
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def store_message
|
17
17
|
simple_matcher('store message') do |block|
|
18
18
|
thread_count, message_count = MList::Thread.count, MList::Message.count
|
@@ -20,7 +20,7 @@ describe MList do
|
|
20
20
|
MList::Thread.count == thread_count + 1 && MList::Message.count == message_count + 1
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def start_new_thread(tmail)
|
25
25
|
simple_matcher('start new thread') do |email_server|
|
26
26
|
delivery_count = email_server.deliveries.size
|
@@ -32,34 +32,34 @@ describe MList do
|
|
32
32
|
MList::Message.count == (message_count + 1)
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
dataset do
|
37
37
|
@list_manager = MList::Manager::Database.new
|
38
38
|
@list_one = @list_manager.create_list('list_one@example.com')
|
39
39
|
@list_one.subscribe('adam@nomail.net')
|
40
40
|
@list_one.subscribe('tom@example.com')
|
41
41
|
@list_one.subscribe('dick@example.com')
|
42
|
-
|
42
|
+
|
43
43
|
@list_two = @list_manager.create_list('list_two@example.com')
|
44
44
|
@list_two.subscribe('adam@nomail.net')
|
45
45
|
@list_two.subscribe('jane@example.com')
|
46
|
-
|
46
|
+
|
47
47
|
@list_three = @list_manager.create_list('empty@example.com')
|
48
48
|
@list_three.subscribe('adam@nomail.net')
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
before do
|
52
52
|
@email_server = MList::EmailServer::Fake.new
|
53
53
|
@server = MList::Server.new(
|
54
54
|
:list_manager => @list_manager,
|
55
55
|
:email_server => @email_server
|
56
56
|
)
|
57
|
-
|
57
|
+
|
58
58
|
# TODO Move this stuff to Dataset
|
59
59
|
ActiveRecord::Base.connection.increment_open_transactions
|
60
60
|
ActiveRecord::Base.connection.begin_db_transaction
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
after do
|
64
64
|
if ActiveRecord::Base.connection.open_transactions != 0
|
65
65
|
ActiveRecord::Base.connection.rollback_db_transaction
|
@@ -67,39 +67,39 @@ describe MList do
|
|
67
67
|
end
|
68
68
|
ActiveRecord::Base.clear_active_connections!
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
it 'should have threads and mail_lists updated_at set to last message receive time' do
|
72
72
|
now = Time.now
|
73
73
|
stub(Time).now {now}
|
74
74
|
@email_server.receive(tmail_fixture('single_list'))
|
75
75
|
MList::MailList.last.updated_at.to_s.should == now.to_s
|
76
76
|
MList::Thread.last.updated_at.to_s.should == now.to_s
|
77
|
-
|
77
|
+
|
78
78
|
later = 5.days.from_now
|
79
79
|
stub(Time).now {later}
|
80
80
|
@email_server.receive(tmail_fixture('single_list_reply'))
|
81
81
|
MList::MailList.last.updated_at.to_s.should == later.to_s
|
82
82
|
MList::Thread.last.updated_at.to_s.should == later.to_s
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
it 'should associate manager lists to mlist mail lists when they are ActiveRecord instances' do
|
86
86
|
@email_server.receive(tmail_fixture('single_list'))
|
87
87
|
mail_list = MList::MailList.last
|
88
88
|
mail_list.manager_list.should == @list_one
|
89
89
|
mail_list.manager_list_identifier.should == @list_one.list_id
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
it 'should not forward mail that has been on this server before' do
|
93
93
|
# The sample email has multiple headers to prove that's not a problem
|
94
94
|
@email_server.should_not forward_email(tmail_fixture('x-beenthere'))
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
it 'should store message/thread even when there are no recipient subscribers' do
|
98
98
|
tmail = tmail_fixture('single_list')
|
99
99
|
tmail.to = @list_three.address
|
100
100
|
@email_server.should start_new_thread(tmail)
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
it 'should not forward mail from non-subscriber and notify manager list' do
|
104
104
|
tmail = tmail_fixture('single_list')
|
105
105
|
tmail.from = 'unknown@example.com'
|
@@ -107,7 +107,7 @@ describe MList do
|
|
107
107
|
mock(@list_one).non_subscriber_post(is_a(MList::Email))
|
108
108
|
@email_server.should_not forward_email(tmail)
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
111
|
it 'should not forward mail from non-subscriber when inactive and notify as non-subscriber' do
|
112
112
|
tmail = tmail_fixture('single_list')
|
113
113
|
tmail.from = 'unknown@example.com'
|
@@ -116,9 +116,9 @@ describe MList do
|
|
116
116
|
mock(@list_one).non_subscriber_post(is_a(MList::Email))
|
117
117
|
@email_server.should_not forward_email(tmail)
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
it 'should not forward mail from blocked subscriber, notify the subscriber using list manager notifier' do
|
121
|
-
subscriber = MList::Manager::Database::Subscriber.
|
121
|
+
subscriber = MList::Manager::Database::Subscriber.find_by_rfc5322_email('adam@nomail.net')
|
122
122
|
tmail = tmail_fixture('single_list')
|
123
123
|
mock(@list_one).active? {true}
|
124
124
|
mock(@list_one).blocked?(subscriber) { true }
|
@@ -132,7 +132,7 @@ describe MList do
|
|
132
132
|
response_tmail.header_string('x-mlist-notice').should == 'subscriber_blocked'
|
133
133
|
end.should_not store_message
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
it 'should not forward mail to inactive list and notify manager list' do
|
137
137
|
tmail = tmail_fixture('single_list')
|
138
138
|
mock(@list_one).active? { false }
|
@@ -140,26 +140,26 @@ describe MList do
|
|
140
140
|
mock(@list_one).inactive_post(is_a(MList::Email))
|
141
141
|
@email_server.should_not forward_email(tmail)
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
it 'should report unrecognized email to list manager' do
|
145
145
|
tmail = tmail_fixture('single_list')
|
146
146
|
stub(@list_manager).lists(is_a(MList::Email)) { [] }
|
147
147
|
mock(@list_manager).no_lists_found(is_a(MList::Email))
|
148
148
|
@email_server.should_not forward_email(tmail)
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
it 'should report bounces to the list manager' do
|
152
152
|
stub(@list_manager).lists(is_a(MList::Email)) { [@list_one] }
|
153
153
|
mock(@list_one).bounce(is_a(MList::Email))
|
154
154
|
@email_server.should_not forward_email(tmail_fixture('bounces/1'))
|
155
155
|
end
|
156
|
-
|
156
|
+
|
157
157
|
describe 'single list' do
|
158
158
|
before do
|
159
159
|
@tmail_post = tmail_fixture('single_list')
|
160
160
|
@email_server.receive(@tmail_post)
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
it 'should forward emails that are sent to a mailing list' do
|
164
164
|
@email_server.deliveries.size.should == 1
|
165
165
|
email = @email_server.deliveries.first
|
@@ -167,12 +167,12 @@ describe MList do
|
|
167
167
|
# bcc fields are not in the headers of delivered emails
|
168
168
|
email.should have_address(:'reply-to', 'list_one@example.com')
|
169
169
|
end
|
170
|
-
|
170
|
+
|
171
171
|
it 'should start a new thread for a new email' do
|
172
172
|
thread = MList::Thread.last
|
173
173
|
thread.messages.first.email.tmail.should equal_tmail(@tmail_post)
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
it 'should add to an existing thread when reply email' do
|
177
177
|
message = MList::Message.last
|
178
178
|
reply_tmail = tmail_fixture('single_list_reply', 'in-reply-to' => "<#{message.identifier}>")
|
@@ -180,7 +180,7 @@ describe MList do
|
|
180
180
|
thread = MList::Thread.last
|
181
181
|
thread.messages.size.should be(2)
|
182
182
|
end
|
183
|
-
|
183
|
+
|
184
184
|
it 'should associate parent message when reply email' do
|
185
185
|
message = MList::Message.last
|
186
186
|
@email_server.receive(tmail_fixture('single_list_reply', 'in-reply-to' => "<#{message.identifier}>"))
|
@@ -188,46 +188,46 @@ describe MList do
|
|
188
188
|
reply.parent_identifier.should == message.identifier
|
189
189
|
reply.parent.should == message
|
190
190
|
end
|
191
|
-
|
191
|
+
|
192
192
|
it 'should not associate a parent when not a reply' do
|
193
193
|
tmail = tmail_fixture('single_list')
|
194
194
|
tmail['message-id'] = 'asdfasdfj'
|
195
195
|
tmail['subject'] = 'other thing'
|
196
196
|
@email_server.should start_new_thread(tmail)
|
197
197
|
end
|
198
|
-
|
198
|
+
|
199
199
|
it 'should store subscriber address with messages' do
|
200
200
|
MList::Message.last.subscriber_address.should == 'adam@nomail.net'
|
201
201
|
end
|
202
|
-
|
202
|
+
|
203
203
|
it 'should associate subscriber to messages when they are ActiveRecord instances' do
|
204
|
-
MList::Message.last.subscriber.should == MList::Manager::Database::Subscriber.
|
204
|
+
MList::Message.last.subscriber.should == MList::Manager::Database::Subscriber.find_by_rfc5322_email('adam@nomail.net')
|
205
205
|
end
|
206
206
|
end
|
207
|
-
|
207
|
+
|
208
208
|
describe 'multiple lists' do
|
209
209
|
before do
|
210
210
|
@tmail_post = tmail_fixture('multiple_lists')
|
211
211
|
@email_server.receive(@tmail_post)
|
212
212
|
end
|
213
|
-
|
213
|
+
|
214
214
|
it 'should forward emails that are sent to a mailing list' do
|
215
215
|
@email_server.deliveries.size.should == 2
|
216
|
-
|
216
|
+
|
217
217
|
email = @email_server.deliveries.first
|
218
218
|
email.should have_address(:to, 'list_one@example.com')
|
219
219
|
# bcc fields are not in the headers of delivered emails
|
220
220
|
email.should have_address(:'reply-to', 'list_one@example.com')
|
221
|
-
|
221
|
+
|
222
222
|
email = @email_server.deliveries.last
|
223
223
|
email.should have_address(:to, 'list_two@example.com')
|
224
224
|
# bcc fields are not in the headers of delivered emails
|
225
225
|
email.should have_address(:'reply-to', 'list_two@example.com')
|
226
226
|
end
|
227
|
-
|
227
|
+
|
228
228
|
it 'should start a new thread for each list, both referencing the same email' do
|
229
229
|
threads = MList::Thread.find(:all)
|
230
230
|
threads[0].messages.first.email.should == threads[1].messages.first.email
|
231
231
|
end
|
232
232
|
end
|
233
|
-
end
|
233
|
+
end
|
@@ -122,7 +122,7 @@ describe MList::MailList do
|
|
122
122
|
:copy_sender => true)
|
123
123
|
|
124
124
|
tmail = @outgoing_server.deliveries.last
|
125
|
-
tmail.bcc.should include(@subscriber_one.
|
125
|
+
tmail.bcc.should include(@subscriber_one.rfc5322_email)
|
126
126
|
end
|
127
127
|
|
128
128
|
it 'should not copy the subscriber if undesired and list includes the subscriber' do
|
@@ -136,7 +136,7 @@ describe MList::MailList do
|
|
136
136
|
:copy_sender => false)
|
137
137
|
|
138
138
|
tmail = @outgoing_server.deliveries.last
|
139
|
-
tmail.bcc.should_not include(@subscriber_one.
|
139
|
+
tmail.bcc.should_not include(@subscriber_one.rfc5322_email)
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 19
|
9
|
+
version: 0.1.19
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Adam Williams
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-08-12 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|