mail 2.6.4 → 2.9.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 +5 -5
- data/README.md +208 -156
- data/lib/mail/attachments_list.rb +13 -10
- data/lib/mail/body.rb +96 -107
- data/lib/mail/configuration.rb +2 -0
- data/lib/mail/constants.rb +27 -5
- data/lib/mail/elements/address.rb +61 -50
- data/lib/mail/elements/address_list.rb +11 -19
- data/lib/mail/elements/content_disposition_element.rb +9 -16
- data/lib/mail/elements/content_location_element.rb +6 -11
- data/lib/mail/elements/content_transfer_encoding_element.rb +6 -11
- data/lib/mail/elements/content_type_element.rb +16 -23
- data/lib/mail/elements/date_time_element.rb +7 -15
- data/lib/mail/elements/envelope_from_element.rb +22 -23
- data/lib/mail/elements/message_ids_element.rb +18 -13
- data/lib/mail/elements/mime_version_element.rb +7 -15
- data/lib/mail/elements/phrase_list.rb +12 -10
- data/lib/mail/elements/received_element.rb +27 -19
- data/lib/mail/encodings/7bit.rb +9 -14
- data/lib/mail/encodings/8bit.rb +2 -21
- data/lib/mail/encodings/base64.rb +11 -12
- data/lib/mail/encodings/binary.rb +3 -22
- data/lib/mail/encodings/identity.rb +24 -0
- data/lib/mail/encodings/quoted_printable.rb +6 -6
- data/lib/mail/encodings/transfer_encoding.rb +38 -29
- data/lib/mail/encodings/unix_to_unix.rb +4 -2
- data/lib/mail/encodings.rb +83 -56
- data/lib/mail/envelope.rb +11 -14
- data/lib/mail/field.rb +181 -130
- data/lib/mail/field_list.rb +61 -8
- data/lib/mail/fields/bcc_field.rb +33 -52
- data/lib/mail/fields/cc_field.rb +27 -49
- data/lib/mail/fields/comments_field.rb +26 -37
- data/lib/mail/fields/common_address_field.rb +162 -0
- data/lib/mail/fields/common_date_field.rb +56 -0
- data/lib/mail/fields/common_field.rb +77 -0
- data/lib/mail/fields/common_message_id_field.rb +41 -0
- data/lib/mail/fields/content_description_field.rb +6 -14
- data/lib/mail/fields/content_disposition_field.rb +11 -38
- data/lib/mail/fields/content_id_field.rb +23 -51
- data/lib/mail/fields/content_location_field.rb +10 -25
- data/lib/mail/fields/content_transfer_encoding_field.rb +30 -31
- data/lib/mail/fields/content_type_field.rb +53 -84
- data/lib/mail/fields/date_field.rb +22 -52
- data/lib/mail/fields/from_field.rb +27 -49
- data/lib/mail/fields/in_reply_to_field.rb +37 -49
- data/lib/mail/fields/keywords_field.rb +17 -31
- data/lib/mail/fields/message_id_field.rb +24 -71
- data/lib/mail/fields/mime_version_field.rb +18 -30
- data/lib/mail/fields/named_structured_field.rb +10 -0
- data/lib/mail/fields/named_unstructured_field.rb +10 -0
- data/lib/mail/fields/optional_field.rb +9 -8
- data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +13 -11
- data/lib/mail/fields/received_field.rb +42 -57
- data/lib/mail/fields/references_field.rb +34 -49
- data/lib/mail/fields/reply_to_field.rb +27 -49
- data/lib/mail/fields/resent_bcc_field.rb +27 -49
- data/lib/mail/fields/resent_cc_field.rb +27 -49
- data/lib/mail/fields/resent_date_field.rb +4 -30
- data/lib/mail/fields/resent_from_field.rb +27 -49
- data/lib/mail/fields/resent_message_id_field.rb +4 -29
- data/lib/mail/fields/resent_sender_field.rb +26 -56
- data/lib/mail/fields/resent_to_field.rb +27 -49
- data/lib/mail/fields/return_path_field.rb +49 -54
- data/lib/mail/fields/sender_field.rb +33 -55
- data/lib/mail/fields/structured_field.rb +2 -30
- data/lib/mail/fields/subject_field.rb +8 -11
- data/lib/mail/fields/to_field.rb +27 -49
- data/lib/mail/fields/unstructured_field.rb +31 -47
- data/lib/mail/fields.rb +9 -0
- data/lib/mail/header.rb +71 -110
- data/lib/mail/mail.rb +34 -37
- data/lib/mail/matchers/attachment_matchers.rb +15 -0
- data/lib/mail/matchers/has_sent_mail.rb +21 -1
- data/lib/mail/message.rb +126 -127
- data/lib/mail/multibyte/chars.rb +24 -181
- data/lib/mail/multibyte/unicode.rb +11 -11
- data/lib/mail/multibyte/utils.rb +26 -43
- data/lib/mail/multibyte.rb +55 -16
- data/lib/mail/network/delivery_methods/exim.rb +8 -11
- data/lib/mail/network/delivery_methods/file_delivery.rb +15 -18
- data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +32 -35
- data/lib/mail/network/delivery_methods/smtp.rb +125 -68
- data/lib/mail/network/delivery_methods/smtp_connection.rb +11 -16
- data/lib/mail/network/delivery_methods/test_mailer.rb +12 -13
- data/lib/mail/network/retriever_methods/base.rb +13 -13
- data/lib/mail/network/retriever_methods/imap.rb +25 -9
- data/lib/mail/network/retriever_methods/pop3.rb +25 -23
- data/lib/mail/network/retriever_methods/test_retriever.rb +3 -2
- data/lib/mail/network.rb +1 -0
- data/lib/mail/parser_tools.rb +15 -0
- data/lib/mail/parsers/address_lists_parser.rb +33228 -116
- data/lib/mail/parsers/address_lists_parser.rl +183 -0
- data/lib/mail/parsers/content_disposition_parser.rb +885 -49
- data/lib/mail/parsers/content_disposition_parser.rl +93 -0
- data/lib/mail/parsers/content_location_parser.rb +812 -23
- data/lib/mail/parsers/content_location_parser.rl +82 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +512 -21
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
- data/lib/mail/parsers/content_type_parser.rb +1039 -55
- data/lib/mail/parsers/content_type_parser.rl +94 -0
- data/lib/mail/parsers/date_time_parser.rb +880 -25
- data/lib/mail/parsers/date_time_parser.rl +73 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3672 -40
- data/lib/mail/parsers/envelope_from_parser.rl +93 -0
- data/lib/mail/parsers/message_ids_parser.rb +5149 -25
- data/lib/mail/parsers/message_ids_parser.rl +97 -0
- data/lib/mail/parsers/mime_version_parser.rb +500 -26
- data/lib/mail/parsers/mime_version_parser.rl +72 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +873 -22
- data/lib/mail/parsers/phrase_lists_parser.rl +94 -0
- data/lib/mail/parsers/received_parser.rb +8779 -43
- data/lib/mail/parsers/received_parser.rl +95 -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/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
- data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
- data/lib/mail/parsers.rb +11 -25
- data/lib/mail/part.rb +25 -29
- data/lib/mail/parts_list.rb +62 -6
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +361 -74
- data/lib/mail/version.rb +2 -2
- data/lib/mail/yaml.rb +30 -0
- data/lib/mail.rb +4 -37
- metadata +125 -67
- data/CHANGELOG.rdoc +0 -787
- data/CONTRIBUTING.md +0 -60
- data/Dependencies.txt +0 -2
- data/Gemfile +0 -11
- data/Rakefile +0 -29
- data/TODO.rdoc +0 -9
- data/lib/mail/check_delivery_params.rb +0 -21
- data/lib/mail/core_extensions/smtp.rb +0 -25
- data/lib/mail/core_extensions/string/access.rb +0 -146
- data/lib/mail/core_extensions/string/multibyte.rb +0 -79
- data/lib/mail/core_extensions/string.rb +0 -21
- data/lib/mail/fields/common/address_container.rb +0 -17
- data/lib/mail/fields/common/common_address.rb +0 -136
- data/lib/mail/fields/common/common_date.rb +0 -36
- data/lib/mail/fields/common/common_field.rb +0 -61
- data/lib/mail/fields/common/common_message_id.rb +0 -49
- data/lib/mail/multibyte/exceptions.rb +0 -9
- data/lib/mail/parsers/ragel/common.rl +0 -185
- data/lib/mail/parsers/ragel/parser_info.rb +0 -61
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
- data/lib/mail/parsers/ragel/ruby.rb +0 -40
- data/lib/mail/parsers/ragel.rb +0 -18
- data/lib/mail/version_specific/ruby_1_8.rb +0 -126
- data/lib/mail/version_specific/ruby_1_9.rb +0 -223
data/lib/mail/field.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mail/fields'
|
|
3
|
+
require 'mail/constants'
|
|
3
4
|
|
|
4
5
|
# encoding: utf-8
|
|
5
6
|
module Mail
|
|
@@ -22,8 +23,6 @@ module Mail
|
|
|
22
23
|
# sections 3 and 4 of this standard.
|
|
23
24
|
#
|
|
24
25
|
class Field
|
|
25
|
-
|
|
26
|
-
include Utilities
|
|
27
26
|
include Comparable
|
|
28
27
|
|
|
29
28
|
STRUCTURED_FIELDS = %w[ bcc cc content-description content-disposition
|
|
@@ -37,40 +36,68 @@ module Mail
|
|
|
37
36
|
KNOWN_FIELDS = STRUCTURED_FIELDS + ['comments', 'subject']
|
|
38
37
|
|
|
39
38
|
FIELDS_MAP = {
|
|
40
|
-
"to" => ToField,
|
|
41
|
-
"cc" => CcField,
|
|
42
|
-
"bcc" => BccField,
|
|
43
|
-
"message-id" => MessageIdField,
|
|
44
|
-
"in-reply-to" => InReplyToField,
|
|
45
|
-
"references" => ReferencesField,
|
|
46
|
-
"subject" => SubjectField,
|
|
47
|
-
"comments" => CommentsField,
|
|
48
|
-
"keywords" => KeywordsField,
|
|
49
|
-
"date" => DateField,
|
|
50
|
-
"from" => FromField,
|
|
51
|
-
"sender" => SenderField,
|
|
52
|
-
"reply-to" => ReplyToField,
|
|
53
|
-
"resent-date" => ResentDateField,
|
|
54
|
-
"resent-from" => ResentFromField,
|
|
55
|
-
"resent-sender" =>
|
|
56
|
-
"resent-to" => ResentToField,
|
|
57
|
-
"resent-cc" => ResentCcField,
|
|
58
|
-
"resent-bcc" => ResentBccField,
|
|
59
|
-
"resent-message-id" => ResentMessageIdField,
|
|
60
|
-
"return-path" => ReturnPathField,
|
|
61
|
-
"received" => ReceivedField,
|
|
62
|
-
"mime-version" => MimeVersionField,
|
|
63
|
-
"content-transfer-encoding" => ContentTransferEncodingField,
|
|
64
|
-
"content-description" => ContentDescriptionField,
|
|
65
|
-
"content-disposition" => ContentDispositionField,
|
|
66
|
-
"content-type" => ContentTypeField,
|
|
67
|
-
"content-id" => ContentIdField,
|
|
68
|
-
"content-location" => ContentLocationField,
|
|
39
|
+
"to" => "ToField",
|
|
40
|
+
"cc" => "CcField",
|
|
41
|
+
"bcc" => "BccField",
|
|
42
|
+
"message-id" => "MessageIdField",
|
|
43
|
+
"in-reply-to" => "InReplyToField",
|
|
44
|
+
"references" => "ReferencesField",
|
|
45
|
+
"subject" => "SubjectField",
|
|
46
|
+
"comments" => "CommentsField",
|
|
47
|
+
"keywords" => "KeywordsField",
|
|
48
|
+
"date" => "DateField",
|
|
49
|
+
"from" => "FromField",
|
|
50
|
+
"sender" => "SenderField",
|
|
51
|
+
"reply-to" => "ReplyToField",
|
|
52
|
+
"resent-date" => "ResentDateField",
|
|
53
|
+
"resent-from" => "ResentFromField",
|
|
54
|
+
"resent-sender" => "ResentSenderField",
|
|
55
|
+
"resent-to" => "ResentToField",
|
|
56
|
+
"resent-cc" => "ResentCcField",
|
|
57
|
+
"resent-bcc" => "ResentBccField",
|
|
58
|
+
"resent-message-id" => "ResentMessageIdField",
|
|
59
|
+
"return-path" => "ReturnPathField",
|
|
60
|
+
"received" => "ReceivedField",
|
|
61
|
+
"mime-version" => "MimeVersionField",
|
|
62
|
+
"content-transfer-encoding" => "ContentTransferEncodingField",
|
|
63
|
+
"content-description" => "ContentDescriptionField",
|
|
64
|
+
"content-disposition" => "ContentDispositionField",
|
|
65
|
+
"content-type" => "ContentTypeField",
|
|
66
|
+
"content-id" => "ContentIdField",
|
|
67
|
+
"content-location" => "ContentLocationField",
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
FIELD_NAME_MAP =
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
FIELD_NAME_MAP = {
|
|
71
|
+
"to" => "To",
|
|
72
|
+
"cc" => "Cc",
|
|
73
|
+
"bcc" => "Bcc",
|
|
74
|
+
"message-id" => "Message-ID",
|
|
75
|
+
"in-reply-to" => "In-Reply-To",
|
|
76
|
+
"references" => "References",
|
|
77
|
+
"subject" => "Subject",
|
|
78
|
+
"comments" => "Comments",
|
|
79
|
+
"keywords" => "Keywords",
|
|
80
|
+
"date" => "Date",
|
|
81
|
+
"from" => "From",
|
|
82
|
+
"sender" => "Sender",
|
|
83
|
+
"reply-to" => "Reply-To",
|
|
84
|
+
"resent-date" => "Resent-Date",
|
|
85
|
+
"resent-from" => "Resent-From",
|
|
86
|
+
"resent-sender" => "Resent-Sender",
|
|
87
|
+
"resent-to" => "Resent-To",
|
|
88
|
+
"resent-cc" => "Resent-Cc",
|
|
89
|
+
"resent-bcc" => "Resent-Bcc",
|
|
90
|
+
"resent-message-id" => "Resent-Message-ID",
|
|
91
|
+
"return-path" => "Return-Path",
|
|
92
|
+
"received" => "Received",
|
|
93
|
+
"mime-version" => "MIME-Version",
|
|
94
|
+
"content-transfer-encoding" => "Content-Transfer-Encoding",
|
|
95
|
+
"content-description" => "Content-Description",
|
|
96
|
+
"content-disposition" => "Content-Disposition",
|
|
97
|
+
"content-type" => "Content-Type",
|
|
98
|
+
"content-id" => "Content-ID",
|
|
99
|
+
"content-location" => "Content-Location",
|
|
100
|
+
}
|
|
74
101
|
|
|
75
102
|
# Generic Field Exception
|
|
76
103
|
class FieldError < StandardError
|
|
@@ -83,9 +110,31 @@ module Mail
|
|
|
83
110
|
|
|
84
111
|
def initialize(element, value, reason)
|
|
85
112
|
@element = element
|
|
86
|
-
@value = value
|
|
87
|
-
@reason = reason
|
|
88
|
-
super("#{element} can not parse |#{value}
|
|
113
|
+
@value = to_utf8(value)
|
|
114
|
+
@reason = to_utf8(reason)
|
|
115
|
+
super("#{@element} can not parse |#{@value}|: #{@reason}")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
def to_utf8(text)
|
|
120
|
+
if text.respond_to?(:force_encoding)
|
|
121
|
+
text.dup.force_encoding(Encoding::UTF_8)
|
|
122
|
+
else
|
|
123
|
+
text
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class NilParseError < ParseError #:nodoc:
|
|
129
|
+
def initialize(element)
|
|
130
|
+
super element, nil, 'nil is invalid'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class IncompleteParseError < ParseError #:nodoc:
|
|
135
|
+
def initialize(element, original_text, unparsed_index)
|
|
136
|
+
parsed_text = to_utf8(original_text[0...unparsed_index])
|
|
137
|
+
super element, original_text, "Only able to parse up to #{parsed_text.inspect}"
|
|
89
138
|
end
|
|
90
139
|
end
|
|
91
140
|
|
|
@@ -93,53 +142,79 @@ module Mail
|
|
|
93
142
|
class SyntaxError < FieldError #:nodoc:
|
|
94
143
|
end
|
|
95
144
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
145
|
+
class << self
|
|
146
|
+
# Parse a field from a raw header line:
|
|
147
|
+
#
|
|
148
|
+
# Mail::Field.parse("field-name: field data")
|
|
149
|
+
# # => #<Mail::Field …>
|
|
150
|
+
def parse(field, charset = 'utf-8')
|
|
151
|
+
name, value = split(field)
|
|
152
|
+
if name && value
|
|
153
|
+
new name, value, charset
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def split(raw_field) #:nodoc:
|
|
158
|
+
if raw_field.index(Constants::COLON)
|
|
159
|
+
name, value = raw_field.split(Constants::COLON, 2)
|
|
160
|
+
name.rstrip!
|
|
161
|
+
if /\A#{Constants::FIELD_NAME}\z/.match?(name)
|
|
162
|
+
[ name.rstrip, value.strip ]
|
|
163
|
+
else
|
|
164
|
+
Kernel.warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: invalid header name syntax: #{name.inspect}"
|
|
165
|
+
nil
|
|
166
|
+
end
|
|
167
|
+
else
|
|
168
|
+
raw_field.strip
|
|
169
|
+
end
|
|
170
|
+
rescue => error
|
|
171
|
+
warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: #{error.class}: #{error.message}"
|
|
172
|
+
nil
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def field_class_for(name) #:nodoc:
|
|
176
|
+
class_name = FIELDS_MAP[name.to_s.downcase]
|
|
177
|
+
Mail.const_get(class_name) if class_name
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
attr_reader :unparsed_value
|
|
182
|
+
|
|
183
|
+
# Create a field by name and optional value:
|
|
103
184
|
#
|
|
104
|
-
#
|
|
185
|
+
# Mail::Field.new("field-name", "value")
|
|
186
|
+
# # => #<Mail::Field …>
|
|
105
187
|
#
|
|
106
|
-
#
|
|
188
|
+
# Values that aren't strings or arrays are coerced to Strings with `#to_s`.
|
|
107
189
|
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
# it will be passed through as is, for example, content-type
|
|
111
|
-
# field can accept an array with the type and a hash of
|
|
112
|
-
# parameters:
|
|
190
|
+
# Mail::Field.new("field-name", 1234)
|
|
191
|
+
# # => #<Mail::Field …>
|
|
113
192
|
#
|
|
114
|
-
# Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
|
193
|
+
# Mail::Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
|
194
|
+
# # => #<Mail::Field …>
|
|
115
195
|
def initialize(name, value = nil, charset = 'utf-8')
|
|
116
196
|
case
|
|
117
|
-
when name.index(COLON)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
@raw_value = name
|
|
121
|
-
@value = nil
|
|
122
|
-
when Utilities.blank?(value) # Field.new("field-name")
|
|
197
|
+
when name.index(Constants::COLON)
|
|
198
|
+
raise ArgumentError, 'Passing an unparsed header field to Mail::Field.new is not supported in Mail 2.8.0+. Use Mail::Field.parse instead.'
|
|
199
|
+
when Utilities.blank?(value)
|
|
123
200
|
@name = name
|
|
124
|
-
@
|
|
125
|
-
@raw_value = nil
|
|
201
|
+
@unparsed_value = nil
|
|
126
202
|
@charset = charset
|
|
127
|
-
else
|
|
203
|
+
else
|
|
128
204
|
@name = name
|
|
129
|
-
@
|
|
130
|
-
@raw_value = nil
|
|
205
|
+
@unparsed_value = value
|
|
131
206
|
@charset = charset
|
|
132
207
|
end
|
|
133
|
-
|
|
208
|
+
klass = self.class.field_class_for(@name)
|
|
209
|
+
@name = klass ? klass::NAME : @name
|
|
134
210
|
end
|
|
135
211
|
|
|
136
|
-
def field=(
|
|
137
|
-
@field =
|
|
212
|
+
def field=(field)
|
|
213
|
+
@field = field
|
|
138
214
|
end
|
|
139
215
|
|
|
140
216
|
def field
|
|
141
|
-
|
|
142
|
-
@field ||= create_field(@name, @value, @charset)
|
|
217
|
+
@field ||= create_field(@name, @unparsed_value, @charset)
|
|
143
218
|
end
|
|
144
219
|
|
|
145
220
|
def name
|
|
@@ -164,64 +239,63 @@ module Mail
|
|
|
164
239
|
end.join(" ")}>"
|
|
165
240
|
end
|
|
166
241
|
|
|
167
|
-
def
|
|
168
|
-
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
def same( other )
|
|
172
|
-
return false unless other.kind_of?(self.class)
|
|
173
|
-
match_to_s(other.name, self.name)
|
|
242
|
+
def same(other)
|
|
243
|
+
other.kind_of?(self.class) && Utilities.match_to_s(other.name, name)
|
|
174
244
|
end
|
|
175
245
|
|
|
176
|
-
def ==(
|
|
177
|
-
|
|
178
|
-
match_to_s(other.name, self.name) && match_to_s(other.value, self.value)
|
|
246
|
+
def ==(other)
|
|
247
|
+
same(other) && Utilities.match_to_s(other.value, value)
|
|
179
248
|
end
|
|
180
249
|
|
|
181
|
-
def responsible_for?(
|
|
182
|
-
name.to_s.casecmp(
|
|
250
|
+
def responsible_for?(field_name)
|
|
251
|
+
name.to_s.casecmp(field_name.to_s) == 0
|
|
183
252
|
end
|
|
184
253
|
|
|
185
|
-
def <=>(
|
|
186
|
-
|
|
254
|
+
def <=>(other)
|
|
255
|
+
field_order_id <=> other.field_order_id
|
|
187
256
|
end
|
|
188
257
|
|
|
189
258
|
def field_order_id
|
|
190
|
-
@field_order_id ||= (
|
|
259
|
+
@field_order_id ||= FIELD_ORDER_LOOKUP.fetch(self.name.to_s.downcase, 100)
|
|
191
260
|
end
|
|
192
261
|
|
|
193
262
|
def method_missing(name, *args, &block)
|
|
194
263
|
field.send(name, *args, &block)
|
|
195
264
|
end
|
|
196
265
|
|
|
197
|
-
|
|
198
|
-
|
|
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
|
|
266
|
+
def respond_to_missing?(method_name, include_private)
|
|
267
|
+
field.respond_to?(method_name, include_private) || super
|
|
205
268
|
end
|
|
206
269
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
270
|
+
FIELD_ORDER_LOOKUP = Hash[%w[
|
|
271
|
+
return-path received
|
|
272
|
+
resent-date resent-from resent-sender resent-to
|
|
273
|
+
resent-cc resent-bcc resent-message-id
|
|
274
|
+
date from sender reply-to to cc bcc
|
|
275
|
+
message-id in-reply-to references
|
|
276
|
+
subject comments keywords
|
|
277
|
+
mime-version content-type content-transfer-encoding
|
|
278
|
+
content-location content-disposition content-description
|
|
279
|
+
].each_with_index.to_a]
|
|
217
280
|
|
|
218
281
|
private
|
|
219
282
|
|
|
220
|
-
def
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
283
|
+
def create_field(name, value, charset)
|
|
284
|
+
parse_field(name, value, charset)
|
|
285
|
+
rescue Mail::Field::ParseError => e
|
|
286
|
+
field = Mail::UnstructuredField.new(name, value)
|
|
287
|
+
field.errors << [name, value, e]
|
|
288
|
+
field
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def parse_field(name, value, charset)
|
|
292
|
+
value = unfold(value) if value.is_a?(String)
|
|
293
|
+
|
|
294
|
+
if klass = self.class.field_class_for(name)
|
|
295
|
+
klass.parse(value, charset)
|
|
296
|
+
else
|
|
297
|
+
OptionalField.parse(name, value, charset)
|
|
298
|
+
end
|
|
225
299
|
end
|
|
226
300
|
|
|
227
301
|
# 2.2.3. Long Header Fields
|
|
@@ -233,30 +307,7 @@ module Mail
|
|
|
233
307
|
# treated in its unfolded form for further syntactic and semantic
|
|
234
308
|
# evaluation.
|
|
235
309
|
def unfold(string)
|
|
236
|
-
string.gsub(
|
|
310
|
+
string.gsub(Constants::UNFOLD_WS, '\1')
|
|
237
311
|
end
|
|
238
|
-
|
|
239
|
-
def create_field(name, value, charset)
|
|
240
|
-
value = unfold(value) if value.is_a?(String)
|
|
241
|
-
|
|
242
|
-
begin
|
|
243
|
-
new_field(name, value, charset)
|
|
244
|
-
rescue Mail::Field::ParseError => e
|
|
245
|
-
field = Mail::UnstructuredField.new(name, value)
|
|
246
|
-
field.errors << [name, value, e]
|
|
247
|
-
field
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
def new_field(name, value, charset)
|
|
252
|
-
lower_case_name = name.to_s.downcase
|
|
253
|
-
if field_klass = FIELDS_MAP[lower_case_name]
|
|
254
|
-
field_klass.new(value, charset)
|
|
255
|
-
else
|
|
256
|
-
OptionalField.new(name, value, charset)
|
|
257
|
-
end
|
|
258
|
-
end
|
|
259
|
-
|
|
260
312
|
end
|
|
261
|
-
|
|
262
313
|
end
|
data/lib/mail/field_list.rb
CHANGED
|
@@ -2,12 +2,40 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
module Mail
|
|
4
4
|
|
|
5
|
-
# Field List class provides an enhanced array that keeps a list of
|
|
5
|
+
# Field List class provides an enhanced array that keeps a list of
|
|
6
6
|
# email fields in order. And allows you to insert new fields without
|
|
7
7
|
# having to worry about the order they will appear in.
|
|
8
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
|
|
9
21
|
|
|
10
|
-
|
|
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
|
|
30
|
+
|
|
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
|
|
35
|
+
else
|
|
36
|
+
insert_field field
|
|
37
|
+
end
|
|
38
|
+
end
|
|
11
39
|
|
|
12
40
|
# Insert the field in sorted order.
|
|
13
41
|
#
|
|
@@ -15,20 +43,45 @@ module Mail
|
|
|
15
43
|
# Copyright (C) 2001-2013 Python Software Foundation.
|
|
16
44
|
# Licensed under <http://docs.python.org/license.html>
|
|
17
45
|
# From <http://hg.python.org/cpython/file/2.7/Lib/bisect.py>
|
|
18
|
-
def
|
|
19
|
-
lo = 0
|
|
20
|
-
hi = size
|
|
21
|
-
|
|
46
|
+
def insert_field(field)
|
|
47
|
+
lo, hi = 0, size
|
|
22
48
|
while lo < hi
|
|
23
49
|
mid = (lo + hi).div(2)
|
|
24
|
-
if
|
|
50
|
+
if field < self[mid]
|
|
25
51
|
hi = mid
|
|
26
52
|
else
|
|
27
53
|
lo = mid + 1
|
|
28
54
|
end
|
|
29
55
|
end
|
|
30
56
|
|
|
31
|
-
insert
|
|
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
|
|
84
|
+
end
|
|
32
85
|
end
|
|
33
86
|
end
|
|
34
87
|
end
|
|
@@ -1,68 +1,49 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
#
|
|
4
|
-
# = Blind Carbon Copy Field
|
|
5
|
-
#
|
|
6
|
-
# The Bcc field inherits from StructuredField and handles the Bcc: header
|
|
7
|
-
# field in the email.
|
|
8
|
-
#
|
|
9
|
-
# Sending bcc to a mail message will instantiate a Mail::Field object that
|
|
10
|
-
# has a BccField as its field type. This includes all Mail::CommonAddress
|
|
11
|
-
# module instance metods.
|
|
12
|
-
#
|
|
13
|
-
# Only one Bcc field can appear in a header, though it can have multiple
|
|
14
|
-
# addresses and groups of addresses.
|
|
15
|
-
#
|
|
16
|
-
# == Examples:
|
|
17
|
-
#
|
|
18
|
-
# mail = Mail.new
|
|
19
|
-
# mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
20
|
-
# mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
21
|
-
# mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
22
|
-
# mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
23
|
-
# mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
24
|
-
#
|
|
25
|
-
# mail[:bcc].encoded #=> '' # Bcc field does not get output into an email
|
|
26
|
-
# mail[:bcc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
27
|
-
# mail[:bcc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
28
|
-
# mail[:bcc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
|
29
|
-
#
|
|
30
|
-
require 'mail/fields/common/common_address'
|
|
31
3
|
|
|
32
4
|
module Mail
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
5
|
+
# = Blind Carbon Copy Field
|
|
6
|
+
#
|
|
7
|
+
# The Bcc field inherits from StructuredField and handles the Bcc: header
|
|
8
|
+
# field in the email.
|
|
9
|
+
#
|
|
10
|
+
# Sending bcc to a mail message will instantiate a Mail::Field object that
|
|
11
|
+
# has a BccField as its field type. This includes all Mail::CommonAddress
|
|
12
|
+
# module instance metods.
|
|
13
|
+
#
|
|
14
|
+
# Only one Bcc field can appear in a header, though it can have multiple
|
|
15
|
+
# addresses and groups of addresses.
|
|
16
|
+
#
|
|
17
|
+
# == Examples:
|
|
18
|
+
#
|
|
19
|
+
# mail = Mail.new
|
|
20
|
+
# mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
21
|
+
# mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
22
|
+
# mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
23
|
+
# mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
24
|
+
# mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
|
|
25
|
+
#
|
|
26
|
+
# mail[:bcc].encoded #=> '' # Bcc field does not get output into an email
|
|
27
|
+
# mail[:bcc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
28
|
+
# mail[:bcc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
29
|
+
# mail[:bcc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
|
30
|
+
class BccField < CommonAddressField #:nodoc:
|
|
31
|
+
NAME = 'Bcc'
|
|
49
32
|
|
|
50
|
-
|
|
51
|
-
|
|
33
|
+
attr_accessor :include_in_headers
|
|
34
|
+
|
|
35
|
+
def initialize(value = nil, charset = nil)
|
|
36
|
+
super
|
|
37
|
+
self.include_in_headers = false
|
|
52
38
|
end
|
|
53
39
|
|
|
54
40
|
# Bcc field should not be :encoded by default
|
|
55
41
|
def encoded
|
|
56
42
|
if include_in_headers
|
|
57
|
-
|
|
43
|
+
super
|
|
58
44
|
else
|
|
59
45
|
''
|
|
60
46
|
end
|
|
61
47
|
end
|
|
62
|
-
|
|
63
|
-
def decoded
|
|
64
|
-
do_decode
|
|
65
|
-
end
|
|
66
|
-
|
|
67
48
|
end
|
|
68
49
|
end
|
data/lib/mail/fields/cc_field.rb
CHANGED
|
@@ -1,55 +1,33 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
#
|
|
4
|
-
# = Carbon Copy Field
|
|
5
|
-
#
|
|
6
|
-
# The Cc field inherits from StructuredField and handles the Cc: header
|
|
7
|
-
# field in the email.
|
|
8
|
-
#
|
|
9
|
-
# Sending cc to a mail message will instantiate a Mail::Field object that
|
|
10
|
-
# has a CcField as its field type. This includes all Mail::CommonAddress
|
|
11
|
-
# module instance metods.
|
|
12
|
-
#
|
|
13
|
-
# Only one Cc field can appear in a header, though it can have multiple
|
|
14
|
-
# addresses and groups of addresses.
|
|
15
|
-
#
|
|
16
|
-
# == Examples:
|
|
17
|
-
#
|
|
18
|
-
# mail = Mail.new
|
|
19
|
-
# mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
20
|
-
# mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
21
|
-
# mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
22
|
-
# mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
23
|
-
# mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
24
|
-
#
|
|
25
|
-
# mail[:cc].encoded #=> 'Cc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
|
|
26
|
-
# mail[:cc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
27
|
-
# mail[:cc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
28
|
-
# mail[:cc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
|
29
|
-
#
|
|
30
|
-
require 'mail/fields/common/common_address'
|
|
31
3
|
|
|
32
4
|
module Mail
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
5
|
+
# = Carbon Copy Field
|
|
6
|
+
#
|
|
7
|
+
# The Cc field inherits from StructuredField and handles the Cc: header
|
|
8
|
+
# field in the email.
|
|
9
|
+
#
|
|
10
|
+
# Sending cc to a mail message will instantiate a Mail::Field object that
|
|
11
|
+
# has a CcField as its field type. This includes all Mail::CommonAddress
|
|
12
|
+
# module instance metods.
|
|
13
|
+
#
|
|
14
|
+
# Only one Cc field can appear in a header, though it can have multiple
|
|
15
|
+
# addresses and groups of addresses.
|
|
16
|
+
#
|
|
17
|
+
# == Examples:
|
|
18
|
+
#
|
|
19
|
+
# mail = Mail.new
|
|
20
|
+
# mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
21
|
+
# mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
22
|
+
# mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
23
|
+
# mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
24
|
+
# mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
|
|
25
|
+
#
|
|
26
|
+
# mail[:cc].encoded #=> 'Cc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
|
|
27
|
+
# mail[:cc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
28
|
+
# mail[:cc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
29
|
+
# mail[:cc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
|
30
|
+
class CcField < CommonAddressField #:nodoc:
|
|
31
|
+
NAME = 'Cc'
|
|
54
32
|
end
|
|
55
33
|
end
|