mail 2.5.2 → 2.6.4
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 +124 -0
- data/CONTRIBUTING.md +21 -6
- data/Dependencies.txt +0 -1
- data/Gemfile +7 -22
- data/MIT-LICENSE +20 -0
- data/README.md +86 -31
- data/Rakefile +11 -22
- data/lib/mail/attachments_list.rb +4 -2
- data/lib/mail/body.rb +36 -11
- data/lib/mail/check_delivery_params.rb +13 -22
- data/lib/mail/configuration.rb +1 -0
- data/lib/mail/{patterns.rb → constants.rb} +29 -6
- data/lib/mail/core_extensions/smtp.rb +13 -13
- data/lib/mail/core_extensions/string/access.rb +1 -0
- data/lib/mail/core_extensions/string/multibyte.rb +1 -0
- data/lib/mail/core_extensions/string.rb +5 -17
- data/lib/mail/elements/address.rb +86 -145
- data/lib/mail/elements/address_list.rb +10 -42
- data/lib/mail/elements/content_disposition_element.rb +4 -7
- data/lib/mail/elements/content_location_element.rb +8 -11
- data/lib/mail/elements/content_transfer_encoding_element.rb +4 -10
- data/lib/mail/elements/content_type_element.rb +5 -8
- data/lib/mail/elements/date_time_element.rb +4 -7
- data/lib/mail/elements/envelope_from_element.rb +19 -13
- data/lib/mail/elements/message_ids_element.rb +8 -11
- data/lib/mail/elements/mime_version_element.rb +4 -7
- data/lib/mail/elements/phrase_list.rb +3 -7
- data/lib/mail/elements/received_element.rb +4 -7
- data/lib/mail/elements.rb +1 -0
- data/lib/mail/encodings/7bit.rb +1 -0
- data/lib/mail/encodings/8bit.rb +8 -2
- data/lib/mail/encodings/base64.rb +7 -1
- data/lib/mail/encodings/binary.rb +1 -0
- data/lib/mail/encodings/quoted_printable.rb +11 -4
- data/lib/mail/encodings/transfer_encoding.rb +27 -17
- data/lib/mail/encodings/unix_to_unix.rb +18 -0
- data/lib/mail/encodings.rb +54 -39
- data/lib/mail/envelope.rb +1 -5
- data/lib/mail/field.rb +81 -31
- data/lib/mail/field_list.rb +19 -18
- data/lib/mail/fields/bcc_field.rb +17 -5
- data/lib/mail/fields/cc_field.rb +3 -3
- data/lib/mail/fields/comments_field.rb +2 -1
- data/lib/mail/fields/common/address_container.rb +1 -0
- data/lib/mail/fields/common/common_address.rb +34 -28
- data/lib/mail/fields/common/common_date.rb +2 -8
- data/lib/mail/fields/common/common_field.rb +9 -5
- data/lib/mail/fields/common/common_message_id.rb +3 -2
- data/lib/mail/fields/common/parameter_hash.rb +4 -3
- data/lib/mail/fields/content_description_field.rb +1 -0
- data/lib/mail/fields/content_disposition_field.rb +13 -12
- data/lib/mail/fields/content_id_field.rb +4 -4
- data/lib/mail/fields/content_location_field.rb +2 -1
- data/lib/mail/fields/content_transfer_encoding_field.rb +4 -9
- data/lib/mail/fields/content_type_field.rb +4 -3
- data/lib/mail/fields/date_field.rb +16 -15
- data/lib/mail/fields/from_field.rb +3 -3
- data/lib/mail/fields/in_reply_to_field.rb +3 -1
- data/lib/mail/fields/keywords_field.rb +2 -2
- data/lib/mail/fields/message_id_field.rb +4 -4
- data/lib/mail/fields/mime_version_field.rb +3 -2
- data/lib/mail/fields/optional_field.rb +1 -0
- data/lib/mail/fields/received_field.rb +4 -3
- data/lib/mail/fields/references_field.rb +3 -1
- data/lib/mail/fields/reply_to_field.rb +3 -3
- data/lib/mail/fields/resent_bcc_field.rb +3 -3
- data/lib/mail/fields/resent_cc_field.rb +3 -3
- data/lib/mail/fields/resent_date_field.rb +2 -1
- data/lib/mail/fields/resent_from_field.rb +3 -3
- data/lib/mail/fields/resent_message_id_field.rb +1 -0
- data/lib/mail/fields/resent_sender_field.rb +4 -4
- data/lib/mail/fields/resent_to_field.rb +3 -3
- data/lib/mail/fields/return_path_field.rb +1 -1
- data/lib/mail/fields/sender_field.rb +9 -9
- data/lib/mail/fields/structured_field.rb +1 -0
- data/lib/mail/fields/subject_field.rb +1 -0
- data/lib/mail/fields/to_field.rb +3 -3
- data/lib/mail/fields/unstructured_field.rb +15 -8
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +21 -29
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +16 -1
- data/lib/mail/matchers/attachment_matchers.rb +29 -0
- data/lib/mail/matchers/has_sent_mail.rb +61 -4
- data/lib/mail/message.rb +175 -72
- data/lib/mail/multibyte/chars.rb +3 -2
- data/lib/mail/multibyte/exceptions.rb +1 -0
- data/lib/mail/multibyte/unicode.rb +22 -15
- data/lib/mail/multibyte/utils.rb +1 -0
- data/lib/mail/multibyte.rb +1 -0
- data/lib/mail/network/delivery_methods/exim.rb +3 -7
- data/lib/mail/network/delivery_methods/file_delivery.rb +2 -1
- data/lib/mail/network/delivery_methods/sendmail.rb +33 -10
- data/lib/mail/network/delivery_methods/smtp.rb +32 -34
- data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -6
- data/lib/mail/network/delivery_methods/test_mailer.rb +3 -2
- data/lib/mail/network/retriever_methods/base.rb +1 -0
- data/lib/mail/network/retriever_methods/imap.rb +19 -13
- data/lib/mail/network/retriever_methods/pop3.rb +1 -0
- data/lib/mail/network/retriever_methods/test_retriever.rb +1 -0
- data/lib/mail/network.rb +1 -0
- data/lib/mail/parsers/address_lists_parser.rb +133 -0
- data/lib/mail/parsers/content_disposition_parser.rb +68 -0
- data/lib/mail/parsers/content_location_parser.rb +36 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +34 -0
- data/lib/mail/parsers/content_type_parser.rb +67 -0
- data/lib/mail/parsers/date_time_parser.rb +39 -0
- data/lib/mail/parsers/envelope_from_parser.rb +46 -0
- data/lib/mail/parsers/message_ids_parser.rb +40 -0
- data/lib/mail/parsers/mime_version_parser.rb +42 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +36 -0
- data/lib/mail/parsers/ragel/common.rl +185 -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 +2149 -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 +40 -0
- data/lib/mail/parsers/ragel.rb +18 -0
- data/lib/mail/parsers/received_parser.rb +49 -0
- data/lib/mail/parsers.rb +27 -0
- data/lib/mail/part.rb +11 -4
- data/lib/mail/parts_list.rb +30 -10
- data/lib/mail/utilities.rb +127 -63
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +8 -15
- data/lib/mail/version_specific/ruby_1_8.rb +18 -7
- data/lib/mail/version_specific/ruby_1_9.rb +136 -32
- data/lib/mail.rb +12 -6
- metadata +115 -77
- data/lib/VERSION +0 -4
- data/lib/load_parsers.rb +0 -41
- data/lib/mail/core_extensions/nil.rb +0 -19
- data/lib/mail/core_extensions/object.rb +0 -13
- 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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mail/fields'
|
|
2
3
|
|
|
3
4
|
# encoding: utf-8
|
|
@@ -22,7 +23,7 @@ module Mail
|
|
|
22
23
|
#
|
|
23
24
|
class Field
|
|
24
25
|
|
|
25
|
-
include
|
|
26
|
+
include Utilities
|
|
26
27
|
include Comparable
|
|
27
28
|
|
|
28
29
|
STRUCTURED_FIELDS = %w[ bcc cc content-description content-disposition
|
|
@@ -67,6 +68,10 @@ module Mail
|
|
|
67
68
|
"content-location" => ContentLocationField,
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
FIELD_NAME_MAP = FIELDS_MAP.inject({}) do |map, (field, field_klass)|
|
|
72
|
+
map.update(field => field_klass::CAPITALIZED_FIELD)
|
|
73
|
+
end
|
|
74
|
+
|
|
70
75
|
# Generic Field Exception
|
|
71
76
|
class FieldError < StandardError
|
|
72
77
|
end
|
|
@@ -109,16 +114,23 @@ module Mail
|
|
|
109
114
|
# Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
|
110
115
|
def initialize(name, value = nil, charset = 'utf-8')
|
|
111
116
|
case
|
|
112
|
-
when name
|
|
113
|
-
charset = value
|
|
114
|
-
name
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
when name.index(COLON) # Field.new("field-name: field data")
|
|
118
|
+
@charset = Utilities.blank?(value) ? charset : value
|
|
119
|
+
@name = name[FIELD_PREFIX]
|
|
120
|
+
@raw_value = name
|
|
121
|
+
@value = nil
|
|
122
|
+
when Utilities.blank?(value) # Field.new("field-name")
|
|
123
|
+
@name = name
|
|
124
|
+
@value = nil
|
|
125
|
+
@raw_value = nil
|
|
126
|
+
@charset = charset
|
|
118
127
|
else # Field.new("field-name", "value")
|
|
119
|
-
|
|
128
|
+
@name = name
|
|
129
|
+
@value = value
|
|
130
|
+
@raw_value = nil
|
|
131
|
+
@charset = charset
|
|
120
132
|
end
|
|
121
|
-
|
|
133
|
+
@name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
|
|
122
134
|
end
|
|
123
135
|
|
|
124
136
|
def field=(value)
|
|
@@ -126,11 +138,12 @@ module Mail
|
|
|
126
138
|
end
|
|
127
139
|
|
|
128
140
|
def field
|
|
129
|
-
@
|
|
141
|
+
_, @value = split(@raw_value) if @raw_value && !@value
|
|
142
|
+
@field ||= create_field(@name, @value, @charset)
|
|
130
143
|
end
|
|
131
144
|
|
|
132
145
|
def name
|
|
133
|
-
|
|
146
|
+
@name
|
|
134
147
|
end
|
|
135
148
|
|
|
136
149
|
def value
|
|
@@ -138,33 +151,59 @@ module Mail
|
|
|
138
151
|
end
|
|
139
152
|
|
|
140
153
|
def value=(val)
|
|
141
|
-
create_field(name, val, charset)
|
|
154
|
+
@field = create_field(name, val, @charset)
|
|
142
155
|
end
|
|
143
156
|
|
|
144
157
|
def to_s
|
|
145
158
|
field.to_s
|
|
146
159
|
end
|
|
147
160
|
|
|
161
|
+
def inspect
|
|
162
|
+
"#<#{self.class.name} 0x#{(object_id * 2).to_s(16)} #{instance_variables.map do |ivar|
|
|
163
|
+
"#{ivar}=#{instance_variable_get(ivar).inspect}"
|
|
164
|
+
end.join(" ")}>"
|
|
165
|
+
end
|
|
166
|
+
|
|
148
167
|
def update(name, value)
|
|
149
|
-
create_field(name, value, charset)
|
|
168
|
+
@field = create_field(name, value, @charset)
|
|
150
169
|
end
|
|
151
170
|
|
|
152
171
|
def same( other )
|
|
153
|
-
|
|
172
|
+
return false unless other.kind_of?(self.class)
|
|
173
|
+
match_to_s(other.name, self.name)
|
|
154
174
|
end
|
|
155
175
|
|
|
156
|
-
|
|
176
|
+
def ==( other )
|
|
177
|
+
return false unless other.kind_of?(self.class)
|
|
178
|
+
match_to_s(other.name, self.name) && match_to_s(other.value, self.value)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def responsible_for?( val )
|
|
182
|
+
name.to_s.casecmp(val.to_s) == 0
|
|
183
|
+
end
|
|
157
184
|
|
|
158
185
|
def <=>( other )
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
186
|
+
self.field_order_id <=> other.field_order_id
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def field_order_id
|
|
190
|
+
@field_order_id ||= (FIELD_ORDER_LOOKUP[self.name.to_s.downcase] || 100)
|
|
162
191
|
end
|
|
163
192
|
|
|
164
193
|
def method_missing(name, *args, &block)
|
|
165
194
|
field.send(name, *args, &block)
|
|
166
195
|
end
|
|
167
196
|
|
|
197
|
+
if RUBY_VERSION >= '1.9.2'
|
|
198
|
+
def respond_to_missing?(method_name, include_private)
|
|
199
|
+
field.respond_to?(method_name, include_private) || super
|
|
200
|
+
end
|
|
201
|
+
else
|
|
202
|
+
def respond_to?(method_name, include_private = false)
|
|
203
|
+
field.respond_to?(method_name, include_private) || super
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
168
207
|
FIELD_ORDER = %w[ return-path received
|
|
169
208
|
resent-date resent-from resent-sender resent-to
|
|
170
209
|
resent-cc resent-bcc resent-message-id
|
|
@@ -174,37 +213,48 @@ module Mail
|
|
|
174
213
|
mime-version content-type content-transfer-encoding
|
|
175
214
|
content-location content-disposition content-description ]
|
|
176
215
|
|
|
216
|
+
FIELD_ORDER_LOOKUP = Hash[FIELD_ORDER.each_with_index.to_a]
|
|
217
|
+
|
|
177
218
|
private
|
|
178
219
|
|
|
179
220
|
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]
|
|
221
|
+
match_data = raw_field.mb_chars.match(FIELD_SPLIT)
|
|
222
|
+
[match_data[1].to_s.mb_chars.strip, match_data[2].to_s.mb_chars.strip.to_s]
|
|
182
223
|
rescue
|
|
183
224
|
STDERR.puts "WARNING: Could not parse (and so ignoring) '#{raw_field}'"
|
|
184
225
|
end
|
|
185
226
|
|
|
227
|
+
# 2.2.3. Long Header Fields
|
|
228
|
+
#
|
|
229
|
+
# The process of moving from this folded multiple-line representation
|
|
230
|
+
# of a header field to its single line representation is called
|
|
231
|
+
# "unfolding". Unfolding is accomplished by simply removing any CRLF
|
|
232
|
+
# that is immediately followed by WSP. Each header field should be
|
|
233
|
+
# treated in its unfolded form for further syntactic and semantic
|
|
234
|
+
# evaluation.
|
|
235
|
+
def unfold(string)
|
|
236
|
+
string.gsub(/[\r\n \t]+/m, ' ')
|
|
237
|
+
end
|
|
238
|
+
|
|
186
239
|
def create_field(name, value, charset)
|
|
240
|
+
value = unfold(value) if value.is_a?(String)
|
|
241
|
+
|
|
187
242
|
begin
|
|
188
|
-
|
|
243
|
+
new_field(name, value, charset)
|
|
189
244
|
rescue Mail::Field::ParseError => e
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
245
|
+
field = Mail::UnstructuredField.new(name, value)
|
|
246
|
+
field.errors << [name, value, e]
|
|
247
|
+
field
|
|
193
248
|
end
|
|
194
249
|
end
|
|
195
250
|
|
|
196
251
|
def new_field(name, value, charset)
|
|
197
252
|
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)
|
|
253
|
+
if field_klass = FIELDS_MAP[lower_case_name]
|
|
254
|
+
field_klass.new(value, charset)
|
|
204
255
|
else
|
|
205
256
|
OptionalField.new(name, value, charset)
|
|
206
257
|
end
|
|
207
|
-
|
|
208
258
|
end
|
|
209
259
|
|
|
210
260
|
end
|
data/lib/mail/field_list.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
|
|
4
5
|
# Field List class provides an enhanced array that keeps a list of
|
|
@@ -8,26 +9,26 @@ module Mail
|
|
|
8
9
|
|
|
9
10
|
include Enumerable
|
|
10
11
|
|
|
12
|
+
# Insert the field in sorted order.
|
|
13
|
+
#
|
|
14
|
+
# Heavily based on bisect.insort from Python, which is:
|
|
15
|
+
# Copyright (C) 2001-2013 Python Software Foundation.
|
|
16
|
+
# Licensed under <http://docs.python.org/license.html>
|
|
17
|
+
# From <http://hg.python.org/cpython/file/2.7/Lib/bisect.py>
|
|
11
18
|
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
|
|
19
|
+
lo = 0
|
|
20
|
+
hi = size
|
|
21
|
+
|
|
22
|
+
while lo < hi
|
|
23
|
+
mid = (lo + hi).div(2)
|
|
24
|
+
if new_field < self[mid]
|
|
25
|
+
hi = mid
|
|
26
|
+
else
|
|
27
|
+
lo = mid + 1
|
|
27
28
|
end
|
|
28
|
-
insert(insert_idx, new_field)
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
insert(lo, new_field)
|
|
30
32
|
end
|
|
31
|
-
|
|
32
33
|
end
|
|
33
|
-
end
|
|
34
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# = Blind Carbon Copy Field
|
|
4
5
|
#
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
# field in the email.
|
|
7
8
|
#
|
|
8
9
|
# Sending bcc to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a BccField as
|
|
10
|
+
# has a BccField as its field type. This includes all Mail::CommonAddress
|
|
10
11
|
# module instance metods.
|
|
11
12
|
#
|
|
12
13
|
# Only one Bcc field can appear in a header, though it can have multiple
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
#
|
|
17
18
|
# mail = Mail.new
|
|
18
19
|
# mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.bcc #=> ['
|
|
20
|
+
# mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
21
|
# mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
21
22
|
# mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
22
23
|
# mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
@@ -39,13 +40,24 @@ module Mail
|
|
|
39
40
|
def initialize(value = '', charset = 'utf-8')
|
|
40
41
|
@charset = charset
|
|
41
42
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
|
42
|
-
self.parse
|
|
43
43
|
self
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
def include_in_headers=(include_in_headers)
|
|
47
|
+
@include_in_headers = include_in_headers
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def include_in_headers
|
|
51
|
+
defined?(@include_in_headers) ? @include_in_headers : self.include_in_headers = false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Bcc field should not be :encoded by default
|
|
47
55
|
def encoded
|
|
48
|
-
|
|
56
|
+
if include_in_headers
|
|
57
|
+
do_encode(CAPITALIZED_FIELD)
|
|
58
|
+
else
|
|
59
|
+
''
|
|
60
|
+
end
|
|
49
61
|
end
|
|
50
62
|
|
|
51
63
|
def decoded
|
data/lib/mail/fields/cc_field.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# = Carbon Copy Field
|
|
4
5
|
#
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
# field in the email.
|
|
7
8
|
#
|
|
8
9
|
# Sending cc to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a CcField as
|
|
10
|
+
# has a CcField as its field type. This includes all Mail::CommonAddress
|
|
10
11
|
# module instance metods.
|
|
11
12
|
#
|
|
12
13
|
# Only one Cc field can appear in a header, though it can have multiple
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
#
|
|
17
18
|
# mail = Mail.new
|
|
18
19
|
# mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
19
|
-
# mail.cc #=> ['
|
|
20
|
+
# mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
20
21
|
# mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
21
22
|
# mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
22
23
|
# mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
@@ -39,7 +40,6 @@ module Mail
|
|
|
39
40
|
def initialize(value = nil, charset = 'utf-8')
|
|
40
41
|
self.charset = charset
|
|
41
42
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
|
42
|
-
self.parse
|
|
43
43
|
self
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# = Comments Field
|
|
4
5
|
#
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
# header field in the email.
|
|
7
8
|
#
|
|
8
9
|
# Sending comments to a mail message will instantiate a Mail::Field object that
|
|
9
|
-
# has a CommentsField as
|
|
10
|
+
# has a CommentsField as its field type.
|
|
10
11
|
#
|
|
11
12
|
# An email header can have as many comments fields as it wants. There is no upper
|
|
12
13
|
# limit, the comments field is also optional (that is, no comment is needed)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'mail/fields/common/address_container'
|
|
3
4
|
|
|
4
5
|
module Mail
|
|
5
6
|
module CommonAddress # :nodoc:
|
|
6
7
|
|
|
7
8
|
def parse(val = value)
|
|
8
|
-
unless
|
|
9
|
-
@
|
|
9
|
+
unless Utilities.blank?(val)
|
|
10
|
+
@address_list = AddressList.new(encode_if_needed(val))
|
|
10
11
|
else
|
|
11
12
|
nil
|
|
12
13
|
end
|
|
@@ -20,54 +21,60 @@ module Mail
|
|
|
20
21
|
Encodings.address_encode(val, charset)
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
# Allows you to iterate through each address object in the
|
|
24
|
+
# Allows you to iterate through each address object in the address_list
|
|
24
25
|
def each
|
|
25
|
-
|
|
26
|
+
address_list.addresses.each do |address|
|
|
26
27
|
yield(address)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# Returns the address string of all the addresses in the address list
|
|
31
32
|
def addresses
|
|
32
|
-
list =
|
|
33
|
+
list = address_list.addresses.map { |a| a.address }
|
|
33
34
|
Mail::AddressContainer.new(self, list)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
# Returns the formatted string of all the addresses in the address list
|
|
37
38
|
def formatted
|
|
38
|
-
list =
|
|
39
|
+
list = address_list.addresses.map { |a| a.format }
|
|
39
40
|
Mail::AddressContainer.new(self, list)
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
# Returns the display name of all the addresses in the address list
|
|
43
44
|
def display_names
|
|
44
|
-
list =
|
|
45
|
+
list = address_list.addresses.map { |a| a.display_name }
|
|
45
46
|
Mail::AddressContainer.new(self, list)
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
# Returns the actual address objects in the address list
|
|
49
50
|
def addrs
|
|
50
|
-
list =
|
|
51
|
+
list = address_list.addresses
|
|
51
52
|
Mail::AddressContainer.new(self, list)
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
# Returns a hash of group name => address strings for the address list
|
|
55
56
|
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
|
|
57
|
+
address_list.addresses_grouped_by_group
|
|
61
58
|
end
|
|
62
59
|
|
|
63
60
|
# Returns the addresses that are part of groups
|
|
64
61
|
def group_addresses
|
|
65
|
-
|
|
62
|
+
decoded_group_addresses
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns a list of decoded group addresses
|
|
66
|
+
def decoded_group_addresses
|
|
67
|
+
groups.map { |k,v| v.map { |a| a.decoded } }.flatten
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns a list of encoded group addresses
|
|
71
|
+
def encoded_group_addresses
|
|
72
|
+
groups.map { |k,v| v.map { |a| a.encoded } }.flatten
|
|
66
73
|
end
|
|
67
74
|
|
|
68
75
|
# Returns the name of all the groups in a string
|
|
69
76
|
def group_names # :nodoc:
|
|
70
|
-
|
|
77
|
+
address_list.group_names
|
|
71
78
|
end
|
|
72
79
|
|
|
73
80
|
def default
|
|
@@ -78,10 +85,10 @@ module Mail
|
|
|
78
85
|
case
|
|
79
86
|
when val.nil?
|
|
80
87
|
raise ArgumentError, "Need to pass an address to <<"
|
|
81
|
-
when
|
|
88
|
+
when Utilities.blank?(val)
|
|
82
89
|
parse(encoded)
|
|
83
90
|
else
|
|
84
|
-
self.value = [self.value, val].reject {|a|
|
|
91
|
+
self.value = [self.value, val].reject {|a| Utilities.blank?(a) }.join(", ")
|
|
85
92
|
end
|
|
86
93
|
end
|
|
87
94
|
|
|
@@ -93,34 +100,33 @@ module Mail
|
|
|
93
100
|
private
|
|
94
101
|
|
|
95
102
|
def do_encode(field_name)
|
|
96
|
-
return '' if
|
|
97
|
-
address_array =
|
|
103
|
+
return '' if Utilities.blank?(value)
|
|
104
|
+
address_array = address_list.addresses.reject { |a| encoded_group_addresses.include?(a.encoded) }.compact.map { |a| a.encoded }
|
|
98
105
|
address_text = address_array.join(", \r\n\s")
|
|
99
106
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.encoded }.join(", \r\n\s")};" }
|
|
100
107
|
group_text = group_array.join(" \r\n\s")
|
|
101
|
-
return_array = [address_text, group_text].reject { |a|
|
|
108
|
+
return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
|
|
102
109
|
"#{field_name}: #{return_array.join(", \r\n\s")}\r\n"
|
|
103
110
|
end
|
|
104
111
|
|
|
105
112
|
def do_decode
|
|
106
|
-
return nil if
|
|
107
|
-
address_array =
|
|
113
|
+
return nil if Utilities.blank?(value)
|
|
114
|
+
address_array = address_list.addresses.reject { |a| decoded_group_addresses.include?(a.decoded) }.map { |a| a.decoded }
|
|
108
115
|
address_text = address_array.join(", ")
|
|
109
116
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.decoded }.join(", ")};" }
|
|
110
117
|
group_text = group_array.join(" ")
|
|
111
|
-
return_array = [address_text, group_text].reject { |a|
|
|
118
|
+
return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
|
|
112
119
|
return_array.join(", ")
|
|
113
120
|
end
|
|
114
121
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
@tree ||= AddressList.new(value)
|
|
122
|
+
def address_list # :nodoc:
|
|
123
|
+
@address_list ||= AddressList.new(value)
|
|
118
124
|
end
|
|
119
125
|
|
|
120
126
|
def get_group_addresses(group_list)
|
|
121
127
|
if group_list.respond_to?(:addresses)
|
|
122
|
-
group_list.addresses.map do |
|
|
123
|
-
Mail::Address.new(
|
|
128
|
+
group_list.addresses.map do |address|
|
|
129
|
+
Mail::Address.new(address)
|
|
124
130
|
end
|
|
125
131
|
else
|
|
126
132
|
[]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
module CommonDate # :nodoc:
|
|
4
5
|
# Returns a date time object of the parsed date
|
|
@@ -11,9 +12,8 @@ module Mail
|
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
def parse(val = value)
|
|
14
|
-
unless
|
|
15
|
+
unless Utilities.blank?(val)
|
|
15
16
|
@element = Mail::DateTimeElement.new(val)
|
|
16
|
-
@tree = @element.tree
|
|
17
17
|
else
|
|
18
18
|
nil
|
|
19
19
|
end
|
|
@@ -32,11 +32,5 @@ module Mail
|
|
|
32
32
|
def element
|
|
33
33
|
@element ||= Mail::DateTimeElement.new(value)
|
|
34
34
|
end
|
|
35
|
-
|
|
36
|
-
# Returns the syntax tree of the Date
|
|
37
|
-
def tree
|
|
38
|
-
@tree ||= element.tree
|
|
39
|
-
end
|
|
40
|
-
|
|
41
35
|
end
|
|
42
36
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
module CommonField # :nodoc:
|
|
5
|
+
include Mail::Constants
|
|
4
6
|
|
|
5
7
|
def name=(value)
|
|
6
8
|
@name = value
|
|
@@ -22,7 +24,7 @@ module Mail
|
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def to_s
|
|
25
|
-
decoded
|
|
27
|
+
decoded.to_s
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def default
|
|
@@ -43,15 +45,17 @@ module Mail
|
|
|
43
45
|
if value.is_a?(Array)
|
|
44
46
|
value
|
|
45
47
|
else
|
|
46
|
-
value.to_s.
|
|
48
|
+
value.to_s.sub(/\A#{field_name}:\s+/i, EMPTY)
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
|
52
|
+
FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
|
|
50
53
|
def ensure_filename_quoted(value)
|
|
51
|
-
if
|
|
52
|
-
value.
|
|
54
|
+
if value.is_a?(String)
|
|
55
|
+
value.sub FILENAME_RE, '\1="\2"'
|
|
56
|
+
else
|
|
57
|
+
value
|
|
53
58
|
end
|
|
54
59
|
end
|
|
55
|
-
|
|
56
60
|
end
|
|
57
61
|
end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
module CommonMessageId # :nodoc:
|
|
4
5
|
def element
|
|
5
|
-
@element ||= Mail::MessageIdsElement.new(value) unless
|
|
6
|
+
@element ||= Mail::MessageIdsElement.new(value) unless Utilities.blank?(value)
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def parse(val = value)
|
|
9
|
-
unless
|
|
10
|
+
unless Utilities.blank?(val)
|
|
10
11
|
@element = Mail::MessageIdsElement.new(val)
|
|
11
12
|
else
|
|
12
13
|
nil
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
|
|
4
5
|
# ParameterHash is an intelligent Hash that allows you to add
|
|
@@ -18,7 +19,7 @@ module Mail
|
|
|
18
19
|
exact = nil
|
|
19
20
|
each do |k,v|
|
|
20
21
|
if k =~ /^#{key_pattern}(\*|$)/i
|
|
21
|
-
if $1 ==
|
|
22
|
+
if $1 == ASTERISK
|
|
22
23
|
pairs << [k, v]
|
|
23
24
|
else
|
|
24
25
|
exact = k
|
|
@@ -40,7 +41,7 @@ module Mail
|
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
def encoded
|
|
43
|
-
map.
|
|
44
|
+
map.sort_by { |a| a.first.to_s }.map! do |key_name, value|
|
|
44
45
|
unless value.ascii_only?
|
|
45
46
|
value = Mail::Encodings.param_encode(value)
|
|
46
47
|
key_name = "#{key_name}*"
|
|
@@ -50,7 +51,7 @@ module Mail
|
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
def decoded
|
|
53
|
-
map.
|
|
54
|
+
map.sort_by { |a| a.first.to_s }.map! do |key_name, value|
|
|
54
55
|
%Q{#{key_name}=#{quote_token(value)}}
|
|
55
56
|
end.join("; ")
|
|
56
57
|
end
|