mail 2.6.1 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +150 -107
- data/lib/mail/attachments_list.rb +13 -10
- data/lib/mail/body.rb +104 -90
- data/lib/mail/check_delivery_params.rb +55 -10
- data/lib/mail/configuration.rb +3 -0
- data/lib/mail/constants.rb +79 -0
- data/lib/mail/elements/address.rb +96 -108
- data/lib/mail/elements/address_list.rb +13 -30
- data/lib/mail/elements/content_disposition_element.rb +10 -16
- data/lib/mail/elements/content_location_element.rb +9 -13
- data/lib/mail/elements/content_transfer_encoding_element.rb +7 -11
- data/lib/mail/elements/content_type_element.rb +17 -23
- data/lib/mail/elements/date_time_element.rb +8 -15
- data/lib/mail/elements/envelope_from_element.rb +23 -23
- data/lib/mail/elements/message_ids_element.rb +22 -15
- data/lib/mail/elements/mime_version_element.rb +8 -15
- data/lib/mail/elements/phrase_list.rb +13 -10
- data/lib/mail/elements/received_element.rb +28 -19
- 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 -92
- data/lib/mail/envelope.rb +12 -14
- data/lib/mail/field.rb +121 -85
- data/lib/mail/field_list.rb +62 -8
- 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 +32 -31
- 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 +36 -50
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +73 -110
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +6 -11
- data/lib/mail/matchers/attachment_matchers.rb +44 -0
- data/lib/mail/matchers/has_sent_mail.rb +53 -9
- data/lib/mail/message.rb +132 -136
- data/lib/mail/multibyte/chars.rb +24 -180
- data/lib/mail/multibyte/unicode.rb +31 -26
- data/lib/mail/multibyte/utils.rb +27 -43
- data/lib/mail/multibyte.rb +56 -16
- data/lib/mail/network/delivery_methods/exim.rb +9 -11
- data/lib/mail/network/delivery_methods/file_delivery.rb +14 -16
- data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +68 -24
- data/lib/mail/network/delivery_methods/smtp.rb +77 -54
- data/lib/mail/network/delivery_methods/smtp_connection.rb +5 -9
- data/lib/mail/network/delivery_methods/test_mailer.rb +9 -9
- data/lib/mail/network/retriever_methods/base.rb +9 -8
- data/lib/mail/network/retriever_methods/imap.rb +21 -7
- 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 +33226 -116
- data/lib/mail/parsers/address_lists_parser.rl +179 -0
- data/lib/mail/parsers/content_disposition_parser.rb +883 -49
- data/lib/mail/parsers/content_disposition_parser.rl +89 -0
- data/lib/mail/parsers/content_location_parser.rb +810 -23
- data/lib/mail/parsers/content_location_parser.rl +78 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +510 -21
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
- data/lib/mail/parsers/content_type_parser.rb +1031 -47
- data/lib/mail/parsers/content_type_parser.rl +90 -0
- data/lib/mail/parsers/date_time_parser.rb +879 -24
- data/lib/mail/parsers/date_time_parser.rl +69 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3670 -40
- data/lib/mail/parsers/envelope_from_parser.rl +89 -0
- data/lib/mail/parsers/message_ids_parser.rb +5147 -25
- data/lib/mail/parsers/message_ids_parser.rl +93 -0
- data/lib/mail/parsers/mime_version_parser.rb +498 -26
- data/lib/mail/parsers/mime_version_parser.rl +68 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +872 -21
- data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
- data/lib/mail/parsers/received_parser.rb +8777 -42
- 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/{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 +12 -25
- data/lib/mail/part.rb +11 -12
- data/lib/mail/parts_list.rb +88 -14
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +377 -40
- 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 +138 -94
- data/CHANGELOG.rdoc +0 -752
- data/CONTRIBUTING.md +0 -60
- data/Dependencies.txt +0 -2
- data/Gemfile +0 -15
- data/Rakefile +0 -29
- data/TODO.rdoc +0 -9
- data/VERSION +0 -4
- 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 -43
- data/lib/mail/fields/common/address_container.rb +0 -16
- data/lib/mail/fields/common/common_address.rb +0 -135
- data/lib/mail/fields/common/common_date.rb +0 -35
- 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/ragel/common.rl +0 -184
- 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 -2129
- 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 -39
- data/lib/mail/parsers/ragel.rb +0 -17
- data/lib/mail/patterns.rb +0 -37
- data/lib/mail/version_specific/ruby_1_8.rb +0 -119
- data/lib/mail/version_specific/ruby_1_9.rb +0 -159
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_structured_field'
|
4
|
+
require 'mail/utilities'
|
5
|
+
|
6
|
+
module Mail
|
7
|
+
class CommonMessageIdField < NamedStructuredField #:nodoc:
|
8
|
+
def element
|
9
|
+
@element ||= Mail::MessageIdsElement.new(value)
|
10
|
+
end
|
11
|
+
|
12
|
+
def message_id
|
13
|
+
element.message_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def message_ids
|
17
|
+
element.message_ids
|
18
|
+
end
|
19
|
+
|
20
|
+
def default
|
21
|
+
ids = message_ids
|
22
|
+
ids.one? ? ids.first : ids
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
decoded.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def do_encode
|
31
|
+
%Q{#{name}: #{formatted_message_ids("\r\n ")}\r\n}
|
32
|
+
end
|
33
|
+
|
34
|
+
def do_decode
|
35
|
+
formatted_message_ids
|
36
|
+
end
|
37
|
+
|
38
|
+
def formatted_message_ids(join = ' ')
|
39
|
+
message_ids.map { |m| "<#{m}>" }.join(join) if message_ids.any?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,19 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_unstructured_field'
|
4
|
+
|
5
5
|
module Mail
|
6
|
-
class ContentDescriptionField <
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(value = nil, charset = 'utf-8')
|
12
|
-
self.charset = charset
|
13
|
-
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
14
|
-
self.parse
|
15
|
-
self
|
6
|
+
class ContentDescriptionField < NamedUnstructuredField #:nodoc:
|
7
|
+
NAME = 'Content-Description'
|
8
|
+
|
9
|
+
def self.singular?
|
10
|
+
true
|
16
11
|
end
|
17
|
-
|
18
12
|
end
|
19
13
|
end
|
@@ -1,26 +1,20 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_structured_field'
|
4
|
+
require 'mail/fields/parameter_hash'
|
3
5
|
|
4
6
|
module Mail
|
5
|
-
class ContentDispositionField <
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(value = nil, charset = 'utf-8')
|
11
|
-
self.charset = charset
|
12
|
-
ensure_filename_quoted(value)
|
13
|
-
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
14
|
-
self.parse
|
15
|
-
self
|
7
|
+
class ContentDispositionField < NamedStructuredField #:nodoc:
|
8
|
+
NAME = 'Content-Disposition'
|
9
|
+
|
10
|
+
def self.singular?
|
11
|
+
true
|
16
12
|
end
|
17
|
-
|
18
|
-
def
|
19
|
-
|
20
|
-
@element = Mail::ContentDispositionElement.new(val)
|
21
|
-
end
|
13
|
+
|
14
|
+
def initialize(value = nil, charset = nil)
|
15
|
+
super ensure_filename_quoted(value), charset
|
22
16
|
end
|
23
|
-
|
17
|
+
|
24
18
|
def element
|
25
19
|
@element ||= Mail::ContentDispositionElement.new(value)
|
26
20
|
end
|
@@ -28,43 +22,25 @@ module Mail
|
|
28
22
|
def disposition_type
|
29
23
|
element.disposition_type
|
30
24
|
end
|
31
|
-
|
25
|
+
|
32
26
|
def parameters
|
33
27
|
@parameters = ParameterHash.new
|
34
|
-
element.parameters.each { |p| @parameters.merge!(p) }
|
28
|
+
element.parameters.each { |p| @parameters.merge!(p) } unless element.parameters.nil?
|
35
29
|
@parameters
|
36
30
|
end
|
37
31
|
|
38
32
|
def filename
|
39
|
-
|
40
|
-
when !parameters['filename'].blank?
|
41
|
-
@filename = parameters['filename']
|
42
|
-
when !parameters['name'].blank?
|
43
|
-
@filename = parameters['name']
|
44
|
-
else
|
45
|
-
@filename = nil
|
46
|
-
end
|
47
|
-
@filename
|
33
|
+
@filename ||= parameters['filename'] || parameters['name']
|
48
34
|
end
|
49
35
|
|
50
|
-
# TODO: Fix this up
|
51
36
|
def encoded
|
52
|
-
if parameters.length > 0
|
53
|
-
|
54
|
-
else
|
55
|
-
p = "\r\n"
|
56
|
-
end
|
57
|
-
"#{CAPITALIZED_FIELD}: #{disposition_type}" + p
|
37
|
+
p = ";\r\n\s#{parameters.encoded}" if parameters.length > 0
|
38
|
+
"#{name}: #{disposition_type}#{p}\r\n"
|
58
39
|
end
|
59
|
-
|
40
|
+
|
60
41
|
def decoded
|
61
|
-
if parameters.length > 0
|
62
|
-
|
63
|
-
else
|
64
|
-
p = ""
|
65
|
-
end
|
66
|
-
"#{disposition_type}" + p
|
42
|
+
p = "; #{parameters.decoded}" if parameters.length > 0
|
43
|
+
"#{disposition_type}#{p}"
|
67
44
|
end
|
68
|
-
|
69
45
|
end
|
70
46
|
end
|
@@ -1,62 +1,36 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_structured_field'
|
4
|
+
require 'mail/utilities'
|
5
|
+
|
5
6
|
module Mail
|
6
|
-
class ContentIdField <
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
if
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
20
|
-
self.parse
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def parse(val = value)
|
25
|
-
unless val.blank?
|
26
|
-
@element = Mail::MessageIdsElement.new(val)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
7
|
+
class ContentIdField < NamedStructuredField #:nodoc:
|
8
|
+
NAME = 'Content-ID'
|
9
|
+
|
10
|
+
def self.singular?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(value = nil, charset = nil)
|
15
|
+
value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
|
16
|
+
super value, charset
|
17
|
+
end
|
18
|
+
|
30
19
|
def element
|
31
20
|
@element ||= Mail::MessageIdsElement.new(value)
|
32
21
|
end
|
33
|
-
|
34
|
-
def name
|
35
|
-
'Content-ID'
|
36
|
-
end
|
37
|
-
|
22
|
+
|
38
23
|
def content_id
|
39
24
|
element.message_id
|
40
25
|
end
|
41
|
-
|
42
|
-
def to_s
|
43
|
-
"<#{content_id}>"
|
44
|
-
end
|
45
|
-
|
46
|
-
# TODO: Fix this up
|
47
|
-
def encoded
|
48
|
-
"#{CAPITALIZED_FIELD}: #{to_s}\r\n"
|
49
|
-
end
|
50
|
-
|
51
|
-
def decoded
|
52
|
-
"#{to_s}"
|
53
|
-
end
|
54
|
-
|
26
|
+
|
55
27
|
private
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
28
|
+
def do_decode
|
29
|
+
"<#{content_id}>"
|
30
|
+
end
|
31
|
+
|
32
|
+
def do_encode
|
33
|
+
"#{name}: #{do_decode}\r\n"
|
34
|
+
end
|
61
35
|
end
|
62
36
|
end
|
@@ -1,26 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_structured_field'
|
4
|
+
|
5
5
|
module Mail
|
6
|
-
class ContentLocationField <
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(value = nil, charset = 'utf-8')
|
12
|
-
self.charset = charset
|
13
|
-
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
14
|
-
self.parse
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
def parse(val = value)
|
19
|
-
unless val.blank?
|
20
|
-
@element = Mail::ContentLocationElement.new(val)
|
21
|
-
end
|
6
|
+
class ContentLocationField < NamedStructuredField #:nodoc:
|
7
|
+
NAME = 'Content-Location'
|
8
|
+
|
9
|
+
def self.singular?
|
10
|
+
true
|
22
11
|
end
|
23
|
-
|
12
|
+
|
24
13
|
def element
|
25
14
|
@element ||= Mail::ContentLocationElement.new(value)
|
26
15
|
end
|
@@ -29,14 +18,12 @@ module Mail
|
|
29
18
|
element.location
|
30
19
|
end
|
31
20
|
|
32
|
-
# TODO: Fix this up
|
33
21
|
def encoded
|
34
|
-
"#{
|
22
|
+
"#{name}: #{location}\r\n"
|
35
23
|
end
|
36
|
-
|
24
|
+
|
37
25
|
def decoded
|
38
|
-
location
|
26
|
+
location
|
39
27
|
end
|
40
|
-
|
41
28
|
end
|
42
29
|
end
|
@@ -1,44 +1,45 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
#
|
3
|
-
|
4
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_structured_field'
|
4
|
+
|
5
5
|
module Mail
|
6
|
-
class ContentTransferEncodingField <
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(value = nil, charset = 'utf-8')
|
12
|
-
self.charset = charset
|
13
|
-
value = '7bit' if value.to_s =~ /7-?bits?/i
|
14
|
-
value = '8bit' if value.to_s =~ /8-?bits?/i
|
15
|
-
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
16
|
-
self.parse
|
17
|
-
self
|
6
|
+
class ContentTransferEncodingField < NamedStructuredField #:nodoc:
|
7
|
+
NAME = 'Content-Transfer-Encoding'
|
8
|
+
|
9
|
+
def self.singular?
|
10
|
+
true
|
18
11
|
end
|
19
|
-
|
20
|
-
def
|
21
|
-
|
22
|
-
|
12
|
+
|
13
|
+
def self.normalize_content_transfer_encoding(value)
|
14
|
+
case value
|
15
|
+
when /7-?bits?/i
|
16
|
+
'7bit'
|
17
|
+
when /8-?bits?/i
|
18
|
+
'8bit'
|
19
|
+
else
|
20
|
+
value
|
23
21
|
end
|
24
22
|
end
|
25
|
-
|
23
|
+
|
24
|
+
def initialize(value = nil, charset = nil)
|
25
|
+
super self.class.normalize_content_transfer_encoding(value), charset
|
26
|
+
end
|
27
|
+
|
26
28
|
def element
|
27
29
|
@element ||= Mail::ContentTransferEncodingElement.new(value)
|
28
30
|
end
|
29
|
-
|
31
|
+
|
30
32
|
def encoding
|
31
33
|
element.encoding
|
32
34
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
|
36
|
+
private
|
37
|
+
def do_encode
|
38
|
+
"#{name}: #{encoding}\r\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_decode
|
42
|
+
encoding
|
43
|
+
end
|
43
44
|
end
|
44
45
|
end
|
@@ -1,52 +1,55 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/fields/named_structured_field'
|
4
|
+
require 'mail/fields/parameter_hash'
|
3
5
|
|
4
6
|
module Mail
|
5
|
-
class ContentTypeField <
|
7
|
+
class ContentTypeField < NamedStructuredField #:nodoc:
|
8
|
+
NAME = 'Content-Type'
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
class << self
|
11
|
+
def singular?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_boundary(type)
|
16
|
+
new "#{type}; boundary=#{generate_boundary}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate_boundary
|
20
|
+
"--==_mimepart_#{Mail.random_tag}"
|
21
|
+
end
|
22
|
+
end
|
9
23
|
|
10
|
-
def initialize(value = nil, charset =
|
11
|
-
|
12
|
-
if value.class == Array
|
24
|
+
def initialize(value = nil, charset = nil)
|
25
|
+
if value.is_a? Array
|
13
26
|
@main_type = value[0]
|
14
27
|
@sub_type = value[1]
|
15
28
|
@parameters = ParameterHash.new.merge!(value.last)
|
16
29
|
else
|
17
30
|
@main_type = nil
|
18
31
|
@sub_type = nil
|
19
|
-
|
20
|
-
value = strip_field(FIELD_NAME, value)
|
32
|
+
value = value.to_s
|
21
33
|
end
|
22
|
-
ensure_filename_quoted(value)
|
23
|
-
super(CAPITALIZED_FIELD, value, charset)
|
24
|
-
self.parse
|
25
|
-
self
|
26
|
-
end
|
27
34
|
|
28
|
-
|
29
|
-
unless val.blank?
|
30
|
-
self.value = val
|
31
|
-
@element = nil
|
32
|
-
element
|
33
|
-
end
|
35
|
+
super ensure_filename_quoted(value), charset
|
34
36
|
end
|
35
37
|
|
36
38
|
def element
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
@element ||=
|
40
|
+
begin
|
41
|
+
Mail::ContentTypeElement.new(value)
|
42
|
+
rescue Mail::Field::ParseError
|
43
|
+
attempt_to_clean
|
44
|
+
end
|
42
45
|
end
|
43
46
|
|
44
47
|
def attempt_to_clean
|
45
48
|
# Sanitize the value, handle special cases
|
46
|
-
|
47
|
-
rescue
|
49
|
+
Mail::ContentTypeElement.new(sanitize(value))
|
50
|
+
rescue Mail::Field::ParseError
|
48
51
|
# All else fails, just get the MIME media type
|
49
|
-
|
52
|
+
Mail::ContentTypeElement.new(get_mime_type(value))
|
50
53
|
end
|
51
54
|
|
52
55
|
def main_type
|
@@ -60,31 +63,22 @@ module Mail
|
|
60
63
|
def string
|
61
64
|
"#{main_type}/#{sub_type}"
|
62
65
|
end
|
66
|
+
alias_method :content_type, :string
|
63
67
|
|
64
68
|
def default
|
65
69
|
decoded
|
66
70
|
end
|
67
71
|
|
68
|
-
alias :content_type :string
|
69
|
-
|
70
72
|
def parameters
|
71
|
-
unless @parameters
|
73
|
+
unless defined? @parameters
|
72
74
|
@parameters = ParameterHash.new
|
73
75
|
element.parameters.each { |p| @parameters.merge!(p) }
|
74
76
|
end
|
75
77
|
@parameters
|
76
78
|
end
|
77
79
|
|
78
|
-
def ContentTypeField.with_boundary(type)
|
79
|
-
new("#{type}; boundary=#{generate_boundary}")
|
80
|
-
end
|
81
|
-
|
82
|
-
def ContentTypeField.generate_boundary
|
83
|
-
"--==_mimepart_#{Mail.random_tag}"
|
84
|
-
end
|
85
|
-
|
86
80
|
def value
|
87
|
-
if @value.
|
81
|
+
if @value.is_a? Array
|
88
82
|
"#{@main_type}/#{@sub_type}; #{stringify(parameters)}"
|
89
83
|
else
|
90
84
|
@value
|
@@ -96,34 +90,17 @@ module Mail
|
|
96
90
|
end
|
97
91
|
|
98
92
|
def filename
|
99
|
-
|
100
|
-
when parameters['filename']
|
101
|
-
@filename = parameters['filename']
|
102
|
-
when parameters['name']
|
103
|
-
@filename = parameters['name']
|
104
|
-
else
|
105
|
-
@filename = nil
|
106
|
-
end
|
107
|
-
@filename
|
93
|
+
@filename ||= parameters['filename'] || parameters['name']
|
108
94
|
end
|
109
95
|
|
110
|
-
# TODO: Fix this up
|
111
96
|
def encoded
|
112
|
-
if parameters.length > 0
|
113
|
-
|
114
|
-
else
|
115
|
-
p = ""
|
116
|
-
end
|
117
|
-
"#{CAPITALIZED_FIELD}: #{content_type}#{p}\r\n"
|
97
|
+
p = ";\r\n\s#{parameters.encoded}" if parameters && parameters.length > 0
|
98
|
+
"#{name}: #{content_type}#{p}\r\n"
|
118
99
|
end
|
119
100
|
|
120
101
|
def decoded
|
121
|
-
if parameters.length > 0
|
122
|
-
|
123
|
-
else
|
124
|
-
p = ""
|
125
|
-
end
|
126
|
-
"#{content_type}" + p
|
102
|
+
p = "; #{parameters.decoded}" if parameters && parameters.length > 0
|
103
|
+
"#{content_type}#{p}"
|
127
104
|
end
|
128
105
|
|
129
106
|
private
|
@@ -139,30 +116,24 @@ module Mail
|
|
139
116
|
|
140
117
|
# Various special cases from random emails found that I am not going to change
|
141
118
|
# the parser for
|
142
|
-
def
|
143
|
-
|
119
|
+
def sanitize(val)
|
144
120
|
# TODO: check if there are cases where whitespace is not a separator
|
145
121
|
val = val.
|
146
122
|
gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
|
147
|
-
|
148
|
-
squeeze(';').
|
149
|
-
gsub(';', '; '). #use '; ' as a separator (or EOL)
|
123
|
+
gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL)
|
150
124
|
gsub(/;\s*$/,'') #remove trailing to keep examples below
|
151
125
|
|
152
|
-
if val =~ /(boundary=(\S*))/i
|
153
|
-
val = "#{$`.downcase}
|
126
|
+
if val =~ /((boundary|name|filename)=(\S*))/i
|
127
|
+
val = "#{$`.downcase}#{$2}=#{$3}#{$'.downcase}"
|
154
128
|
else
|
155
129
|
val.downcase!
|
156
130
|
end
|
157
131
|
|
158
132
|
case
|
159
|
-
when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;;+(.*)$/i
|
160
|
-
# Handles 'text/plain;; format="flowed"' (double semi colon)
|
161
|
-
"#{$1}/#{$2}; #{$3}"
|
162
133
|
when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
|
163
134
|
# Microsoft helper:
|
164
135
|
# Handles 'type/subtype;ISO-8559-1'
|
165
|
-
"#{$1}/#{$2}; charset=#{quote_atom($3)}"
|
136
|
+
"#{$1}/#{$2}; charset=#{Utilities.quote_atom($3)}"
|
166
137
|
when val.chomp =~ /^text;?$/i
|
167
138
|
# Handles 'text;' and 'text'
|
168
139
|
"text/plain;"
|
@@ -171,7 +142,7 @@ module Mail
|
|
171
142
|
"text/plain; #{$2}"
|
172
143
|
when val =~ /([\w\-]+\/[\w\-]+);\scharset="charset="(\w+)""/i
|
173
144
|
# Handles text/html; charset="charset="GB2312""
|
174
|
-
"#{$1}; charset=#{quote_atom($2)}"
|
145
|
+
"#{$1}; charset=#{Utilities.quote_atom($2)}"
|
175
146
|
when val =~ /([\w\-]+\/[\w\-]+);\s+(.*)/i
|
176
147
|
type = $1
|
177
148
|
# Handles misquoted param values
|
@@ -179,19 +150,19 @@ module Mail
|
|
179
150
|
# and: audio/x-midi;\r\n\sname=Part .exe
|
180
151
|
params = $2.to_s.split(/\s+/)
|
181
152
|
params = params.map { |i| i.to_s.chomp.strip }
|
182
|
-
params = params.map { |i| i.split(/\s*\=\s
|
183
|
-
params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
|
153
|
+
params = params.map { |i| i.split(/\s*\=\s*/, 2) }
|
154
|
+
params = params.map { |i| "#{i[0]}=#{Utilities.dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
|
184
155
|
"#{type}; #{params}"
|
185
156
|
when val =~ /^\s*$/
|
186
157
|
'text/plain'
|
187
158
|
else
|
188
|
-
|
159
|
+
val
|
189
160
|
end
|
190
161
|
end
|
191
162
|
|
192
|
-
def get_mime_type(
|
193
|
-
case
|
194
|
-
when
|
163
|
+
def get_mime_type(val)
|
164
|
+
case val
|
165
|
+
when /^([\w\-]+)\/([\w\-]+);.+$/i
|
195
166
|
"#{$1}/#{$2}"
|
196
167
|
else
|
197
168
|
'text/plain'
|