mail 2.5.5 → 2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +170 -108
- data/lib/mail/attachments_list.rb +13 -10
- data/lib/mail/body.rb +105 -91
- data/lib/mail/check_delivery_params.rb +30 -22
- data/lib/mail/configuration.rb +3 -0
- data/lib/mail/constants.rb +79 -0
- data/lib/mail/elements/address.rb +118 -174
- data/lib/mail/elements/address_list.rb +16 -56
- data/lib/mail/elements/content_disposition_element.rb +12 -22
- data/lib/mail/elements/content_location_element.rb +9 -17
- data/lib/mail/elements/content_transfer_encoding_element.rb +8 -19
- data/lib/mail/elements/content_type_element.rb +20 -30
- data/lib/mail/elements/date_time_element.rb +10 -21
- data/lib/mail/elements/envelope_from_element.rb +23 -31
- data/lib/mail/elements/message_ids_element.rb +22 -20
- data/lib/mail/elements/mime_version_element.rb +10 -21
- data/lib/mail/elements/phrase_list.rb +13 -15
- data/lib/mail/elements/received_element.rb +26 -21
- data/lib/mail/elements.rb +1 -0
- data/lib/mail/encodings/7bit.rb +10 -14
- data/lib/mail/encodings/8bit.rb +5 -18
- data/lib/mail/encodings/base64.rb +15 -10
- data/lib/mail/encodings/binary.rb +4 -22
- data/lib/mail/encodings/identity.rb +24 -0
- data/lib/mail/encodings/quoted_printable.rb +13 -7
- data/lib/mail/encodings/transfer_encoding.rb +47 -28
- data/lib/mail/encodings/unix_to_unix.rb +20 -0
- data/lib/mail/encodings.rb +102 -93
- data/lib/mail/envelope.rb +12 -19
- data/lib/mail/field.rb +143 -71
- data/lib/mail/field_list.rb +73 -19
- data/lib/mail/fields/bcc_field.rb +42 -48
- data/lib/mail/fields/cc_field.rb +29 -50
- data/lib/mail/fields/comments_field.rb +28 -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 +8 -14
- data/lib/mail/fields/content_disposition_field.rb +20 -44
- data/lib/mail/fields/content_id_field.rb +25 -51
- data/lib/mail/fields/content_location_field.rb +12 -25
- data/lib/mail/fields/content_transfer_encoding_field.rb +31 -36
- data/lib/mail/fields/content_type_field.rb +51 -80
- data/lib/mail/fields/date_field.rb +24 -52
- data/lib/mail/fields/from_field.rb +29 -50
- data/lib/mail/fields/in_reply_to_field.rb +39 -49
- data/lib/mail/fields/keywords_field.rb +19 -32
- data/lib/mail/fields/message_id_field.rb +26 -71
- data/lib/mail/fields/mime_version_field.rb +20 -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 +10 -7
- data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +16 -13
- data/lib/mail/fields/received_field.rb +44 -57
- data/lib/mail/fields/references_field.rb +36 -49
- data/lib/mail/fields/reply_to_field.rb +29 -50
- data/lib/mail/fields/resent_bcc_field.rb +29 -50
- data/lib/mail/fields/resent_cc_field.rb +29 -50
- data/lib/mail/fields/resent_date_field.rb +6 -30
- data/lib/mail/fields/resent_from_field.rb +29 -50
- data/lib/mail/fields/resent_message_id_field.rb +6 -29
- data/lib/mail/fields/resent_sender_field.rb +28 -57
- data/lib/mail/fields/resent_to_field.rb +29 -50
- data/lib/mail/fields/return_path_field.rb +51 -55
- data/lib/mail/fields/sender_field.rb +35 -56
- data/lib/mail/fields/structured_field.rb +4 -30
- data/lib/mail/fields/subject_field.rb +10 -11
- data/lib/mail/fields/to_field.rb +29 -50
- data/lib/mail/fields/unstructured_field.rb +43 -51
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +78 -129
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +18 -11
- data/lib/mail/matchers/attachment_matchers.rb +44 -0
- data/lib/mail/matchers/has_sent_mail.rb +81 -4
- data/lib/mail/message.rb +142 -139
- data/lib/mail/multibyte/chars.rb +24 -180
- data/lib/mail/multibyte/unicode.rb +32 -27
- data/lib/mail/multibyte/utils.rb +27 -43
- data/lib/mail/multibyte.rb +56 -16
- data/lib/mail/network/delivery_methods/exim.rb +6 -4
- data/lib/mail/network/delivery_methods/file_delivery.rb +12 -10
- data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +63 -21
- data/lib/mail/network/delivery_methods/smtp.rb +76 -50
- data/lib/mail/network/delivery_methods/smtp_connection.rb +4 -4
- data/lib/mail/network/delivery_methods/test_mailer.rb +5 -2
- data/lib/mail/network/retriever_methods/base.rb +9 -8
- data/lib/mail/network/retriever_methods/imap.rb +37 -18
- data/lib/mail/network/retriever_methods/pop3.rb +6 -3
- data/lib/mail/network/retriever_methods/test_retriever.rb +4 -2
- data/lib/mail/network.rb +2 -0
- data/lib/mail/parser_tools.rb +15 -0
- data/lib/mail/parsers/address_lists_parser.rb +33242 -0
- data/lib/mail/parsers/address_lists_parser.rl +179 -0
- data/lib/mail/parsers/content_disposition_parser.rb +901 -0
- data/lib/mail/parsers/content_disposition_parser.rl +89 -0
- data/lib/mail/parsers/content_location_parser.rb +822 -0
- data/lib/mail/parsers/content_location_parser.rl +78 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +522 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
- data/lib/mail/parsers/content_type_parser.rb +1048 -0
- data/lib/mail/parsers/content_type_parser.rl +90 -0
- data/lib/mail/parsers/date_time_parser.rb +891 -0
- data/lib/mail/parsers/date_time_parser.rl +69 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3675 -0
- data/lib/mail/parsers/envelope_from_parser.rl +89 -0
- data/lib/mail/parsers/message_ids_parser.rb +5161 -0
- data/lib/mail/parsers/message_ids_parser.rl +93 -0
- data/lib/mail/parsers/mime_version_parser.rb +513 -0
- data/lib/mail/parsers/mime_version_parser.rl +68 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +884 -0
- data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
- data/lib/mail/parsers/received_parser.rb +8782 -0
- data/lib/mail/parsers/received_parser.rl +91 -0
- data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
- data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
- data/lib/mail/parsers/rfc2045_mime.rl +16 -0
- data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
- data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
- data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
- data/lib/mail/parsers/rfc5322.rl +74 -0
- data/lib/mail/parsers/rfc5322_address.rl +72 -0
- data/lib/mail/parsers/rfc5322_date_time.rl +37 -0
- data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
- data/lib/mail/parsers.rb +13 -0
- data/lib/mail/part.rb +11 -12
- data/lib/mail/parts_list.rb +90 -14
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +415 -76
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +8 -15
- data/lib/mail/yaml.rb +30 -0
- data/lib/mail.rb +9 -32
- metadata +127 -79
- data/CHANGELOG.rdoc +0 -742
- data/CONTRIBUTING.md +0 -45
- data/Dependencies.txt +0 -3
- data/Gemfile +0 -32
- data/Rakefile +0 -21
- data/TODO.rdoc +0 -9
- data/lib/VERSION +0 -4
- data/lib/load_parsers.rb +0 -35
- data/lib/mail/core_extensions/nil.rb +0 -19
- data/lib/mail/core_extensions/object.rb +0 -13
- data/lib/mail/core_extensions/smtp.rb +0 -24
- data/lib/mail/core_extensions/string/access.rb +0 -145
- data/lib/mail/core_extensions/string/multibyte.rb +0 -78
- data/lib/mail/core_extensions/string.rb +0 -33
- data/lib/mail/fields/common/address_container.rb +0 -16
- data/lib/mail/fields/common/common_address.rb +0 -140
- data/lib/mail/fields/common/common_date.rb +0 -42
- data/lib/mail/fields/common/common_field.rb +0 -57
- data/lib/mail/fields/common/common_message_id.rb +0 -48
- data/lib/mail/multibyte/exceptions.rb +0 -8
- 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 -201
- data/lib/mail/parsers/content_transfer_encoding.treetop +0 -18
- data/lib/mail/parsers/content_type.rb +0 -971
- 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 -421
- data/lib/mail/parsers/rfc2045.treetop +0 -35
- data/lib/mail/parsers/rfc2822.rb +0 -5397
- data/lib/mail/parsers/rfc2822.treetop +0 -408
- data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
- data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
- data/lib/mail/patterns.rb +0 -35
- data/lib/mail/version_specific/ruby_1_8.rb +0 -119
- data/lib/mail/version_specific/ruby_1_9.rb +0 -147
- data/lib/tasks/corpus.rake +0 -125
- data/lib/tasks/treetop.rake +0 -10
data/lib/mail/field.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'mail/fields'
|
3
|
+
require 'mail/constants'
|
2
4
|
|
3
5
|
# encoding: utf-8
|
4
6
|
module Mail
|
@@ -21,8 +23,6 @@ module Mail
|
|
21
23
|
# sections 3 and 4 of this standard.
|
22
24
|
#
|
23
25
|
class Field
|
24
|
-
|
25
|
-
include Patterns
|
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::NAME)
|
72
|
+
end
|
73
|
+
|
70
74
|
# Generic Field Exception
|
71
75
|
class FieldError < StandardError
|
72
76
|
end
|
@@ -78,9 +82,31 @@ module Mail
|
|
78
82
|
|
79
83
|
def initialize(element, value, reason)
|
80
84
|
@element = element
|
81
|
-
@value = value
|
82
|
-
@reason = reason
|
83
|
-
super("#{element} can not parse |#{value}
|
85
|
+
@value = to_utf8(value)
|
86
|
+
@reason = to_utf8(reason)
|
87
|
+
super("#{@element} can not parse |#{@value}|: #{@reason}")
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def to_utf8(text)
|
92
|
+
if text.respond_to?(:force_encoding)
|
93
|
+
text.dup.force_encoding(Encoding::UTF_8)
|
94
|
+
else
|
95
|
+
text
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class NilParseError < ParseError #:nodoc:
|
101
|
+
def initialize(element)
|
102
|
+
super element, nil, 'nil is invalid'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class IncompleteParseError < ParseError #:nodoc:
|
107
|
+
def initialize(element, original_text, unparsed_index)
|
108
|
+
parsed_text = to_utf8(original_text[0...unparsed_index])
|
109
|
+
super element, original_text, "Only able to parse up to #{parsed_text.inspect}"
|
84
110
|
end
|
85
111
|
end
|
86
112
|
|
@@ -88,49 +114,81 @@ module Mail
|
|
88
114
|
class SyntaxError < FieldError #:nodoc:
|
89
115
|
end
|
90
116
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
117
|
+
class << self
|
118
|
+
# Parse a field from a raw header line:
|
119
|
+
#
|
120
|
+
# Mail::Field.parse("field-name: field data")
|
121
|
+
# # => #<Mail::Field …>
|
122
|
+
def parse(field, charset = 'utf-8')
|
123
|
+
name, value = split(field)
|
124
|
+
if name && value
|
125
|
+
new name, value, charset
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def split(raw_field) #:nodoc:
|
130
|
+
if raw_field.index(Constants::COLON)
|
131
|
+
name, value = raw_field.split(Constants::COLON, 2)
|
132
|
+
name.rstrip!
|
133
|
+
if name =~ /\A#{Constants::FIELD_NAME}\z/
|
134
|
+
[ name.rstrip, value.strip ]
|
135
|
+
else
|
136
|
+
Kernel.warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: invalid header name syntax: #{name.inspect}"
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
else
|
140
|
+
raw_field.strip
|
141
|
+
end
|
142
|
+
rescue => error
|
143
|
+
warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: #{error.class}: #{error.message}"
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def field_class_for(name) #:nodoc:
|
148
|
+
FIELDS_MAP[name.to_s.downcase]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
attr_reader :unparsed_value
|
153
|
+
|
154
|
+
# Create a field by name and optional value:
|
98
155
|
#
|
99
|
-
#
|
156
|
+
# Mail::Field.new("field-name", "value")
|
157
|
+
# # => #<Mail::Field …>
|
100
158
|
#
|
101
|
-
#
|
159
|
+
# Values that aren't strings or arrays are coerced to Strings with `#to_s`.
|
102
160
|
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
# it will be passed through as is, for example, content-type
|
106
|
-
# field can accept an array with the type and a hash of
|
107
|
-
# parameters:
|
161
|
+
# Mail::Field.new("field-name", 1234)
|
162
|
+
# # => #<Mail::Field …>
|
108
163
|
#
|
109
|
-
# Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
164
|
+
# Mail::Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
165
|
+
# # => #<Mail::Field …>
|
110
166
|
def initialize(name, value = nil, charset = 'utf-8')
|
111
167
|
case
|
112
|
-
when name
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
else
|
119
|
-
|
168
|
+
when name.index(Constants::COLON)
|
169
|
+
raise ArgumentError, 'Passing an unparsed header field to Mail::Field.new is not supported in Mail 2.8.0+. Use Mail::Field.parse instead.'
|
170
|
+
when Utilities.blank?(value)
|
171
|
+
@name = name
|
172
|
+
@unparsed_value = nil
|
173
|
+
@charset = charset
|
174
|
+
else
|
175
|
+
@name = name
|
176
|
+
@unparsed_value = value
|
177
|
+
@charset = charset
|
120
178
|
end
|
121
|
-
|
179
|
+
@name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
|
122
180
|
end
|
123
181
|
|
124
|
-
def field=(
|
125
|
-
@field =
|
182
|
+
def field=(field)
|
183
|
+
@field = field
|
126
184
|
end
|
127
185
|
|
128
186
|
def field
|
129
|
-
@field
|
187
|
+
@field ||= create_field(@name, @unparsed_value, @charset)
|
130
188
|
end
|
131
189
|
|
132
190
|
def name
|
133
|
-
|
191
|
+
@name
|
134
192
|
end
|
135
193
|
|
136
194
|
def value
|
@@ -138,74 +196,88 @@ module Mail
|
|
138
196
|
end
|
139
197
|
|
140
198
|
def value=(val)
|
141
|
-
create_field(name, val, charset)
|
199
|
+
@field = create_field(name, val, @charset)
|
142
200
|
end
|
143
201
|
|
144
202
|
def to_s
|
145
203
|
field.to_s
|
146
204
|
end
|
147
205
|
|
148
|
-
def
|
149
|
-
|
206
|
+
def inspect
|
207
|
+
"#<#{self.class.name} 0x#{(object_id * 2).to_s(16)} #{instance_variables.map do |ivar|
|
208
|
+
"#{ivar}=#{instance_variable_get(ivar).inspect}"
|
209
|
+
end.join(" ")}>"
|
210
|
+
end
|
211
|
+
|
212
|
+
def same(other)
|
213
|
+
other.kind_of?(self.class) && Utilities.match_to_s(other.name, name)
|
150
214
|
end
|
151
215
|
|
152
|
-
def
|
153
|
-
match_to_s(other.
|
216
|
+
def ==(other)
|
217
|
+
same(other) && Utilities.match_to_s(other.value, value)
|
154
218
|
end
|
155
219
|
|
156
|
-
|
220
|
+
def responsible_for?(field_name)
|
221
|
+
name.to_s.casecmp(field_name.to_s) == 0
|
222
|
+
end
|
157
223
|
|
158
|
-
def <=>(
|
159
|
-
|
224
|
+
def <=>(other)
|
225
|
+
field_order_id <=> other.field_order_id
|
160
226
|
end
|
161
227
|
|
162
228
|
def field_order_id
|
163
|
-
@field_order_id ||= (
|
229
|
+
@field_order_id ||= FIELD_ORDER_LOOKUP.fetch(self.name.to_s.downcase, 100)
|
164
230
|
end
|
165
231
|
|
166
232
|
def method_missing(name, *args, &block)
|
167
233
|
field.send(name, *args, &block)
|
168
234
|
end
|
169
235
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
date from sender reply-to to cc bcc
|
174
|
-
message-id in-reply-to references
|
175
|
-
subject comments keywords
|
176
|
-
mime-version content-type content-transfer-encoding
|
177
|
-
content-location content-disposition content-description ]
|
236
|
+
def respond_to_missing?(method_name, include_private)
|
237
|
+
field.respond_to?(method_name, include_private) || super
|
238
|
+
end
|
178
239
|
|
179
|
-
FIELD_ORDER_LOOKUP = Hash[
|
240
|
+
FIELD_ORDER_LOOKUP = Hash[%w[
|
241
|
+
return-path received
|
242
|
+
resent-date resent-from resent-sender resent-to
|
243
|
+
resent-cc resent-bcc resent-message-id
|
244
|
+
date from sender reply-to to cc bcc
|
245
|
+
message-id in-reply-to references
|
246
|
+
subject comments keywords
|
247
|
+
mime-version content-type content-transfer-encoding
|
248
|
+
content-location content-disposition content-description
|
249
|
+
].each_with_index.to_a]
|
180
250
|
|
181
251
|
private
|
182
252
|
|
183
|
-
def split(raw_field)
|
184
|
-
match_data = raw_field.mb_chars.match(FIELD_SPLIT)
|
185
|
-
[match_data[1].to_s.mb_chars.strip, match_data[2].to_s.mb_chars.strip]
|
186
|
-
rescue
|
187
|
-
STDERR.puts "WARNING: Could not parse (and so ignoring) '#{raw_field}'"
|
188
|
-
end
|
189
|
-
|
190
253
|
def create_field(name, value, charset)
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
self.field
|
197
|
-
end
|
254
|
+
parse_field(name, value, charset)
|
255
|
+
rescue Mail::Field::ParseError => e
|
256
|
+
field = Mail::UnstructuredField.new(name, value)
|
257
|
+
field.errors << [name, value, e]
|
258
|
+
field
|
198
259
|
end
|
199
260
|
|
200
|
-
def
|
201
|
-
|
202
|
-
|
203
|
-
|
261
|
+
def parse_field(name, value, charset)
|
262
|
+
value = unfold(value) if value.is_a?(String)
|
263
|
+
|
264
|
+
if klass = self.class.field_class_for(name)
|
265
|
+
klass.parse(value, charset)
|
204
266
|
else
|
205
|
-
OptionalField.
|
267
|
+
OptionalField.parse(name, value, charset)
|
206
268
|
end
|
207
269
|
end
|
208
270
|
|
271
|
+
# 2.2.3. Long Header Fields
|
272
|
+
#
|
273
|
+
# The process of moving from this folded multiple-line representation
|
274
|
+
# of a header field to its single line representation is called
|
275
|
+
# "unfolding". Unfolding is accomplished by simply removing any CRLF
|
276
|
+
# that is immediately followed by WSP. Each header field should be
|
277
|
+
# treated in its unfolded form for further syntactic and semantic
|
278
|
+
# evaluation.
|
279
|
+
def unfold(string)
|
280
|
+
string.gsub(Constants::UNFOLD_WS, '\1')
|
281
|
+
end
|
209
282
|
end
|
210
|
-
|
211
283
|
end
|
data/lib/mail/field_list.rb
CHANGED
@@ -1,33 +1,87 @@
|
|
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
|
5
6
|
# email fields in order. And allows you to insert new fields without
|
6
7
|
# having to worry about the order they will appear in.
|
7
8
|
class FieldList < Array
|
9
|
+
def has_field?(field_name)
|
10
|
+
any? { |f| f.responsible_for? field_name }
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_field(field_name)
|
14
|
+
fields = select_fields(field_name)
|
15
|
+
case fields.size
|
16
|
+
when 0; nil
|
17
|
+
when 1; fields.first
|
18
|
+
else fields
|
19
|
+
end
|
20
|
+
end
|
8
21
|
|
9
|
-
|
22
|
+
def add_field(field)
|
23
|
+
if field.singular?
|
24
|
+
replace_field field
|
25
|
+
else
|
26
|
+
insert_field field
|
27
|
+
end
|
28
|
+
end
|
29
|
+
alias_method :<<, :add_field
|
10
30
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
31
|
+
def replace_field(field)
|
32
|
+
if first_offset = index { |f| f.responsible_for? field.name }
|
33
|
+
delete_field field.name
|
34
|
+
insert first_offset, field
|
15
35
|
else
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
36
|
+
insert_field field
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Insert the field in sorted order.
|
41
|
+
#
|
42
|
+
# Heavily based on bisect.insort from Python, which is:
|
43
|
+
# Copyright (C) 2001-2013 Python Software Foundation.
|
44
|
+
# Licensed under <http://docs.python.org/license.html>
|
45
|
+
# From <http://hg.python.org/cpython/file/2.7/Lib/bisect.py>
|
46
|
+
def insert_field(field)
|
47
|
+
lo, hi = 0, size
|
48
|
+
while lo < hi
|
49
|
+
mid = (lo + hi).div(2)
|
50
|
+
if field < self[mid]
|
51
|
+
hi = mid
|
52
|
+
else
|
53
|
+
lo = mid + 1
|
27
54
|
end
|
28
|
-
|
55
|
+
end
|
56
|
+
|
57
|
+
insert lo, field
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete_field(name)
|
61
|
+
delete_if { |f| f.responsible_for? name }
|
62
|
+
end
|
63
|
+
|
64
|
+
def summary
|
65
|
+
map { |f| "<#{f.name}: #{f.value}>" }.join(", ")
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def select_fields(field_name)
|
71
|
+
fields = select { |f| f.responsible_for? field_name }
|
72
|
+
if fields.size > 1 && singular?(field_name)
|
73
|
+
Array(fields.detect { |f| f.errors.size == 0 } || fields.first)
|
74
|
+
else
|
75
|
+
fields
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def singular?(field_name)
|
80
|
+
if klass = Mail::Field.field_class_for(field_name)
|
81
|
+
klass.singular?
|
82
|
+
else
|
83
|
+
false
|
29
84
|
end
|
30
85
|
end
|
31
|
-
|
32
86
|
end
|
33
|
-
end
|
87
|
+
end
|
@@ -1,56 +1,50 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
#
|
5
|
-
# The Bcc field inherits from StructuredField and handles the Bcc: header
|
6
|
-
# field in the email.
|
7
|
-
#
|
8
|
-
# Sending bcc to a mail message will instantiate a Mail::Field object that
|
9
|
-
# has a BccField as its field type. This includes all Mail::CommonAddress
|
10
|
-
# module instance metods.
|
11
|
-
#
|
12
|
-
# Only one Bcc field can appear in a header, though it can have multiple
|
13
|
-
# addresses and groups of addresses.
|
14
|
-
#
|
15
|
-
# == Examples:
|
16
|
-
#
|
17
|
-
# mail = Mail.new
|
18
|
-
# mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
19
|
-
# mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
20
|
-
# mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
21
|
-
# mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
22
|
-
# mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
23
|
-
#
|
24
|
-
# mail[:bcc].encoded #=> '' # Bcc field does not get output into an email
|
25
|
-
# mail[:bcc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
26
|
-
# mail[:bcc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
27
|
-
# mail[:bcc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
28
|
-
#
|
29
|
-
require 'mail/fields/common/common_address'
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/common_address_field'
|
30
4
|
|
31
5
|
module Mail
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
6
|
+
# = Blind Carbon Copy Field
|
7
|
+
#
|
8
|
+
# The Bcc field inherits from StructuredField and handles the Bcc: header
|
9
|
+
# field in the email.
|
10
|
+
#
|
11
|
+
# Sending bcc to a mail message will instantiate a Mail::Field object that
|
12
|
+
# has a BccField as its field type. This includes all Mail::CommonAddress
|
13
|
+
# module instance metods.
|
14
|
+
#
|
15
|
+
# Only one Bcc field can appear in a header, though it can have multiple
|
16
|
+
# addresses and groups of addresses.
|
17
|
+
#
|
18
|
+
# == Examples:
|
19
|
+
#
|
20
|
+
# mail = Mail.new
|
21
|
+
# mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
22
|
+
# mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
23
|
+
# mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
24
|
+
# mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
25
|
+
# mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
26
|
+
#
|
27
|
+
# mail[:bcc].encoded #=> '' # Bcc field does not get output into an email
|
28
|
+
# mail[:bcc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
29
|
+
# mail[:bcc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
30
|
+
# mail[:bcc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
31
|
+
class BccField < CommonAddressField #:nodoc:
|
32
|
+
NAME = 'Bcc'
|
33
|
+
|
34
|
+
attr_accessor :include_in_headers
|
35
|
+
|
36
|
+
def initialize(value = nil, charset = nil)
|
37
|
+
super
|
38
|
+
self.include_in_headers = false
|
44
39
|
end
|
45
|
-
|
46
|
-
# Bcc field should
|
40
|
+
|
41
|
+
# Bcc field should not be :encoded by default
|
47
42
|
def encoded
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
43
|
+
if include_in_headers
|
44
|
+
super
|
45
|
+
else
|
46
|
+
''
|
47
|
+
end
|
53
48
|
end
|
54
|
-
|
55
49
|
end
|
56
50
|
end
|
data/lib/mail/fields/cc_field.rb
CHANGED
@@ -1,55 +1,34 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
#
|
5
|
-
# The Cc field inherits from StructuredField and handles the Cc: header
|
6
|
-
# field in the email.
|
7
|
-
#
|
8
|
-
# Sending cc to a mail message will instantiate a Mail::Field object that
|
9
|
-
# has a CcField as its field type. This includes all Mail::CommonAddress
|
10
|
-
# module instance metods.
|
11
|
-
#
|
12
|
-
# Only one Cc field can appear in a header, though it can have multiple
|
13
|
-
# addresses and groups of addresses.
|
14
|
-
#
|
15
|
-
# == Examples:
|
16
|
-
#
|
17
|
-
# mail = Mail.new
|
18
|
-
# mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
19
|
-
# mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
20
|
-
# mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
21
|
-
# mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
22
|
-
# mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
23
|
-
#
|
24
|
-
# mail[:cc].encoded #=> 'Cc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
|
25
|
-
# mail[:cc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
26
|
-
# mail[:cc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
27
|
-
# mail[:cc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
28
|
-
#
|
29
|
-
require 'mail/fields/common/common_address'
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/common_address_field'
|
30
4
|
|
31
5
|
module Mail
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
6
|
+
# = Carbon Copy Field
|
7
|
+
#
|
8
|
+
# The Cc field inherits from StructuredField and handles the Cc: header
|
9
|
+
# field in the email.
|
10
|
+
#
|
11
|
+
# Sending cc to a mail message will instantiate a Mail::Field object that
|
12
|
+
# has a CcField as its field type. This includes all Mail::CommonAddress
|
13
|
+
# module instance metods.
|
14
|
+
#
|
15
|
+
# Only one Cc field can appear in a header, though it can have multiple
|
16
|
+
# addresses and groups of addresses.
|
17
|
+
#
|
18
|
+
# == Examples:
|
19
|
+
#
|
20
|
+
# mail = Mail.new
|
21
|
+
# mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
22
|
+
# mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
23
|
+
# mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
24
|
+
# mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
25
|
+
# mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
26
|
+
#
|
27
|
+
# mail[:cc].encoded #=> 'Cc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
|
28
|
+
# mail[:cc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
29
|
+
# mail[:cc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
30
|
+
# mail[:cc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
31
|
+
class CcField < CommonAddressField #:nodoc:
|
32
|
+
NAME = 'Cc'
|
54
33
|
end
|
55
34
|
end
|
@@ -1,41 +1,32 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
# The Comments field inherits from UnstructuredField and handles the Comments:
|
6
|
-
# header field in the email.
|
7
|
-
#
|
8
|
-
# Sending comments to a mail message will instantiate a Mail::Field object that
|
9
|
-
# has a CommentsField as its field type.
|
10
|
-
#
|
11
|
-
# An email header can have as many comments fields as it wants. There is no upper
|
12
|
-
# limit, the comments field is also optional (that is, no comment is needed)
|
13
|
-
#
|
14
|
-
# == Examples:
|
15
|
-
#
|
16
|
-
# mail = Mail.new
|
17
|
-
# mail.comments = 'This is a comment'
|
18
|
-
# mail.comments #=> 'This is a comment'
|
19
|
-
# mail[:comments] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
|
20
|
-
# mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
|
21
|
-
# mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
|
22
|
-
#
|
23
|
-
# mail.comments = "This is another comment"
|
24
|
-
# mail[:comments].map { |c| c.to_s }
|
25
|
-
# #=> ['This is a comment', "This is another comment"]
|
26
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_unstructured_field'
|
4
|
+
|
27
5
|
module Mail
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
6
|
+
# = Comments Field
|
7
|
+
#
|
8
|
+
# The Comments field inherits from UnstructuredField and handles the Comments:
|
9
|
+
# header field in the email.
|
10
|
+
#
|
11
|
+
# Sending comments to a mail message will instantiate a Mail::Field object that
|
12
|
+
# has a CommentsField as its field type.
|
13
|
+
#
|
14
|
+
# An email header can have as many comments fields as it wants. There is no upper
|
15
|
+
# limit, the comments field is also optional (that is, no comment is needed)
|
16
|
+
#
|
17
|
+
# == Examples:
|
18
|
+
#
|
19
|
+
# mail = Mail.new
|
20
|
+
# mail.comments = 'This is a comment'
|
21
|
+
# mail.comments #=> 'This is a comment'
|
22
|
+
# mail[:comments] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
|
23
|
+
# mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
|
24
|
+
# mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
|
25
|
+
#
|
26
|
+
# mail.comments = "This is another comment"
|
27
|
+
# mail[:comments].map { |c| c.to_s }
|
28
|
+
# #=> ['This is a comment', "This is another comment"]
|
29
|
+
class CommentsField < NamedUnstructuredField #:nodoc:
|
30
|
+
NAME = 'Comments'
|
40
31
|
end
|
41
32
|
end
|