mail 2.5.2 → 2.6.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 +7 -0
- data/CHANGELOG.rdoc +78 -0
- data/CONTRIBUTING.md +17 -4
- data/Dependencies.txt +0 -1
- data/Gemfile +10 -21
- data/MIT-LICENSE +20 -0
- data/README.md +50 -29
- data/Rakefile +11 -22
- data/VERSION +4 -0
- data/lib/mail/attachments_list.rb +2 -2
- data/lib/mail/body.rb +5 -5
- data/lib/mail/check_delivery_params.rb +12 -22
- data/lib/mail/core_extensions/object.rb +8 -8
- data/lib/mail/core_extensions/smtp.rb +12 -13
- data/lib/mail/core_extensions/string.rb +16 -6
- data/lib/mail/elements/address.rb +43 -79
- data/lib/mail/elements/address_list.rb +19 -42
- data/lib/mail/elements/content_disposition_element.rb +3 -7
- data/lib/mail/elements/content_location_element.rb +2 -6
- data/lib/mail/elements/content_transfer_encoding_element.rb +3 -10
- data/lib/mail/elements/content_type_element.rb +4 -8
- data/lib/mail/elements/date_time_element.rb +3 -7
- data/lib/mail/elements/envelope_from_element.rb +18 -13
- data/lib/mail/elements/message_ids_element.rb +1 -6
- data/lib/mail/elements/mime_version_element.rb +3 -7
- data/lib/mail/elements/phrase_list.rb +2 -7
- data/lib/mail/elements/received_element.rb +3 -7
- data/lib/mail/encodings/quoted_printable.rb +4 -3
- data/lib/mail/encodings.rb +60 -28
- data/lib/mail/envelope.rb +0 -5
- data/lib/mail/field.rb +63 -28
- data/lib/mail/field_list.rb +18 -18
- data/lib/mail/fields/bcc_field.rb +2 -2
- data/lib/mail/fields/cc_field.rb +2 -2
- data/lib/mail/fields/comments_field.rb +1 -1
- data/lib/mail/fields/common/common_address.rb +26 -21
- data/lib/mail/fields/common/common_date.rb +0 -7
- data/lib/mail/fields/common/common_field.rb +5 -5
- data/lib/mail/fields/content_id_field.rb +1 -2
- data/lib/mail/fields/content_transfer_encoding_field.rb +2 -8
- data/lib/mail/fields/content_type_field.rb +1 -1
- data/lib/mail/fields/date_field.rb +14 -14
- data/lib/mail/fields/from_field.rb +2 -2
- data/lib/mail/fields/in_reply_to_field.rb +2 -1
- data/lib/mail/fields/message_id_field.rb +2 -3
- data/lib/mail/fields/references_field.rb +2 -1
- data/lib/mail/fields/reply_to_field.rb +2 -2
- data/lib/mail/fields/resent_bcc_field.rb +2 -2
- data/lib/mail/fields/resent_cc_field.rb +2 -2
- data/lib/mail/fields/resent_from_field.rb +2 -2
- data/lib/mail/fields/resent_sender_field.rb +3 -3
- data/lib/mail/fields/resent_to_field.rb +2 -2
- data/lib/mail/fields/sender_field.rb +8 -8
- data/lib/mail/fields/to_field.rb +2 -2
- data/lib/mail/fields/unstructured_field.rb +8 -2
- data/lib/mail/header.rb +13 -23
- data/lib/mail/mail.rb +12 -0
- data/lib/mail/matchers/has_sent_mail.rb +34 -1
- data/lib/mail/message.rb +151 -48
- data/lib/mail/multibyte/chars.rb +2 -2
- data/lib/mail/multibyte/unicode.rb +6 -4
- data/lib/mail/network/delivery_methods/exim.rb +1 -6
- data/lib/mail/network/delivery_methods/file_delivery.rb +1 -1
- data/lib/mail/network/delivery_methods/sendmail.rb +32 -10
- data/lib/mail/network/delivery_methods/smtp.rb +31 -34
- data/lib/mail/network/delivery_methods/smtp_connection.rb +6 -6
- data/lib/mail/network/delivery_methods/test_mailer.rb +2 -2
- data/lib/mail/network/retriever_methods/imap.rb +18 -13
- data/lib/mail/parsers/address_lists_parser.rb +132 -0
- data/lib/mail/parsers/content_disposition_parser.rb +67 -0
- data/lib/mail/parsers/content_location_parser.rb +35 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +33 -0
- data/lib/mail/parsers/content_type_parser.rb +64 -0
- data/lib/mail/parsers/date_time_parser.rb +36 -0
- data/lib/mail/parsers/envelope_from_parser.rb +45 -0
- data/lib/mail/parsers/message_ids_parser.rb +39 -0
- data/lib/mail/parsers/mime_version_parser.rb +41 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +33 -0
- data/lib/mail/parsers/ragel/common.rl +184 -0
- data/lib/mail/parsers/ragel/date_time.rl +30 -0
- data/lib/mail/parsers/ragel/parser_info.rb +61 -0
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +14864 -0
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +751 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +614 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +447 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +825 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +817 -0
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +2129 -0
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +1570 -0
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +440 -0
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +564 -0
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +51 -0
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +5144 -0
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +37 -0
- data/lib/mail/parsers/ragel/ruby.rb +29 -0
- data/lib/mail/parsers/ragel.rb +17 -0
- data/lib/mail/parsers/received_parser.rb +47 -0
- data/lib/mail/parsers.rb +26 -0
- data/lib/mail/part.rb +6 -2
- data/lib/mail/parts_list.rb +5 -3
- data/lib/mail/patterns.rb +4 -1
- data/lib/mail/utilities.rb +28 -18
- data/lib/mail/version.rb +1 -1
- data/lib/mail/version_specific/ruby_1_8.rb +6 -2
- data/lib/mail/version_specific/ruby_1_9.rb +61 -21
- data/lib/mail.rb +1 -2
- metadata +112 -73
- data/lib/VERSION +0 -4
- data/lib/load_parsers.rb +0 -41
- data/lib/mail/core_extensions/shell_escape.rb +0 -56
- data/lib/mail/parsers/address_lists.rb +0 -64
- data/lib/mail/parsers/address_lists.treetop +0 -19
- data/lib/mail/parsers/content_disposition.rb +0 -535
- data/lib/mail/parsers/content_disposition.treetop +0 -46
- data/lib/mail/parsers/content_location.rb +0 -139
- data/lib/mail/parsers/content_location.treetop +0 -20
- data/lib/mail/parsers/content_transfer_encoding.rb +0 -162
- data/lib/mail/parsers/content_transfer_encoding.treetop +0 -20
- data/lib/mail/parsers/content_type.rb +0 -967
- data/lib/mail/parsers/content_type.treetop +0 -68
- data/lib/mail/parsers/date_time.rb +0 -114
- data/lib/mail/parsers/date_time.treetop +0 -11
- data/lib/mail/parsers/envelope_from.rb +0 -194
- data/lib/mail/parsers/envelope_from.treetop +0 -32
- data/lib/mail/parsers/message_ids.rb +0 -45
- data/lib/mail/parsers/message_ids.treetop +0 -15
- data/lib/mail/parsers/mime_version.rb +0 -144
- data/lib/mail/parsers/mime_version.treetop +0 -19
- data/lib/mail/parsers/phrase_lists.rb +0 -45
- data/lib/mail/parsers/phrase_lists.treetop +0 -15
- data/lib/mail/parsers/received.rb +0 -71
- data/lib/mail/parsers/received.treetop +0 -11
- data/lib/mail/parsers/rfc2045.rb +0 -464
- data/lib/mail/parsers/rfc2045.treetop +0 -36
- data/lib/mail/parsers/rfc2822.rb +0 -5397
- data/lib/mail/parsers/rfc2822.treetop +0 -410
- data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
- data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
- data/lib/tasks/corpus.rake +0 -125
- data/lib/tasks/treetop.rake +0 -10
data/lib/mail/field.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Mail
|
|
|
22
22
|
#
|
|
23
23
|
class Field
|
|
24
24
|
|
|
25
|
-
include
|
|
25
|
+
include Utilities
|
|
26
26
|
include Comparable
|
|
27
27
|
|
|
28
28
|
STRUCTURED_FIELDS = %w[ bcc cc content-description content-disposition
|
|
@@ -67,6 +67,10 @@ module Mail
|
|
|
67
67
|
"content-location" => ContentLocationField,
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
FIELD_NAME_MAP = FIELDS_MAP.inject({}) do |map, (field, field_klass)|
|
|
71
|
+
map.update(field => field_klass::CAPITALIZED_FIELD)
|
|
72
|
+
end
|
|
73
|
+
|
|
70
74
|
# Generic Field Exception
|
|
71
75
|
class FieldError < StandardError
|
|
72
76
|
end
|
|
@@ -110,15 +114,22 @@ module Mail
|
|
|
110
114
|
def initialize(name, value = nil, charset = 'utf-8')
|
|
111
115
|
case
|
|
112
116
|
when name =~ /:/ # Field.new("field-name: field data")
|
|
113
|
-
charset = value
|
|
114
|
-
name
|
|
115
|
-
|
|
117
|
+
@charset = value.blank? ? charset : value
|
|
118
|
+
@name = name[FIELD_PREFIX]
|
|
119
|
+
@raw_value = name
|
|
120
|
+
@value = nil
|
|
116
121
|
when name !~ /:/ && value.blank? # Field.new("field-name")
|
|
117
|
-
|
|
122
|
+
@name = name
|
|
123
|
+
@value = nil
|
|
124
|
+
@raw_value = nil
|
|
125
|
+
@charset = charset
|
|
118
126
|
else # Field.new("field-name", "value")
|
|
119
|
-
|
|
127
|
+
@name = name
|
|
128
|
+
@value = value
|
|
129
|
+
@raw_value = nil
|
|
130
|
+
@charset = charset
|
|
120
131
|
end
|
|
121
|
-
|
|
132
|
+
@name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
|
|
122
133
|
end
|
|
123
134
|
|
|
124
135
|
def field=(value)
|
|
@@ -126,11 +137,12 @@ module Mail
|
|
|
126
137
|
end
|
|
127
138
|
|
|
128
139
|
def field
|
|
129
|
-
@
|
|
140
|
+
_, @value = split(@raw_value) if @raw_value && !@value
|
|
141
|
+
@field ||= create_field(@name, @value, @charset)
|
|
130
142
|
end
|
|
131
143
|
|
|
132
144
|
def name
|
|
133
|
-
|
|
145
|
+
@name
|
|
134
146
|
end
|
|
135
147
|
|
|
136
148
|
def value
|
|
@@ -138,27 +150,39 @@ module Mail
|
|
|
138
150
|
end
|
|
139
151
|
|
|
140
152
|
def value=(val)
|
|
141
|
-
create_field(name, val, charset)
|
|
153
|
+
@field = create_field(name, val, @charset)
|
|
142
154
|
end
|
|
143
155
|
|
|
144
156
|
def to_s
|
|
145
157
|
field.to_s
|
|
146
158
|
end
|
|
147
159
|
|
|
160
|
+
def inspect
|
|
161
|
+
"#<#{self.class.name} 0x#{(object_id * 2).to_s(16)} #{instance_variables.map do |ivar|
|
|
162
|
+
"#{ivar}=#{instance_variable_get(ivar).inspect}"
|
|
163
|
+
end.join(" ")}>"
|
|
164
|
+
end
|
|
165
|
+
|
|
148
166
|
def update(name, value)
|
|
149
|
-
create_field(name, value, charset)
|
|
167
|
+
@field = create_field(name, value, @charset)
|
|
150
168
|
end
|
|
151
169
|
|
|
152
170
|
def same( other )
|
|
153
|
-
match_to_s(other.name,
|
|
171
|
+
match_to_s(other.name, self.name)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def responsible_for?( val )
|
|
175
|
+
name.to_s.casecmp(val.to_s) == 0
|
|
154
176
|
end
|
|
155
177
|
|
|
156
178
|
alias_method :==, :same
|
|
157
179
|
|
|
158
180
|
def <=>( other )
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
181
|
+
self.field_order_id <=> other.field_order_id
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def field_order_id
|
|
185
|
+
@field_order_id ||= (FIELD_ORDER_LOOKUP[self.name.to_s.downcase] || 100)
|
|
162
186
|
end
|
|
163
187
|
|
|
164
188
|
def method_missing(name, *args, &block)
|
|
@@ -174,37 +198,48 @@ module Mail
|
|
|
174
198
|
mime-version content-type content-transfer-encoding
|
|
175
199
|
content-location content-disposition content-description ]
|
|
176
200
|
|
|
201
|
+
FIELD_ORDER_LOOKUP = Hash[FIELD_ORDER.each_with_index.to_a]
|
|
202
|
+
|
|
177
203
|
private
|
|
178
204
|
|
|
179
205
|
def split(raw_field)
|
|
180
|
-
match_data = raw_field.mb_chars.match(
|
|
181
|
-
[match_data[1].to_s.mb_chars.strip, match_data[2].to_s.mb_chars.strip]
|
|
206
|
+
match_data = raw_field.mb_chars.match(FIELD_SPLIT)
|
|
207
|
+
[match_data[1].to_s.mb_chars.strip, match_data[2].to_s.mb_chars.strip.to_s]
|
|
182
208
|
rescue
|
|
183
209
|
STDERR.puts "WARNING: Could not parse (and so ignoring) '#{raw_field}'"
|
|
184
210
|
end
|
|
185
211
|
|
|
212
|
+
# 2.2.3. Long Header Fields
|
|
213
|
+
#
|
|
214
|
+
# The process of moving from this folded multiple-line representation
|
|
215
|
+
# of a header field to its single line representation is called
|
|
216
|
+
# "unfolding". Unfolding is accomplished by simply removing any CRLF
|
|
217
|
+
# that is immediately followed by WSP. Each header field should be
|
|
218
|
+
# treated in its unfolded form for further syntactic and semantic
|
|
219
|
+
# evaluation.
|
|
220
|
+
def unfold(string)
|
|
221
|
+
string.gsub(/[\r\n \t]+/m, ' ')
|
|
222
|
+
end
|
|
223
|
+
|
|
186
224
|
def create_field(name, value, charset)
|
|
225
|
+
value = unfold(value) if value.is_a?(String)
|
|
226
|
+
|
|
187
227
|
begin
|
|
188
|
-
|
|
228
|
+
new_field(name, value, charset)
|
|
189
229
|
rescue Mail::Field::ParseError => e
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
230
|
+
field = Mail::UnstructuredField.new(name, value)
|
|
231
|
+
field.errors << [name, value, e]
|
|
232
|
+
field
|
|
193
233
|
end
|
|
194
234
|
end
|
|
195
235
|
|
|
196
236
|
def new_field(name, value, charset)
|
|
197
237
|
lower_case_name = name.to_s.downcase
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
header_name = field_name if lower_case_name == field_name
|
|
201
|
-
end
|
|
202
|
-
if header_name
|
|
203
|
-
FIELDS_MAP[header_name].new(value, charset)
|
|
238
|
+
if field_klass = FIELDS_MAP[lower_case_name]
|
|
239
|
+
field_klass.new(value, charset)
|
|
204
240
|
else
|
|
205
241
|
OptionalField.new(name, value, charset)
|
|
206
242
|
end
|
|
207
|
-
|
|
208
243
|
end
|
|
209
244
|
|
|
210
245
|
end
|
data/lib/mail/field_list.rb
CHANGED
|
@@ -8,26 +8,26 @@ module Mail
|
|
|
8
8
|
|
|
9
9
|
include Enumerable
|
|
10
10
|
|
|
11
|
+
# Insert the field in sorted order.
|
|
12
|
+
#
|
|
13
|
+
# Heavily based on bisect.insort from Python, which is:
|
|
14
|
+
# Copyright (C) 2001-2013 Python Software Foundation.
|
|
15
|
+
# Licensed under <http://docs.python.org/license.html>
|
|
16
|
+
# From <http://hg.python.org/cpython/file/2.7/Lib/bisect.py>
|
|
11
17
|
def <<( new_field )
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
when 0
|
|
22
|
-
next
|
|
23
|
-
when 1
|
|
24
|
-
insert_idx = idx
|
|
25
|
-
break
|
|
26
|
-
end
|
|
18
|
+
lo = 0
|
|
19
|
+
hi = size
|
|
20
|
+
|
|
21
|
+
while lo < hi
|
|
22
|
+
mid = (lo + hi) / 2
|
|
23
|
+
if new_field < self[mid]
|
|
24
|
+
hi = mid
|
|
25
|
+
else
|
|
26
|
+
lo = mid + 1
|
|
27
27
|
end
|
|
28
|
-
insert(insert_idx, new_field)
|
|
29
28
|
end
|
|
29
|
+
|
|
30
|
+
insert(lo, new_field)
|
|
30
31
|
end
|
|
31
|
-
|
|
32
32
|
end
|
|
33
|
-
end
|
|
33
|
+
end
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending bcc to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a BccField as
|
|
9
|
+
# has a BccField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Only one Bcc field can appear in a header, though it can have multiple
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
#
|
|
17
17
|
# mail = Mail.new
|
|
18
18
|
# mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.bcc #=> ['
|
|
19
|
+
# mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
20
|
# mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
21
21
|
# mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
22
22
|
# mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
data/lib/mail/fields/cc_field.rb
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending cc to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a CcField as
|
|
9
|
+
# has a CcField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Only one Cc field can appear in a header, though it can have multiple
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
#
|
|
17
17
|
# mail = Mail.new
|
|
18
18
|
# mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.cc #=> ['
|
|
19
|
+
# mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
20
|
# mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
21
21
|
# mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
22
22
|
# mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# header field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending comments to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a CommentsField as
|
|
9
|
+
# has a CommentsField as its field type.
|
|
10
10
|
#
|
|
11
11
|
# An email header can have as many comments fields as it wants. There is no upper
|
|
12
12
|
# limit, the comments field is also optional (that is, no comment is needed)
|
|
@@ -6,7 +6,7 @@ module Mail
|
|
|
6
6
|
|
|
7
7
|
def parse(val = value)
|
|
8
8
|
unless val.blank?
|
|
9
|
-
@
|
|
9
|
+
@address_list = AddressList.new(encode_if_needed(val))
|
|
10
10
|
else
|
|
11
11
|
nil
|
|
12
12
|
end
|
|
@@ -20,54 +20,60 @@ module Mail
|
|
|
20
20
|
Encodings.address_encode(val, charset)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
# Allows you to iterate through each address object in the
|
|
23
|
+
# Allows you to iterate through each address object in the address_list
|
|
24
24
|
def each
|
|
25
|
-
|
|
25
|
+
address_list.addresses.each do |address|
|
|
26
26
|
yield(address)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Returns the address string of all the addresses in the address list
|
|
31
31
|
def addresses
|
|
32
|
-
list =
|
|
32
|
+
list = address_list.addresses.map { |a| a.address }
|
|
33
33
|
Mail::AddressContainer.new(self, list)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# Returns the formatted string of all the addresses in the address list
|
|
37
37
|
def formatted
|
|
38
|
-
list =
|
|
38
|
+
list = address_list.addresses.map { |a| a.format }
|
|
39
39
|
Mail::AddressContainer.new(self, list)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# Returns the display name of all the addresses in the address list
|
|
43
43
|
def display_names
|
|
44
|
-
list =
|
|
44
|
+
list = address_list.addresses.map { |a| a.display_name }
|
|
45
45
|
Mail::AddressContainer.new(self, list)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# Returns the actual address objects in the address list
|
|
49
49
|
def addrs
|
|
50
|
-
list =
|
|
50
|
+
list = address_list.addresses
|
|
51
51
|
Mail::AddressContainer.new(self, list)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Returns a hash of group name => address strings for the address list
|
|
55
55
|
def groups
|
|
56
|
-
|
|
57
|
-
tree.group_recipients.each do |group|
|
|
58
|
-
@groups[group.group_name.text_value.to_str] = get_group_addresses(group.group_list)
|
|
59
|
-
end
|
|
60
|
-
@groups
|
|
56
|
+
address_list.addresses_grouped_by_group
|
|
61
57
|
end
|
|
62
58
|
|
|
63
59
|
# Returns the addresses that are part of groups
|
|
64
60
|
def group_addresses
|
|
65
|
-
|
|
61
|
+
decoded_group_addresses
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Returns a list of decoded group addresses
|
|
65
|
+
def decoded_group_addresses
|
|
66
|
+
groups.map { |k,v| v.map { |a| a.decoded } }.flatten
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns a list of encoded group addresses
|
|
70
|
+
def encoded_group_addresses
|
|
71
|
+
groups.map { |k,v| v.map { |a| a.encoded } }.flatten
|
|
66
72
|
end
|
|
67
73
|
|
|
68
74
|
# Returns the name of all the groups in a string
|
|
69
75
|
def group_names # :nodoc:
|
|
70
|
-
|
|
76
|
+
address_list.group_names
|
|
71
77
|
end
|
|
72
78
|
|
|
73
79
|
def default
|
|
@@ -94,7 +100,7 @@ module Mail
|
|
|
94
100
|
|
|
95
101
|
def do_encode(field_name)
|
|
96
102
|
return '' if value.blank?
|
|
97
|
-
address_array =
|
|
103
|
+
address_array = address_list.addresses.reject { |a| encoded_group_addresses.include?(a.encoded) }.compact.map { |a| a.encoded }
|
|
98
104
|
address_text = address_array.join(", \r\n\s")
|
|
99
105
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.encoded }.join(", \r\n\s")};" }
|
|
100
106
|
group_text = group_array.join(" \r\n\s")
|
|
@@ -104,7 +110,7 @@ module Mail
|
|
|
104
110
|
|
|
105
111
|
def do_decode
|
|
106
112
|
return nil if value.blank?
|
|
107
|
-
address_array =
|
|
113
|
+
address_array = address_list.addresses.reject { |a| decoded_group_addresses.include?(a.decoded) }.map { |a| a.decoded }
|
|
108
114
|
address_text = address_array.join(", ")
|
|
109
115
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.decoded }.join(", ")};" }
|
|
110
116
|
group_text = group_array.join(" ")
|
|
@@ -112,15 +118,14 @@ module Mail
|
|
|
112
118
|
return_array.join(", ")
|
|
113
119
|
end
|
|
114
120
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
@tree ||= AddressList.new(value)
|
|
121
|
+
def address_list # :nodoc:
|
|
122
|
+
@address_list ||= AddressList.new(value)
|
|
118
123
|
end
|
|
119
124
|
|
|
120
125
|
def get_group_addresses(group_list)
|
|
121
126
|
if group_list.respond_to?(:addresses)
|
|
122
|
-
group_list.addresses.map do |
|
|
123
|
-
Mail::Address.new(
|
|
127
|
+
group_list.addresses.map do |address|
|
|
128
|
+
Mail::Address.new(address)
|
|
124
129
|
end
|
|
125
130
|
else
|
|
126
131
|
[]
|
|
@@ -13,7 +13,6 @@ module Mail
|
|
|
13
13
|
def parse(val = value)
|
|
14
14
|
unless val.blank?
|
|
15
15
|
@element = Mail::DateTimeElement.new(val)
|
|
16
|
-
@tree = @element.tree
|
|
17
16
|
else
|
|
18
17
|
nil
|
|
19
18
|
end
|
|
@@ -32,11 +31,5 @@ module Mail
|
|
|
32
31
|
def element
|
|
33
32
|
@element ||= Mail::DateTimeElement.new(value)
|
|
34
33
|
end
|
|
35
|
-
|
|
36
|
-
# Returns the syntax tree of the Date
|
|
37
|
-
def tree
|
|
38
|
-
@tree ||= element.tree
|
|
39
|
-
end
|
|
40
|
-
|
|
41
34
|
end
|
|
42
35
|
end
|
|
@@ -22,7 +22,7 @@ module Mail
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def to_s
|
|
25
|
-
decoded
|
|
25
|
+
decoded.to_s
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def default
|
|
@@ -43,15 +43,15 @@ module Mail
|
|
|
43
43
|
if value.is_a?(Array)
|
|
44
44
|
value
|
|
45
45
|
else
|
|
46
|
-
value.to_s.
|
|
46
|
+
value.to_s.sub(/#{field_name}:\s+/i, '')
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
|
|
50
51
|
def ensure_filename_quoted(value)
|
|
51
|
-
if
|
|
52
|
-
value.
|
|
52
|
+
if value.is_a?(String)
|
|
53
|
+
value.sub! FILENAME_RE, '\1="\2"'
|
|
53
54
|
end
|
|
54
55
|
end
|
|
55
|
-
|
|
56
56
|
end
|
|
57
57
|
end
|
|
@@ -10,8 +10,8 @@ module Mail
|
|
|
10
10
|
|
|
11
11
|
def initialize(value = nil, charset = 'utf-8')
|
|
12
12
|
self.charset = charset
|
|
13
|
-
value = '7bit' if value.to_s =~ /7
|
|
14
|
-
value = '8bit' if value.to_s =~ /8
|
|
13
|
+
value = '7bit' if value.to_s =~ /7-?bits?/i
|
|
14
|
+
value = '8bit' if value.to_s =~ /8-?bits?/i
|
|
15
15
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
|
16
16
|
self.parse
|
|
17
17
|
self
|
|
@@ -23,12 +23,6 @@ module Mail
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def tree
|
|
27
|
-
STDERR.puts("tree is deprecated. Please use encoding to get parse result\n#{caller}")
|
|
28
|
-
@element ||= Mail::ContentTransferEncodingElement.new(value)
|
|
29
|
-
@tree ||= @element.tree
|
|
30
|
-
end
|
|
31
|
-
|
|
32
26
|
def element
|
|
33
27
|
@element ||= Mail::ContentTransferEncodingElement.new(value)
|
|
34
28
|
end
|
|
@@ -180,7 +180,7 @@ module Mail
|
|
|
180
180
|
params = $2.to_s.split(/\s+/)
|
|
181
181
|
params = params.map { |i| i.to_s.chomp.strip }
|
|
182
182
|
params = params.map { |i| i.split(/\s*\=\s*/) }
|
|
183
|
-
params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s)}" }.join('; ')
|
|
183
|
+
params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
|
|
184
184
|
"#{type}; #{params}"
|
|
185
185
|
when val =~ /^\s*$/
|
|
186
186
|
'text/plain'
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# = Date Field
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# The Date field inherits from StructuredField and handles the Date: header
|
|
6
6
|
# field in the email.
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# Sending date to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a DateField as
|
|
9
|
+
# has a DateField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance methods.
|
|
11
|
-
#
|
|
11
|
+
#
|
|
12
12
|
# There must be excatly one Date field in an RFC2822 email.
|
|
13
|
-
#
|
|
13
|
+
#
|
|
14
14
|
# == Examples:
|
|
15
|
-
#
|
|
15
|
+
#
|
|
16
16
|
# mail = Mail.new
|
|
17
17
|
# mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
|
|
18
18
|
# mail.date #=> #<DateTime: 211747170121/86400,-1/3,2299161>
|
|
@@ -20,17 +20,17 @@
|
|
|
20
20
|
# mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
|
|
21
21
|
# mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
|
|
22
22
|
# mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
|
|
23
|
-
#
|
|
23
|
+
#
|
|
24
24
|
require 'mail/fields/common/common_date'
|
|
25
25
|
|
|
26
26
|
module Mail
|
|
27
27
|
class DateField < StructuredField
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
include Mail::CommonDate
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
FIELD_NAME = 'date'
|
|
32
32
|
CAPITALIZED_FIELD = "Date"
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
def initialize(value = nil, charset = 'utf-8')
|
|
35
35
|
self.charset = charset
|
|
36
36
|
if value.blank?
|
|
@@ -44,14 +44,14 @@ module Mail
|
|
|
44
44
|
rescue ArgumentError => e
|
|
45
45
|
raise e unless "invalid date"==e.message
|
|
46
46
|
end
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
def encoded
|
|
49
49
|
do_encode(CAPITALIZED_FIELD)
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
def decoded
|
|
53
53
|
do_decode
|
|
54
54
|
end
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
end
|
|
57
57
|
end
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending from to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a FromField as
|
|
9
|
+
# has a FromField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Only one From field can appear in a header, though it can have multiple
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
#
|
|
17
17
|
# mail = Mail.new
|
|
18
18
|
# mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.from #=> ['
|
|
19
|
+
# mail.from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
20
|
# mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
|
|
21
21
|
# mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
|
|
22
22
|
# mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# In-Reply-To: header field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending in_reply_to to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a InReplyToField as
|
|
9
|
+
# has a InReplyToField as its field type. This includes all Mail::CommonMessageId
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Note that, the #message_ids method will return an array of message IDs without the
|
|
@@ -38,6 +38,7 @@ module Mail
|
|
|
38
38
|
|
|
39
39
|
def initialize(value = nil, charset = 'utf-8')
|
|
40
40
|
self.charset = charset
|
|
41
|
+
value = value.join("\r\n\s") if value.is_a?(Array)
|
|
41
42
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
|
42
43
|
self.parse
|
|
43
44
|
self
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Message-ID: header field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending message_id to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a MessageIdField as
|
|
9
|
+
# has a MessageIdField as its field type. This includes all Mail::CommonMessageId
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Only one MessageId field can appear in a header, and syntactically it can only have
|
|
@@ -75,8 +75,7 @@ module Mail
|
|
|
75
75
|
private
|
|
76
76
|
|
|
77
77
|
def generate_message_id
|
|
78
|
-
|
|
79
|
-
"<#{Mail.random_tag}@#{fqdn}.mail>"
|
|
78
|
+
"<#{Mail.random_tag}@#{::Socket.gethostname}.mail>"
|
|
80
79
|
end
|
|
81
80
|
|
|
82
81
|
end
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending references to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a ReferencesField as
|
|
9
|
+
# has a ReferencesField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Note that, the #message_ids method will return an array of message IDs without the
|
|
@@ -38,6 +38,7 @@ module Mail
|
|
|
38
38
|
|
|
39
39
|
def initialize(value = nil, charset = 'utf-8')
|
|
40
40
|
self.charset = charset
|
|
41
|
+
value = value.join("\r\n\s") if value.is_a?(Array)
|
|
41
42
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
|
42
43
|
self.parse
|
|
43
44
|
self
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending reply_to to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a ReplyToField as
|
|
9
|
+
# has a ReplyToField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Only one Reply-To field can appear in a header, though it can have multiple
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
#
|
|
17
17
|
# mail = Mail.new
|
|
18
18
|
# mail.reply_to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.reply_to #=> ['
|
|
19
|
+
# mail.reply_to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
20
|
# mail[:reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
|
|
21
21
|
# mail['reply-to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
|
|
22
22
|
# mail['Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# Resent-Bcc: header field in the email.
|
|
7
7
|
#
|
|
8
8
|
# Sending resent_bcc to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a ResentBccField as
|
|
9
|
+
# has a ResentBccField as its field type. This includes all Mail::CommonAddress
|
|
10
10
|
# module instance metods.
|
|
11
11
|
#
|
|
12
12
|
# Only one Resent-Bcc field can appear in a header, though it can have multiple
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
#
|
|
17
17
|
# mail = Mail.new
|
|
18
18
|
# mail.resent_bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.resent_bcc #=> ['
|
|
19
|
+
# mail.resent_bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
20
|
# mail[:resent_bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
|
|
21
21
|
# mail['resent-bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
|
|
22
22
|
# mail['Resent-Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
|