mail 2.7.1 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +59 -28
- data/lib/mail/attachments_list.rb +2 -5
- data/lib/mail/body.rb +24 -47
- data/lib/mail/check_delivery_params.rb +21 -16
- data/lib/mail/constants.rb +27 -5
- data/lib/mail/elements/address.rb +27 -27
- data/lib/mail/elements/address_list.rb +1 -1
- data/lib/mail/elements/content_disposition_element.rb +1 -1
- data/lib/mail/elements/content_location_element.rb +1 -1
- data/lib/mail/elements/content_transfer_encoding_element.rb +1 -1
- data/lib/mail/elements/content_type_element.rb +8 -4
- data/lib/mail/elements/date_time_element.rb +1 -1
- data/lib/mail/elements/envelope_from_element.rb +13 -7
- data/lib/mail/elements/message_ids_element.rb +14 -5
- data/lib/mail/elements/mime_version_element.rb +1 -1
- data/lib/mail/elements/phrase_list.rb +7 -2
- data/lib/mail/elements/received_element.rb +20 -6
- data/lib/mail/encodings/7bit.rb +5 -0
- data/lib/mail/encodings/base64.rb +2 -2
- data/lib/mail/encodings/quoted_printable.rb +2 -2
- data/lib/mail/encodings.rb +30 -59
- data/lib/mail/envelope.rb +11 -14
- data/lib/mail/field.rb +37 -53
- data/lib/mail/field_list.rb +60 -7
- data/lib/mail/fields/bcc_field.rb +34 -52
- data/lib/mail/fields/cc_field.rb +28 -49
- data/lib/mail/fields/comments_field.rb +27 -37
- data/lib/mail/fields/common_address_field.rb +170 -0
- data/lib/mail/fields/common_date_field.rb +58 -0
- data/lib/mail/fields/common_field.rb +77 -0
- data/lib/mail/fields/common_message_id_field.rb +42 -0
- data/lib/mail/fields/content_description_field.rb +7 -14
- data/lib/mail/fields/content_disposition_field.rb +13 -38
- data/lib/mail/fields/content_id_field.rb +24 -51
- data/lib/mail/fields/content_location_field.rb +11 -25
- data/lib/mail/fields/content_transfer_encoding_field.rb +31 -31
- data/lib/mail/fields/content_type_field.rb +46 -71
- data/lib/mail/fields/date_field.rb +23 -51
- data/lib/mail/fields/from_field.rb +28 -49
- data/lib/mail/fields/in_reply_to_field.rb +38 -49
- data/lib/mail/fields/keywords_field.rb +18 -31
- data/lib/mail/fields/message_id_field.rb +25 -71
- data/lib/mail/fields/mime_version_field.rb +19 -30
- data/lib/mail/fields/named_structured_field.rb +11 -0
- data/lib/mail/fields/named_unstructured_field.rb +11 -0
- data/lib/mail/fields/optional_field.rb +5 -6
- data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +12 -10
- data/lib/mail/fields/received_field.rb +43 -57
- data/lib/mail/fields/references_field.rb +35 -49
- data/lib/mail/fields/reply_to_field.rb +28 -49
- data/lib/mail/fields/resent_bcc_field.rb +28 -49
- data/lib/mail/fields/resent_cc_field.rb +28 -49
- data/lib/mail/fields/resent_date_field.rb +5 -29
- data/lib/mail/fields/resent_from_field.rb +28 -49
- data/lib/mail/fields/resent_message_id_field.rb +5 -29
- data/lib/mail/fields/resent_sender_field.rb +27 -56
- data/lib/mail/fields/resent_to_field.rb +28 -49
- data/lib/mail/fields/return_path_field.rb +50 -54
- data/lib/mail/fields/sender_field.rb +34 -55
- data/lib/mail/fields/structured_field.rb +3 -30
- data/lib/mail/fields/subject_field.rb +9 -11
- data/lib/mail/fields/to_field.rb +28 -49
- data/lib/mail/fields/unstructured_field.rb +16 -48
- data/lib/mail/header.rb +69 -110
- data/lib/mail/matchers/attachment_matchers.rb +15 -0
- data/lib/mail/message.rb +52 -66
- data/lib/mail/multibyte/chars.rb +8 -166
- data/lib/mail/multibyte/utils.rb +26 -43
- data/lib/mail/multibyte.rb +1 -11
- data/lib/mail/network/delivery_methods/exim.rb +5 -4
- data/lib/mail/network/delivery_methods/file_delivery.rb +11 -10
- data/lib/mail/network/delivery_methods/logger_delivery.rb +2 -5
- data/lib/mail/network/delivery_methods/sendmail.rb +56 -18
- data/lib/mail/network/delivery_methods/smtp.rb +25 -9
- data/lib/mail/network/delivery_methods/smtp_connection.rb +3 -12
- data/lib/mail/network/delivery_methods/test_mailer.rb +4 -2
- data/lib/mail/network/retriever_methods/base.rb +8 -8
- data/lib/mail/network/retriever_methods/imap.rb +2 -2
- data/lib/mail/network/retriever_methods/pop3.rb +2 -2
- data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
- data/lib/mail/parsers/address_lists_parser.rb +33070 -33064
- data/lib/mail/parsers/address_lists_parser.rl +7 -0
- data/lib/mail/parsers/content_disposition_parser.rb +833 -827
- data/lib/mail/parsers/content_disposition_parser.rl +7 -0
- data/lib/mail/parsers/content_location_parser.rb +770 -764
- data/lib/mail/parsers/content_location_parser.rl +7 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +474 -468
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +7 -0
- data/lib/mail/parsers/content_type_parser.rb +971 -965
- data/lib/mail/parsers/content_type_parser.rl +7 -0
- data/lib/mail/parsers/date_time_parser.rb +838 -832
- data/lib/mail/parsers/date_time_parser.rl +7 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3623 -3529
- data/lib/mail/parsers/envelope_from_parser.rl +7 -0
- data/lib/mail/parsers/message_ids_parser.rb +5107 -2800
- data/lib/mail/parsers/message_ids_parser.rl +12 -1
- data/lib/mail/parsers/mime_version_parser.rb +463 -457
- data/lib/mail/parsers/mime_version_parser.rl +7 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +836 -830
- data/lib/mail/parsers/phrase_lists_parser.rl +8 -1
- data/lib/mail/parsers/received_parser.rb +8688 -8682
- data/lib/mail/parsers/received_parser.rl +7 -0
- data/lib/mail/parsers/rfc5322.rl +28 -13
- data/lib/mail/parsers.rb +11 -17
- data/lib/mail/part.rb +5 -9
- data/lib/mail/parts_list.rb +57 -0
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +307 -69
- data/lib/mail/version.rb +1 -1
- data/lib/mail/yaml.rb +30 -0
- data/lib/mail.rb +3 -20
- metadata +72 -18
- data/lib/mail/core_extensions/smtp.rb +0 -28
- data/lib/mail/core_extensions/string.rb +0 -17
- data/lib/mail/fields/common/address_container.rb +0 -17
- data/lib/mail/fields/common/common_address.rb +0 -161
- data/lib/mail/fields/common/common_date.rb +0 -36
- data/lib/mail/fields/common/common_field.rb +0 -52
- data/lib/mail/fields/common/common_message_id.rb +0 -49
- data/lib/mail/version_specific/ruby_1_8.rb +0 -163
- data/lib/mail/version_specific/ruby_1_9.rb +0 -278
data/lib/mail/header.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
require 'mail/constants'
|
4
|
+
require 'mail/utilities'
|
5
|
+
|
3
6
|
module Mail
|
4
|
-
|
5
7
|
# Provides access to a header object.
|
6
|
-
#
|
8
|
+
#
|
7
9
|
# ===Per RFC2822
|
8
|
-
#
|
10
|
+
#
|
9
11
|
# 2.2. Header Fields
|
10
|
-
#
|
12
|
+
#
|
11
13
|
# Header fields are lines composed of a field name, followed by a colon
|
12
14
|
# (":"), followed by a field body, and terminated by CRLF. A field
|
13
15
|
# name MUST be composed of printable US-ASCII characters (i.e.,
|
@@ -18,14 +20,12 @@ module Mail
|
|
18
20
|
# 2.2.3. All field bodies MUST conform to the syntax described in
|
19
21
|
# sections 3 and 4 of this standard.
|
20
22
|
class Header
|
21
|
-
include Constants
|
22
|
-
include Utilities
|
23
23
|
include Enumerable
|
24
|
-
|
24
|
+
|
25
25
|
@@maximum_amount = 1000
|
26
26
|
|
27
27
|
# Large amount of headers in Email might create extra high CPU load
|
28
|
-
# Use this parameter to limit number of headers that will be parsed by
|
28
|
+
# Use this parameter to limit number of headers that will be parsed by
|
29
29
|
# mail library.
|
30
30
|
# Default: 1000
|
31
31
|
def self.maximum_amount
|
@@ -36,12 +36,14 @@ module Mail
|
|
36
36
|
@@maximum_amount = value
|
37
37
|
end
|
38
38
|
|
39
|
+
attr_reader :raw_source, :charset
|
40
|
+
|
39
41
|
# Creates a new header object.
|
40
|
-
#
|
42
|
+
#
|
41
43
|
# Accepts raw text or nothing. If given raw text will attempt to parse
|
42
44
|
# it and split it into the various fields, instantiating each field as
|
43
45
|
# it goes.
|
44
|
-
#
|
46
|
+
#
|
45
47
|
# If it finds a field that should be a structured field (such as content
|
46
48
|
# type), but it fails to parse it, it will simply make it an unstructured
|
47
49
|
# field and leave it alone. This will mean that the data is preserved but
|
@@ -50,7 +52,7 @@ module Mail
|
|
50
52
|
# me the example so we can fix it.
|
51
53
|
def initialize(header_text = nil, charset = nil)
|
52
54
|
@charset = charset
|
53
|
-
|
55
|
+
@raw_source = ::Mail::Utilities.to_crlf(header_text).lstrip
|
54
56
|
split_header if header_text
|
55
57
|
end
|
56
58
|
|
@@ -59,21 +61,15 @@ module Mail
|
|
59
61
|
@fields = @fields.dup
|
60
62
|
@fields.map!(&:dup)
|
61
63
|
end
|
62
|
-
|
63
|
-
# The preserved raw source of the header as you passed it in, untouched
|
64
|
-
# for your Regexing glory.
|
65
|
-
def raw_source
|
66
|
-
@raw_source
|
67
|
-
end
|
68
|
-
|
64
|
+
|
69
65
|
# Returns an array of all the fields in the header in order that they
|
70
66
|
# were read in.
|
71
67
|
def fields
|
72
68
|
@fields ||= FieldList.new
|
73
69
|
end
|
74
|
-
|
70
|
+
|
75
71
|
# 3.6. Field definitions
|
76
|
-
#
|
72
|
+
#
|
77
73
|
# It is important to note that the header fields are not guaranteed to
|
78
74
|
# be in a particular order. They may appear in any order, and they
|
79
75
|
# have been known to be reordered occasionally when transported over
|
@@ -83,36 +79,35 @@ module Mail
|
|
83
79
|
# header fields MUST NOT be reordered, and SHOULD be kept in blocks
|
84
80
|
# prepended to the message. See sections 3.6.6 and 3.6.7 for more
|
85
81
|
# information.
|
86
|
-
#
|
82
|
+
#
|
87
83
|
# Populates the fields container with Field objects in the order it
|
88
84
|
# receives them in.
|
89
85
|
#
|
90
86
|
# Acceps an array of field string values, for example:
|
91
|
-
#
|
87
|
+
#
|
92
88
|
# h = Header.new
|
93
89
|
# h.fields = ['From: mikel@me.com', 'To: bob@you.com']
|
94
90
|
def fields=(unfolded_fields)
|
95
91
|
@fields = Mail::FieldList.new
|
96
|
-
Kernel.warn "WARNING: More than #{self.class.maximum_amount} header fields; only using the first #{self.class.maximum_amount} and ignoring the rest" if unfolded_fields.length > self.class.maximum_amount
|
97
|
-
unfolded_fields[0..(self.class.maximum_amount-1)].each do |field|
|
98
92
|
|
93
|
+
if unfolded_fields.size > self.class.maximum_amount
|
94
|
+
Kernel.warn "WARNING: More than #{self.class.maximum_amount} header fields; only using the first #{self.class.maximum_amount} and ignoring the rest"
|
95
|
+
unfolded_fields = unfolded_fields.slice(0...self.class.maximum_amount)
|
96
|
+
end
|
97
|
+
|
98
|
+
unfolded_fields.each do |field|
|
99
99
|
if field = Field.parse(field, charset)
|
100
|
-
|
101
|
-
selected.first.update(field.name, field.value)
|
102
|
-
else
|
103
|
-
@fields << field
|
104
|
-
end
|
100
|
+
@fields.add_field field
|
105
101
|
end
|
106
102
|
end
|
107
|
-
|
108
103
|
end
|
109
|
-
|
104
|
+
|
110
105
|
def errors
|
111
106
|
@fields.map(&:errors).flatten(1)
|
112
107
|
end
|
113
|
-
|
108
|
+
|
114
109
|
# 3.6. Field definitions
|
115
|
-
#
|
110
|
+
#
|
116
111
|
# The following table indicates limits on the number of times each
|
117
112
|
# field may occur in a message header as well as any special
|
118
113
|
# limitations on the use of those fields. An asterisk next to a value
|
@@ -122,35 +117,25 @@ module Mail
|
|
122
117
|
# <snip table from 3.6>
|
123
118
|
#
|
124
119
|
# As per RFC, many fields can appear more than once, we will return a string
|
125
|
-
# of the value if there is only one header, or if there is more than one
|
120
|
+
# of the value if there is only one header, or if there is more than one
|
126
121
|
# matching header, will return an array of values in order that they appear
|
127
122
|
# in the header ordered from top to bottom.
|
128
|
-
#
|
123
|
+
#
|
129
124
|
# Example:
|
130
|
-
#
|
125
|
+
#
|
131
126
|
# h = Header.new
|
132
127
|
# h.fields = ['To: mikel@me.com', 'X-Mail-SPAM: 15', 'X-Mail-SPAM: 20']
|
133
128
|
# h['To'] #=> 'mikel@me.com'
|
134
129
|
# h['X-Mail-SPAM'] #=> ['15', '20']
|
135
130
|
def [](name)
|
136
|
-
|
137
|
-
name.downcase!
|
138
|
-
selected = select_field_for(name)
|
139
|
-
case
|
140
|
-
when selected.length > 1
|
141
|
-
selected.map { |f| f }
|
142
|
-
when !Utilities.blank?(selected)
|
143
|
-
selected.first
|
144
|
-
else
|
145
|
-
nil
|
146
|
-
end
|
131
|
+
fields.get_field(Utilities.dasherize(name))
|
147
132
|
end
|
148
|
-
|
133
|
+
|
149
134
|
# Sets the FIRST matching field in the header to passed value, or deletes
|
150
135
|
# the FIRST field matched from the header if passed nil
|
151
|
-
#
|
136
|
+
#
|
152
137
|
# Example:
|
153
|
-
#
|
138
|
+
#
|
154
139
|
# h = Header.new
|
155
140
|
# h.fields = ['To: mikel@me.com', 'X-Mail-SPAM: 15', 'X-Mail-SPAM: 20']
|
156
141
|
# h['To'] = 'bob@you.com'
|
@@ -160,51 +145,39 @@ module Mail
|
|
160
145
|
# h['X-Mail-SPAM'] = nil
|
161
146
|
# h['X-Mail-SPAM'] # => nil
|
162
147
|
def []=(name, value)
|
163
|
-
name =
|
164
|
-
if name.include?(
|
148
|
+
name = name.to_s
|
149
|
+
if name.include?(Constants::COLON)
|
165
150
|
raise ArgumentError, "Header names may not contain a colon: #{name.inspect}"
|
166
151
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
fields.delete_if { |f| selected.include?(f) }
|
174
|
-
|
175
|
-
# User wants to change the field
|
176
|
-
when !Utilities.blank?(selected) && limited_field?(fn)
|
177
|
-
selected.first.update(fn, value)
|
178
|
-
|
179
|
-
# User wants to create the field
|
152
|
+
|
153
|
+
name = Utilities.dasherize(name)
|
154
|
+
|
155
|
+
# Assign nil to delete the field
|
156
|
+
if value.nil?
|
157
|
+
fields.delete_field name
|
180
158
|
else
|
181
|
-
|
182
|
-
|
183
|
-
end
|
184
|
-
if dasherize(fn) == "content-type"
|
159
|
+
fields.add_field Field.new(name.to_s, value, charset)
|
160
|
+
|
185
161
|
# Update charset if specified in Content-Type
|
186
|
-
|
187
|
-
|
162
|
+
if name == 'content-type'
|
163
|
+
params = self[:content_type].parameters rescue nil
|
164
|
+
@charset = params[:charset] if params && params[:charset]
|
165
|
+
end
|
188
166
|
end
|
189
167
|
end
|
190
|
-
|
191
|
-
def charset
|
192
|
-
@charset
|
193
|
-
end
|
194
|
-
|
168
|
+
|
195
169
|
def charset=(val)
|
196
170
|
params = self[:content_type].parameters rescue nil
|
197
171
|
if params
|
198
|
-
|
172
|
+
if val
|
173
|
+
params[:charset] = val
|
174
|
+
else
|
175
|
+
params.delete(:charset)
|
176
|
+
end
|
199
177
|
end
|
200
178
|
@charset = val
|
201
179
|
end
|
202
|
-
|
203
|
-
LIMITED_FIELDS = %w[ date from sender reply-to to cc bcc
|
204
|
-
message-id in-reply-to references subject
|
205
|
-
return-path content-type mime-version
|
206
|
-
content-transfer-encoding content-description
|
207
|
-
content-id content-disposition content-location]
|
180
|
+
|
208
181
|
|
209
182
|
def encoded
|
210
183
|
buffer = String.new
|
@@ -218,61 +191,47 @@ module Mail
|
|
218
191
|
def to_s
|
219
192
|
encoded
|
220
193
|
end
|
221
|
-
|
194
|
+
|
222
195
|
def decoded
|
223
|
-
raise NoMethodError, 'Can not decode an entire header as there could be character set conflicts
|
196
|
+
raise NoMethodError, 'Can not decode an entire header as there could be character set conflicts. Try calling #decoded on the various fields.'
|
224
197
|
end
|
225
198
|
|
226
199
|
def field_summary
|
227
|
-
fields.
|
200
|
+
fields.summary
|
228
201
|
end
|
229
202
|
|
230
203
|
# Returns true if the header has a Message-ID defined (empty or not)
|
231
204
|
def has_message_id?
|
232
|
-
|
205
|
+
fields.has_field? 'Message-ID'
|
233
206
|
end
|
234
207
|
|
235
208
|
# Returns true if the header has a Content-ID defined (empty or not)
|
236
209
|
def has_content_id?
|
237
|
-
|
210
|
+
fields.has_field? 'Content-ID'
|
238
211
|
end
|
239
212
|
|
240
213
|
# Returns true if the header has a Date defined (empty or not)
|
241
214
|
def has_date?
|
242
|
-
|
215
|
+
fields.has_field? 'Date'
|
243
216
|
end
|
244
217
|
|
245
218
|
# Returns true if the header has a MIME version defined (empty or not)
|
246
219
|
def has_mime_version?
|
247
|
-
|
220
|
+
fields.has_field? 'Mime-Version'
|
248
221
|
end
|
249
222
|
|
250
223
|
private
|
251
|
-
|
252
|
-
def raw_source=(val)
|
253
|
-
@raw_source = ::Mail::Utilities.to_crlf(val).lstrip
|
254
|
-
end
|
255
|
-
|
224
|
+
|
256
225
|
# Splits an unfolded and line break cleaned header into individual field
|
257
226
|
# strings.
|
258
227
|
def split_header
|
259
|
-
self.fields = raw_source.split(HEADER_SPLIT)
|
260
|
-
end
|
261
|
-
|
262
|
-
def select_field_for(name)
|
263
|
-
fields.select { |f| f.responsible_for?(name) }
|
264
|
-
end
|
265
|
-
|
266
|
-
def limited_field?(name)
|
267
|
-
LIMITED_FIELDS.include?(name.to_s.downcase)
|
228
|
+
self.fields = @raw_source.split(Constants::HEADER_SPLIT)
|
268
229
|
end
|
269
230
|
|
270
|
-
# Enumerable support; yield each field in order to the block if there is one,
|
271
|
-
# or return an Enumerator for them if there isn't.
|
272
|
-
def each( &block )
|
273
|
-
return self.fields.each( &block ) if block
|
274
|
-
self.fields.each
|
275
|
-
end
|
276
231
|
|
232
|
+
# Enumerable support. Yield each field in order.
|
233
|
+
def each(&block)
|
234
|
+
fields.each(&block)
|
235
|
+
end
|
277
236
|
end
|
278
237
|
end
|
@@ -9,6 +9,10 @@ module Mail
|
|
9
9
|
AttachmentFilenameMatcher.new(filename)
|
10
10
|
end
|
11
11
|
|
12
|
+
def an_attachment_with_mime_type(filename)
|
13
|
+
AttachmentMimeTypeMatcher.new(filename)
|
14
|
+
end
|
15
|
+
|
12
16
|
class AnyAttachmentMatcher
|
13
17
|
def ===(other)
|
14
18
|
other.attachment?
|
@@ -25,5 +29,16 @@ module Mail
|
|
25
29
|
other.attachment? && other.filename == filename
|
26
30
|
end
|
27
31
|
end
|
32
|
+
|
33
|
+
class AttachmentMimeTypeMatcher
|
34
|
+
attr_reader :mime_type
|
35
|
+
def initialize(mime_type)
|
36
|
+
@mime_type = mime_type
|
37
|
+
end
|
38
|
+
|
39
|
+
def ===(other)
|
40
|
+
other.attachment? && other.mime_type == mime_type
|
41
|
+
end
|
42
|
+
end
|
28
43
|
end
|
29
44
|
end
|
data/lib/mail/message.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
-
require
|
3
|
+
require 'mail/constants'
|
4
|
+
require 'mail/utilities'
|
5
|
+
require 'mail/yaml'
|
4
6
|
|
5
7
|
module Mail
|
6
8
|
# The Message class provides a single point of access to all things to do with an
|
@@ -46,10 +48,6 @@ module Mail
|
|
46
48
|
# follows the header and is separated from the header by an empty line
|
47
49
|
# (i.e., a line with nothing preceding the CRLF).
|
48
50
|
class Message
|
49
|
-
|
50
|
-
include Constants
|
51
|
-
include Utilities
|
52
|
-
|
53
51
|
# ==Making an email
|
54
52
|
#
|
55
53
|
# You can make an new mail object via a block, passing a string, file or direct assignment.
|
@@ -149,7 +147,7 @@ module Mail
|
|
149
147
|
# m.to 'recipient@example.com'
|
150
148
|
# end
|
151
149
|
if block_given?
|
152
|
-
if block.arity.zero?
|
150
|
+
if block.arity.zero?
|
153
151
|
instance_eval(&block)
|
154
152
|
else
|
155
153
|
yield self
|
@@ -235,11 +233,6 @@ module Mail
|
|
235
233
|
def self.default_charset=(charset); @@default_charset = charset; end
|
236
234
|
self.default_charset = 'UTF-8'
|
237
235
|
|
238
|
-
def register_for_delivery_notification(observer)
|
239
|
-
warn("Message#register_for_delivery_notification is deprecated, please call Mail.register_observer instead")
|
240
|
-
Mail.register_observer(observer)
|
241
|
-
end
|
242
|
-
|
243
236
|
def inform_observers
|
244
237
|
Mail.inform_observers(self)
|
245
238
|
end
|
@@ -301,7 +294,7 @@ module Mail
|
|
301
294
|
reply.references ||= bracketed_message_id
|
302
295
|
end
|
303
296
|
if subject
|
304
|
-
reply.subject = subject =~ /^Re:/i ? subject : "
|
297
|
+
reply.subject = subject =~ /^Re:/i ? subject : "Re: #{subject}"
|
305
298
|
end
|
306
299
|
if reply_to || from
|
307
300
|
reply.to = self[reply_to ? :reply_to : :from].to_s
|
@@ -406,9 +399,9 @@ module Mail
|
|
406
399
|
end
|
407
400
|
|
408
401
|
# Sets the envelope from for the email
|
409
|
-
def set_envelope(
|
402
|
+
def set_envelope(val)
|
410
403
|
@raw_envelope = val
|
411
|
-
@envelope = Mail::Envelope.
|
404
|
+
@envelope = Mail::Envelope.parse(val) rescue nil
|
412
405
|
end
|
413
406
|
|
414
407
|
# The raw_envelope is the From mikel@test.lindsaar.net Mon May 2 16:07:05 2009
|
@@ -1339,7 +1332,7 @@ module Mail
|
|
1339
1332
|
# mail['foo'] = '1234'
|
1340
1333
|
# mail['foo'].to_s #=> '1234'
|
1341
1334
|
def [](name)
|
1342
|
-
header[underscoreize(name)]
|
1335
|
+
header[Utilities.underscoreize(name)]
|
1343
1336
|
end
|
1344
1337
|
|
1345
1338
|
# Method Missing in this implementation allows you to set any of the
|
@@ -1385,7 +1378,7 @@ module Mail
|
|
1385
1378
|
#:nodoc:
|
1386
1379
|
# Only take the structured fields, as we could take _anything_ really
|
1387
1380
|
# as it could become an optional field... "but therin lies the dark side"
|
1388
|
-
field_name = underscoreize(name).chomp("=")
|
1381
|
+
field_name = Utilities.underscoreize(name).chomp("=")
|
1389
1382
|
if Mail::Field::KNOWN_FIELDS.include?(field_name)
|
1390
1383
|
if args.empty?
|
1391
1384
|
header[field_name]
|
@@ -1436,11 +1429,6 @@ module Mail
|
|
1436
1429
|
header[:content_transfer_encoding] && Utilities.blank?(header[:content_transfer_encoding].errors)
|
1437
1430
|
end
|
1438
1431
|
|
1439
|
-
def has_transfer_encoding? # :nodoc:
|
1440
|
-
warn(":has_transfer_encoding? is deprecated in Mail 1.4.3. Please use has_content_transfer_encoding?\n#{caller}")
|
1441
|
-
has_content_transfer_encoding?
|
1442
|
-
end
|
1443
|
-
|
1444
1432
|
# Creates a new empty Message-ID field and inserts it in the correct order
|
1445
1433
|
# into the Header. The MessageIdField object will automatically generate
|
1446
1434
|
# a unique message ID if you try and encode it or output it to_s without
|
@@ -1489,7 +1477,9 @@ module Mail
|
|
1489
1477
|
warning = "Non US-ASCII detected and no charset defined.\nDefaulting to UTF-8, set your own if this is incorrect.\n"
|
1490
1478
|
warn(warning)
|
1491
1479
|
end
|
1492
|
-
|
1480
|
+
if @charset
|
1481
|
+
header[:content_type].parameters['charset'] = @charset
|
1482
|
+
end
|
1493
1483
|
end
|
1494
1484
|
end
|
1495
1485
|
|
@@ -1498,30 +1488,15 @@ module Mail
|
|
1498
1488
|
header[:content_transfer_encoding] ||= body.default_encoding
|
1499
1489
|
end
|
1500
1490
|
|
1501
|
-
def add_transfer_encoding # :nodoc:
|
1502
|
-
warn(":add_transfer_encoding is deprecated in Mail 1.4.3. Please use add_content_transfer_encoding\n#{caller}")
|
1503
|
-
add_content_transfer_encoding
|
1504
|
-
end
|
1505
|
-
|
1506
|
-
def transfer_encoding # :nodoc:
|
1507
|
-
warn(":transfer_encoding is deprecated in Mail 1.4.3. Please use content_transfer_encoding\n#{caller}")
|
1508
|
-
content_transfer_encoding
|
1509
|
-
end
|
1510
|
-
|
1511
1491
|
# Returns the MIME media type of part we are on, this is taken from the content-type header
|
1512
1492
|
def mime_type
|
1513
1493
|
has_content_type? ? header[:content_type].string : nil rescue nil
|
1514
1494
|
end
|
1515
1495
|
|
1516
|
-
def message_content_type
|
1517
|
-
warn(":message_content_type is deprecated in Mail 1.4.3. Please use mime_type\n#{caller}")
|
1518
|
-
mime_type
|
1519
|
-
end
|
1520
|
-
|
1521
1496
|
# Returns the character set defined in the content type field
|
1522
1497
|
def charset
|
1523
1498
|
if @header
|
1524
|
-
has_content_type? ? content_type_parameters['charset'] : @charset
|
1499
|
+
has_content_type? && !multipart? ? content_type_parameters['charset'] : @charset
|
1525
1500
|
else
|
1526
1501
|
@charset
|
1527
1502
|
end
|
@@ -1544,12 +1519,6 @@ module Mail
|
|
1544
1519
|
has_content_type? ? header[:content_type].sub_type : nil rescue nil
|
1545
1520
|
end
|
1546
1521
|
|
1547
|
-
# Returns the content type parameters
|
1548
|
-
def mime_parameters
|
1549
|
-
warn(':mime_parameters is deprecated in Mail 1.4.3, please use :content_type_parameters instead')
|
1550
|
-
content_type_parameters
|
1551
|
-
end
|
1552
|
-
|
1553
1522
|
# Returns the content type parameters
|
1554
1523
|
def content_type_parameters
|
1555
1524
|
has_content_type? ? header[:content_type].parameters : nil rescue nil
|
@@ -1798,12 +1767,22 @@ module Mail
|
|
1798
1767
|
self.attachments[basename] = filedata
|
1799
1768
|
end
|
1800
1769
|
|
1770
|
+
MULTIPART_CONVERSION_CONTENT_FIELDS = [ :content_description, :content_disposition, :content_transfer_encoding, :content_type ]
|
1771
|
+
private_constant :MULTIPART_CONVERSION_CONTENT_FIELDS if respond_to?(:private_constant)
|
1772
|
+
|
1801
1773
|
def convert_to_multipart
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1774
|
+
text_part = Mail::Part.new(:body => body.decoded)
|
1775
|
+
|
1776
|
+
MULTIPART_CONVERSION_CONTENT_FIELDS.each do |field_name|
|
1777
|
+
if value = send(field_name)
|
1778
|
+
writer = :"#{field_name}="
|
1779
|
+
text_part.send writer, value
|
1780
|
+
send writer, nil
|
1781
|
+
end
|
1782
|
+
end
|
1806
1783
|
text_part.charset = charset unless @defaulted_charset
|
1784
|
+
|
1785
|
+
self.body = ''
|
1807
1786
|
self.body << text_part
|
1808
1787
|
end
|
1809
1788
|
|
@@ -1818,11 +1797,6 @@ module Mail
|
|
1818
1797
|
add_required_fields
|
1819
1798
|
end
|
1820
1799
|
|
1821
|
-
def encode!
|
1822
|
-
warn("Deprecated in 1.1.0 in favour of :ready_to_send! as it is less confusing with encoding and decoding.")
|
1823
|
-
ready_to_send!
|
1824
|
-
end
|
1825
|
-
|
1826
1800
|
# Outputs an encoded string representation of the mail message including
|
1827
1801
|
# all headers, attachments, etc. This is an encoded email in US-ASCII,
|
1828
1802
|
# so it is able to be directly sent to an email server.
|
@@ -1836,7 +1810,7 @@ module Mail
|
|
1836
1810
|
|
1837
1811
|
def without_attachments!
|
1838
1812
|
if has_attachments?
|
1839
|
-
parts.
|
1813
|
+
parts.delete_attachments
|
1840
1814
|
|
1841
1815
|
reencoded = parts.empty? ? '' : body.encoded(content_transfer_encoding)
|
1842
1816
|
@body = nil # So the new parts won't be added to the existing body
|
@@ -1867,7 +1841,7 @@ module Mail
|
|
1867
1841
|
end
|
1868
1842
|
|
1869
1843
|
def self.from_yaml(str)
|
1870
|
-
hash = YAML.load(str)
|
1844
|
+
hash = Mail::YAML.load(str)
|
1871
1845
|
m = self.new(:headers => hash['headers'])
|
1872
1846
|
hash.delete('headers')
|
1873
1847
|
hash.each do |k,v|
|
@@ -1900,6 +1874,15 @@ module Mail
|
|
1900
1874
|
"#<#{self.class}:#{self.object_id}, Multipart: #{multipart?}, Headers: #{header.field_summary}>"
|
1901
1875
|
end
|
1902
1876
|
|
1877
|
+
def inspect_structure
|
1878
|
+
inspect +
|
1879
|
+
if self.multipart?
|
1880
|
+
"\n" + parts.inspect_structure
|
1881
|
+
else
|
1882
|
+
''
|
1883
|
+
end
|
1884
|
+
end
|
1885
|
+
|
1903
1886
|
def decoded
|
1904
1887
|
case
|
1905
1888
|
when self.text?
|
@@ -1984,7 +1967,7 @@ module Mail
|
|
1984
1967
|
|
1985
1968
|
private
|
1986
1969
|
|
1987
|
-
HEADER_SEPARATOR = /#{Constants::
|
1970
|
+
HEADER_SEPARATOR = /#{Constants::LAX_CRLF}#{Constants::LAX_CRLF}/
|
1988
1971
|
|
1989
1972
|
# 2.1. General Description
|
1990
1973
|
# A message consists of header fields (collectively called "the header
|
@@ -2029,7 +2012,7 @@ module Mail
|
|
2029
2012
|
|
2030
2013
|
def set_envelope_header
|
2031
2014
|
raw_string = raw_source.to_s
|
2032
|
-
if match_data = raw_string.match(/\AFrom\s(#{TEXT}
|
2015
|
+
if match_data = raw_string.match(/\AFrom\s+([^:\s]#{Constants::TEXT}*)#{Constants::LAX_CRLF}/m)
|
2033
2016
|
set_envelope(match_data[1])
|
2034
2017
|
self.raw_source = raw_string.sub(match_data[0], "")
|
2035
2018
|
end
|
@@ -2053,10 +2036,12 @@ module Mail
|
|
2053
2036
|
end
|
2054
2037
|
|
2055
2038
|
def identify_and_set_transfer_encoding
|
2056
|
-
if body
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2039
|
+
if body
|
2040
|
+
if body.multipart?
|
2041
|
+
self.content_transfer_encoding = @transport_encoding
|
2042
|
+
else
|
2043
|
+
self.content_transfer_encoding = body.negotiate_best_encoding(@transport_encoding, allowed_encodings).to_s
|
2044
|
+
end
|
2060
2045
|
end
|
2061
2046
|
end
|
2062
2047
|
|
@@ -2076,15 +2061,17 @@ module Mail
|
|
2076
2061
|
|
2077
2062
|
def add_multipart_alternate_header
|
2078
2063
|
header['content-type'] = ContentTypeField.with_boundary('multipart/alternative').value
|
2079
|
-
header['content_type'].parameters[:charset] = @charset
|
2080
2064
|
body.boundary = boundary
|
2081
2065
|
end
|
2082
2066
|
|
2083
2067
|
def add_boundary
|
2084
2068
|
unless body.boundary && boundary
|
2085
|
-
|
2069
|
+
unless header['content-type']
|
2070
|
+
_charset = charset
|
2071
|
+
header['content-type'] = 'multipart/mixed'
|
2072
|
+
header['content-type'].parameters[:charset] = _charset
|
2073
|
+
end
|
2086
2074
|
header['content-type'].parameters[:boundary] = ContentTypeField.generate_boundary
|
2087
|
-
header['content_type'].parameters[:charset] = @charset
|
2088
2075
|
body.boundary = boundary
|
2089
2076
|
end
|
2090
2077
|
end
|
@@ -2092,7 +2079,6 @@ module Mail
|
|
2092
2079
|
def add_multipart_mixed_header
|
2093
2080
|
unless header['content-type']
|
2094
2081
|
header['content-type'] = ContentTypeField.with_boundary('multipart/mixed').value
|
2095
|
-
header['content_type'].parameters[:charset] = @charset
|
2096
2082
|
body.boundary = boundary
|
2097
2083
|
end
|
2098
2084
|
end
|
@@ -2109,7 +2095,7 @@ module Mail
|
|
2109
2095
|
body_content = nil
|
2110
2096
|
|
2111
2097
|
passed_in_options.each_pair do |k,v|
|
2112
|
-
k = underscoreize(k).to_sym if k.class == String
|
2098
|
+
k = Utilities.underscoreize(k).to_sym if k.class == String
|
2113
2099
|
if k == :headers
|
2114
2100
|
self.headers(v)
|
2115
2101
|
elsif k == :body
|