mail 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mail might be problematic. Click here for more details.
- data/.gitignore +4 -0
- data/Manifest.txt +106 -0
- data/README.rdoc +441 -0
- data/Rakefile +38 -0
- data/lib/mail.rb +86 -0
- data/lib/mail/attachment.rb +90 -0
- data/lib/mail/body.rb +149 -0
- data/lib/mail/configuration.rb +90 -0
- data/lib/mail/core_extensions.rb +6 -0
- data/lib/mail/core_extensions/blank.rb +41 -0
- data/lib/mail/core_extensions/nil.rb +15 -0
- data/lib/mail/core_extensions/string.rb +31 -0
- data/lib/mail/elements/address.rb +293 -0
- data/lib/mail/elements/address_list.rb +62 -0
- data/lib/mail/elements/content_disposition_element.rb +34 -0
- data/lib/mail/elements/content_transfer_encoding_element.rb +21 -0
- data/lib/mail/elements/content_type_element.rb +39 -0
- data/lib/mail/elements/date_time_element.rb +26 -0
- data/lib/mail/elements/envelope_from_element.rb +34 -0
- data/lib/mail/elements/message_ids_element.rb +29 -0
- data/lib/mail/elements/mime_version_element.rb +26 -0
- data/lib/mail/elements/phrase_list.rb +21 -0
- data/lib/mail/elements/received_element.rb +30 -0
- data/lib/mail/encodings/base64.rb +17 -0
- data/lib/mail/encodings/encodings.rb +24 -0
- data/lib/mail/encodings/quoted_printable.rb +26 -0
- data/lib/mail/envelope.rb +35 -0
- data/lib/mail/field.rb +202 -0
- data/lib/mail/field_list.rb +33 -0
- data/lib/mail/fields/bcc_field.rb +40 -0
- data/lib/mail/fields/cc_field.rb +40 -0
- data/lib/mail/fields/comments_field.rb +41 -0
- data/lib/mail/fields/common/common_address.rb +62 -0
- data/lib/mail/fields/common/common_date.rb +35 -0
- data/lib/mail/fields/common/common_field.rb +128 -0
- data/lib/mail/fields/common/common_message_id.rb +35 -0
- data/lib/mail/fields/content_description_field.rb +15 -0
- data/lib/mail/fields/content_disposition_field.rb +34 -0
- data/lib/mail/fields/content_id_field.rb +50 -0
- data/lib/mail/fields/content_transfer_encoding_field.rb +28 -0
- data/lib/mail/fields/content_type_field.rb +50 -0
- data/lib/mail/fields/date_field.rb +44 -0
- data/lib/mail/fields/from_field.rb +40 -0
- data/lib/mail/fields/in_reply_to_field.rb +42 -0
- data/lib/mail/fields/keywords_field.rb +22 -0
- data/lib/mail/fields/message_id_field.rb +70 -0
- data/lib/mail/fields/mime_version_field.rb +42 -0
- data/lib/mail/fields/optional_field.rb +11 -0
- data/lib/mail/fields/received_field.rb +49 -0
- data/lib/mail/fields/references_field.rb +42 -0
- data/lib/mail/fields/reply_to_field.rb +40 -0
- data/lib/mail/fields/resent_bcc_field.rb +40 -0
- data/lib/mail/fields/resent_cc_field.rb +40 -0
- data/lib/mail/fields/resent_date_field.rb +16 -0
- data/lib/mail/fields/resent_from_field.rb +40 -0
- data/lib/mail/fields/resent_message_id_field.rb +20 -0
- data/lib/mail/fields/resent_sender_field.rb +48 -0
- data/lib/mail/fields/resent_to_field.rb +40 -0
- data/lib/mail/fields/return_path_field.rb +34 -0
- data/lib/mail/fields/sender_field.rb +48 -0
- data/lib/mail/fields/structured_field.rb +32 -0
- data/lib/mail/fields/subject_field.rb +14 -0
- data/lib/mail/fields/to_field.rb +40 -0
- data/lib/mail/fields/unstructured_field.rb +27 -0
- data/lib/mail/header.rb +213 -0
- data/lib/mail/mail.rb +120 -0
- data/lib/mail/message.rb +648 -0
- data/lib/mail/network/deliverable.rb +42 -0
- data/lib/mail/network/retrievable.rb +63 -0
- data/lib/mail/parsers/address_lists.rb +61 -0
- data/lib/mail/parsers/address_lists.treetop +19 -0
- data/lib/mail/parsers/content_disposition.rb +358 -0
- data/lib/mail/parsers/content_disposition.treetop +45 -0
- data/lib/mail/parsers/content_transfer_encoding.rb +179 -0
- data/lib/mail/parsers/content_transfer_encoding.treetop +25 -0
- data/lib/mail/parsers/content_type.rb +507 -0
- data/lib/mail/parsers/content_type.treetop +58 -0
- data/lib/mail/parsers/date_time.rb +111 -0
- data/lib/mail/parsers/date_time.treetop +11 -0
- data/lib/mail/parsers/envelope_from.rb +188 -0
- data/lib/mail/parsers/envelope_from.treetop +32 -0
- data/lib/mail/parsers/message_ids.rb +42 -0
- data/lib/mail/parsers/message_ids.treetop +15 -0
- data/lib/mail/parsers/mime_version.rb +141 -0
- data/lib/mail/parsers/mime_version.treetop +19 -0
- data/lib/mail/parsers/phrase_lists.rb +42 -0
- data/lib/mail/parsers/phrase_lists.treetop +15 -0
- data/lib/mail/parsers/received.rb +68 -0
- data/lib/mail/parsers/received.treetop +11 -0
- data/lib/mail/parsers/rfc2045.rb +406 -0
- data/lib/mail/parsers/rfc2045.treetop +35 -0
- data/lib/mail/parsers/rfc2822.rb +5005 -0
- data/lib/mail/parsers/rfc2822.treetop +402 -0
- data/lib/mail/parsers/rfc2822_obsolete.rb +3607 -0
- data/lib/mail/parsers/rfc2822_obsolete.treetop +241 -0
- data/lib/mail/part.rb +120 -0
- data/lib/mail/patterns.rb +42 -0
- data/lib/mail/utilities.rb +142 -0
- data/lib/mail/version.rb +10 -0
- data/lib/mail/version_specific/multibyte.rb +62 -0
- data/lib/mail/version_specific/multibyte/chars.rb +701 -0
- data/lib/mail/version_specific/multibyte/exceptions.rb +8 -0
- data/lib/mail/version_specific/multibyte/unicode_database.rb +71 -0
- data/lib/mail/version_specific/ruby_1_8.rb +61 -0
- data/lib/mail/version_specific/ruby_1_8_string.rb +88 -0
- data/lib/mail/version_specific/ruby_1_9.rb +49 -0
- metadata +192 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#:nodoc:
|
3
|
+
# From the nice guys at rubyonrails.org -> ActiveSupport
|
4
|
+
class ::Object
|
5
|
+
# An object is blank if it's nil, empty, or a whitespace string.
|
6
|
+
# For example, "", " ", nil, [], and {} are blank.
|
7
|
+
#
|
8
|
+
# This simplifies
|
9
|
+
# if !address.nil? && !address.empty?
|
10
|
+
# to
|
11
|
+
# if !address.blank?
|
12
|
+
def blank?
|
13
|
+
respond_to?(:empty?) ? empty? : !self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class FalseClass #:nodoc:
|
18
|
+
def blank?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class TrueClass #:nodoc:
|
24
|
+
def blank?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Array #:nodoc:
|
30
|
+
alias_method :blank?, :empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
class Hash #:nodoc:
|
34
|
+
alias_method :blank?, :empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
class Numeric #:nodoc:
|
38
|
+
def blank?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class String #:nodoc:
|
3
|
+
|
4
|
+
if defined?(Mail::Multibyte)
|
5
|
+
include Mail::Multibyte
|
6
|
+
end
|
7
|
+
|
8
|
+
def blank?
|
9
|
+
self !~ /\S/
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_crlf
|
13
|
+
self.gsub(/\n|\r\n|\r/) { "\r\n" }
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_lf
|
17
|
+
self.gsub(/\n|\r\n|\r/) { "\n" }
|
18
|
+
end
|
19
|
+
|
20
|
+
if RUBY_VERSION <= "1.9"
|
21
|
+
|
22
|
+
# Provides all strings with the Ruby 1.9 method of .ascii_only? and
|
23
|
+
# returns true or false
|
24
|
+
US_ASCII_REGEXP = %Q{\x00-\x7f}
|
25
|
+
def ascii_only?
|
26
|
+
!(self =~ /[^#{US_ASCII_REGEXP}]/)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mail
|
3
|
+
class Address
|
4
|
+
|
5
|
+
include Mail::Utilities
|
6
|
+
|
7
|
+
# Mail::Address handles all email addresses in Mail. It takes an email address string
|
8
|
+
# and parses it, breaking it down into it's component parts and allowing you to get the
|
9
|
+
# address, comments, display name, name, local part, domain part and fully formatted
|
10
|
+
# address.
|
11
|
+
#
|
12
|
+
# Mail::Address requires a correctly formatted email address per RFC2822 or RFC822. It
|
13
|
+
# handles all obsolete versions including obsolete domain routing on the local part.
|
14
|
+
#
|
15
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
16
|
+
# a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
|
17
|
+
# a.address #=> 'mikel@test.lindsaar.net'
|
18
|
+
# a.display_name #=> 'Mikel Lindsaar'
|
19
|
+
# a.local #=> 'mikel'
|
20
|
+
# a.domain #=> 'test.lindsaar.net'
|
21
|
+
# a.comments #=> ['My email address']
|
22
|
+
# a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
|
23
|
+
def initialize(value = nil)
|
24
|
+
@raw_text = value
|
25
|
+
case
|
26
|
+
when value.nil?
|
27
|
+
@parsed = false
|
28
|
+
return
|
29
|
+
else
|
30
|
+
parse(value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the raw imput of the passed in string, this is before it is passed
|
35
|
+
# by the parser.
|
36
|
+
def raw
|
37
|
+
@raw_text
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a correctly formatted address for the email going out. If given
|
41
|
+
# an incorrectly formatted address as input, Mail::Address will do it's best
|
42
|
+
# to format it correctly. This includes quoting display names as needed and
|
43
|
+
# putting the address in angle brackets etc.
|
44
|
+
#
|
45
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
46
|
+
# a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
|
47
|
+
def format
|
48
|
+
parse unless @parsed
|
49
|
+
case
|
50
|
+
when tree.nil?
|
51
|
+
''
|
52
|
+
when display_name
|
53
|
+
[quote_phrase(display_name), "<#{address}>", format_comments].compact.join(" ")
|
54
|
+
else
|
55
|
+
[address, format_comments].compact.join(" ")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the address that is in the address itself. That is, the
|
60
|
+
# local@domain string, without any angle brackets or the like.
|
61
|
+
#
|
62
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
63
|
+
# a.address #=> 'mikel@test.lindsaar.net'
|
64
|
+
def address
|
65
|
+
parse unless @parsed
|
66
|
+
domain ? "#{local}@#{domain}" : local
|
67
|
+
end
|
68
|
+
|
69
|
+
# Provides a way to assign an address to an already made Mail::Address object.
|
70
|
+
#
|
71
|
+
# a = Address.new
|
72
|
+
# a.address = 'Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>'
|
73
|
+
# a.address #=> 'mikel@test.lindsaar.net'
|
74
|
+
def address=(value)
|
75
|
+
parse(value)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the display name of the email address passed in.
|
79
|
+
#
|
80
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
81
|
+
# a.display_name #=> 'Mikel Lindsaar'
|
82
|
+
def display_name
|
83
|
+
parse unless @parsed
|
84
|
+
@display_name ||= get_display_name
|
85
|
+
end
|
86
|
+
|
87
|
+
# Provides a way to assign a display name to an already made Mail::Address object.
|
88
|
+
#
|
89
|
+
# a = Address.new
|
90
|
+
# a.address = 'mikel@test.lindsaar.net'
|
91
|
+
# a.display_name = 'Mikel Lindsaar'
|
92
|
+
# a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>'
|
93
|
+
def display_name=( str )
|
94
|
+
@display_name = str
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the local part (the left hand side of the @ sign in the email address) of
|
98
|
+
# the address
|
99
|
+
#
|
100
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
101
|
+
# a.local #=> 'mikel'
|
102
|
+
def local
|
103
|
+
parse unless @parsed
|
104
|
+
"#{obs_domain_list}#{get_local.strip}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns the domain part (the right hand side of the @ sign in the email address) of
|
108
|
+
# the address
|
109
|
+
#
|
110
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
111
|
+
# a.domain #=> 'test.lindsaar.net'
|
112
|
+
def domain
|
113
|
+
parse unless @parsed
|
114
|
+
strip_all_comments(get_domain) if get_domain
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns an array of comments that are in the email, or an empty array if there
|
118
|
+
# are no comments
|
119
|
+
#
|
120
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
121
|
+
# a.comments #=> ['My email address']
|
122
|
+
def comments
|
123
|
+
parse unless @parsed
|
124
|
+
if get_comments.empty?
|
125
|
+
nil
|
126
|
+
else
|
127
|
+
get_comments.map { |c| c.squeeze(" ") }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Sometimes an address will not have a display name, but might have the name
|
132
|
+
# as a comment field after the address. This returns that name if it exists.
|
133
|
+
#
|
134
|
+
# a = Address.new('mikel@test.lindsaar.net (Mikel Lindsaar)')
|
135
|
+
# a.name #=> 'Mikel Lindsaar'
|
136
|
+
def name
|
137
|
+
parse unless @parsed
|
138
|
+
get_name
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns the format of the address, or returns nothing
|
142
|
+
#
|
143
|
+
# a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
|
144
|
+
# a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
|
145
|
+
def to_s
|
146
|
+
parse unless @parsed
|
147
|
+
format
|
148
|
+
end
|
149
|
+
|
150
|
+
# Shows the Address object basic details, including the Address
|
151
|
+
# a = Address.new('Mikel (My email) <mikel@test.lindsaar.net>')
|
152
|
+
# a.inspect #=> "#<Mail::Address:14184910 Address: |Mikel <mikel@test.lindsaar.net> (My email)| >"
|
153
|
+
def inspect
|
154
|
+
parse unless @parsed
|
155
|
+
"#<#{self.class}:#{self.object_id} Address: |#{to_s}| >"
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def parse(value = nil)
|
161
|
+
@parsed = true
|
162
|
+
case
|
163
|
+
when value.nil?
|
164
|
+
nil
|
165
|
+
when value.class == String
|
166
|
+
self.tree = Mail::AddressList.new(value).address_nodes.first
|
167
|
+
else
|
168
|
+
self.tree = value
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
def get_domain
|
174
|
+
if tree.respond_to?(:angle_addr)
|
175
|
+
@domain_text ||= tree.angle_addr.addr_spec.domain.text_value.strip
|
176
|
+
elsif tree.respond_to?(:domain)
|
177
|
+
@domain_text ||= tree.domain.text_value.strip
|
178
|
+
elsif tree.respond_to?(:addr_spec)
|
179
|
+
tree.addr_spec.domain.text_value.strip
|
180
|
+
else
|
181
|
+
nil
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def strip_all_comments(string)
|
186
|
+
unless comments.blank?
|
187
|
+
comments.each do |comment|
|
188
|
+
string = string.gsub("(#{comment})", '')
|
189
|
+
end
|
190
|
+
end
|
191
|
+
string.strip
|
192
|
+
end
|
193
|
+
|
194
|
+
def strip_domain_comments(value)
|
195
|
+
unless comments.blank?
|
196
|
+
comments.each do |comment|
|
197
|
+
if get_domain && get_domain.include?("(#{comment})")
|
198
|
+
value = value.gsub("(#{comment})", '')
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
value.to_s.strip
|
203
|
+
end
|
204
|
+
|
205
|
+
def get_comments
|
206
|
+
if tree.respond_to?(:comments)
|
207
|
+
@comments ||= tree.comments.map { |c| unparen(c.text_value) }
|
208
|
+
else
|
209
|
+
@comments = []
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def get_display_name
|
214
|
+
if tree.respond_to?(:display_name)
|
215
|
+
name = unquote(tree.display_name.text_value.strip)
|
216
|
+
str = strip_all_comments(name)
|
217
|
+
elsif comments
|
218
|
+
if domain
|
219
|
+
str = strip_domain_comments(format_comments)
|
220
|
+
else
|
221
|
+
str = nil
|
222
|
+
end
|
223
|
+
else
|
224
|
+
nil
|
225
|
+
end
|
226
|
+
|
227
|
+
if str.blank?
|
228
|
+
nil
|
229
|
+
else
|
230
|
+
str
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def get_name
|
235
|
+
if display_name
|
236
|
+
str = display_name
|
237
|
+
else
|
238
|
+
if comments
|
239
|
+
comment_text = comments.join(' ').squeeze(" ")
|
240
|
+
str = "(#{comment_text})"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
if str.blank?
|
245
|
+
nil
|
246
|
+
else
|
247
|
+
unparen(str)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# Provides access to the Treetop parse tree for this address
|
252
|
+
def tree
|
253
|
+
@tree
|
254
|
+
end
|
255
|
+
|
256
|
+
def tree=(value)
|
257
|
+
@tree = value
|
258
|
+
end
|
259
|
+
|
260
|
+
def format_comments
|
261
|
+
if comments
|
262
|
+
comment_text = comments.map {|c| escape_paren(c) }.join(' ').squeeze(" ")
|
263
|
+
@format_comments ||= "(#{comment_text})"
|
264
|
+
else
|
265
|
+
nil
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def obs_domain_list
|
270
|
+
if tree.respond_to?(:angle_addr)
|
271
|
+
obs = tree.angle_addr.elements.select { |e| e.respond_to?(:obs_domain_list) }
|
272
|
+
!obs.empty? ? obs.first.text_value : nil
|
273
|
+
else
|
274
|
+
nil
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def get_local
|
279
|
+
case
|
280
|
+
when tree.respond_to?(:local_dot_atom_text)
|
281
|
+
tree.local_dot_atom_text.text_value
|
282
|
+
when tree.respond_to?(:angle_addr)
|
283
|
+
tree.angle_addr.addr_spec.local_part.text_value
|
284
|
+
when tree.respond_to?(:addr_spec)
|
285
|
+
tree.addr_spec.local_part.text_value
|
286
|
+
else
|
287
|
+
tree.local_part.text_value
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
end
|
293
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mail
|
3
|
+
class AddressList # :nodoc:
|
4
|
+
|
5
|
+
# Mail::AddressList is the class that parses To, From and other address fields from
|
6
|
+
# emails passed into Mail.
|
7
|
+
#
|
8
|
+
# AddressList provides a way to query the groups and mailbox lists of the passed in
|
9
|
+
# string.
|
10
|
+
#
|
11
|
+
# It can supply all addresses in an array, or return each address as an address object.
|
12
|
+
#
|
13
|
+
# Mail::AddressList requires a correctly formatted group or mailbox list per RFC2822 or
|
14
|
+
# RFC822. It also handles all obsolete versions in those RFCs.
|
15
|
+
#
|
16
|
+
# list = 'ada@test.lindsaar.net, My Group: mikel@test.lindsaar.net, Bob <bob@test.lindsaar.net>;'
|
17
|
+
# a = AddressList.new(list)
|
18
|
+
# a.addresses #=> [#<Mail::Address:14943130 Address: |ada@test.lindsaar.net...
|
19
|
+
# a.group_names #=> ["My Group"]
|
20
|
+
def initialize(string)
|
21
|
+
parser = Mail::AddressListsParser.new
|
22
|
+
if tree = parser.parse(string)
|
23
|
+
@address_nodes = tree.addresses
|
24
|
+
else
|
25
|
+
raise Mail::Field::ParseError, "AddressListsParser can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a list of address objects from the parsed line
|
30
|
+
def addresses
|
31
|
+
@addresses ||= get_addresses.map do |address_tree|
|
32
|
+
Mail::Address.new(address_tree)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a list of all recipient syntax trees that are not part of a group
|
37
|
+
def individual_recipients # :nodoc:
|
38
|
+
@individual_recipients ||= @address_nodes - group_recipients
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns a list of all recipient syntax trees that are part of a group
|
42
|
+
def group_recipients # :nodoc:
|
43
|
+
@group_recipients ||= @address_nodes.select { |an| an.respond_to?(:group_name) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the names as an array of strings of all groups
|
47
|
+
def group_names # :nodoc:
|
48
|
+
group_recipients.map { |g| g.group_name.text_value }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a list of address syntax trees
|
52
|
+
def address_nodes # :nodoc:
|
53
|
+
@address_nodes
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def get_addresses
|
59
|
+
(individual_recipients + group_recipients.map { |g| g.group_list.addresses }).flatten
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|