mail 2.5.5 → 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 +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
@@ -1,35 +1,25 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/content_type_parser'
|
4
|
+
|
2
5
|
module Mail
|
3
|
-
class ContentTypeElement
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@sub_type = tree.sub_type.text_value.downcase
|
12
|
-
@parameters = tree.parameters
|
13
|
-
else
|
14
|
-
raise Mail::Field::ParseError.new(ContentTypeElement, string, parser.failure_reason)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def main_type
|
19
|
-
@main_type
|
20
|
-
end
|
21
|
-
|
22
|
-
def sub_type
|
23
|
-
@sub_type
|
6
|
+
class ContentTypeElement #:nodoc:
|
7
|
+
attr_reader :main_type, :sub_type, :parameters
|
8
|
+
|
9
|
+
def initialize(string)
|
10
|
+
content_type = Mail::Parsers::ContentTypeParser.parse(cleaned(string))
|
11
|
+
@main_type = content_type.main_type
|
12
|
+
@sub_type = content_type.sub_type
|
13
|
+
@parameters = content_type.parameters
|
24
14
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
15
|
+
|
16
|
+
private
|
17
|
+
def cleaned(string)
|
18
|
+
if string =~ /;\s*$/
|
19
|
+
$`
|
20
|
+
else
|
21
|
+
string
|
22
|
+
end
|
23
|
+
end
|
34
24
|
end
|
35
25
|
end
|
@@ -1,26 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/date_time_parser'
|
4
|
+
|
2
5
|
module Mail
|
3
|
-
class DateTimeElement
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@date_string = tree.date.text_value
|
11
|
-
@time_string = tree.time.text_value
|
12
|
-
else
|
13
|
-
raise Mail::Field::ParseError.new(DateTimeElement, string, parser.failure_reason)
|
14
|
-
end
|
6
|
+
class DateTimeElement #:nodoc:
|
7
|
+
attr_reader :date_string, :time_string
|
8
|
+
|
9
|
+
def initialize(string)
|
10
|
+
date_time = Mail::Parsers::DateTimeParser.parse(string)
|
11
|
+
@date_string = date_time.date_string
|
12
|
+
@time_string = date_time.time_string
|
15
13
|
end
|
16
|
-
|
17
|
-
def date_string
|
18
|
-
@date_string
|
19
|
-
end
|
20
|
-
|
21
|
-
def time_string
|
22
|
-
@time_string
|
23
|
-
end
|
24
|
-
|
25
14
|
end
|
26
15
|
end
|
@@ -1,47 +1,39 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/envelope_from_parser'
|
4
|
+
require 'date'
|
5
|
+
|
2
6
|
module Mail
|
3
|
-
class EnvelopeFromElement
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@address = tree.addr_spec.text_value.strip
|
11
|
-
@date_time = ::DateTime.parse("#{tree.ctime_date.text_value}")
|
12
|
-
else
|
13
|
-
raise Mail::Field::ParseError.new(EnvelopeFromElement, string, parser.failure_reason)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def tree
|
18
|
-
@tree
|
19
|
-
end
|
20
|
-
|
21
|
-
def date_time
|
22
|
-
@date_time
|
23
|
-
end
|
24
|
-
|
25
|
-
def address
|
26
|
-
@address
|
7
|
+
class EnvelopeFromElement #:nodoc:
|
8
|
+
attr_reader :date_time, :address
|
9
|
+
|
10
|
+
def initialize(string)
|
11
|
+
envelope_from = Mail::Parsers::EnvelopeFromParser.parse(string)
|
12
|
+
@address = envelope_from.address
|
13
|
+
@date_time = ::DateTime.parse(envelope_from.ctime_date) if envelope_from.ctime_date
|
27
14
|
end
|
28
|
-
|
15
|
+
|
29
16
|
# RFC 4155:
|
30
17
|
# a timestamp indicating the UTC date and time when the message
|
31
18
|
# was originally received, conformant with the syntax of the
|
32
19
|
# traditional UNIX 'ctime' output sans timezone (note that the
|
33
20
|
# use of UTC precludes the need for a timezone indicator);
|
34
21
|
def formatted_date_time
|
35
|
-
if
|
36
|
-
|
37
|
-
|
38
|
-
|
22
|
+
if date_time
|
23
|
+
if date_time.respond_to?(:ctime)
|
24
|
+
date_time.ctime
|
25
|
+
else
|
26
|
+
date_time.strftime '%a %b %e %T %Y'
|
27
|
+
end
|
39
28
|
end
|
40
29
|
end
|
41
30
|
|
42
31
|
def to_s
|
43
|
-
|
32
|
+
if date_time
|
33
|
+
"#{address} #{formatted_date_time}"
|
34
|
+
else
|
35
|
+
address
|
36
|
+
end
|
44
37
|
end
|
45
|
-
|
46
38
|
end
|
47
39
|
end
|
@@ -1,29 +1,31 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/message_ids_parser'
|
4
|
+
require 'mail/utilities'
|
5
|
+
|
2
6
|
module Mail
|
3
|
-
class MessageIdsElement
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(string)
|
8
|
-
parser = Mail::MessageIdsParser.new
|
9
|
-
if tree = parser.parse(string)
|
10
|
-
@message_ids = tree.message_ids.map { |msg_id| clean_msg_id(msg_id.text_value) }
|
11
|
-
else
|
12
|
-
raise Mail::Field::ParseError.new(MessageIdsElement, string, parser.failure_reason)
|
13
|
-
end
|
7
|
+
class MessageIdsElement #:nodoc:
|
8
|
+
def self.parse(string)
|
9
|
+
new(string).tap(&:message_ids)
|
14
10
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
|
12
|
+
attr_reader :message_ids
|
13
|
+
|
14
|
+
def initialize(string)
|
15
|
+
@message_ids = parse(string)
|
18
16
|
end
|
19
|
-
|
17
|
+
|
20
18
|
def message_id
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def clean_msg_id( val )
|
25
|
-
val =~ /.*<(.*)>.*/ ; $1
|
19
|
+
message_ids.first
|
26
20
|
end
|
27
21
|
|
22
|
+
private
|
23
|
+
def parse(string)
|
24
|
+
if Utilities.blank? string
|
25
|
+
[]
|
26
|
+
else
|
27
|
+
Mail::Parsers::MessageIdsParser.parse(string).message_ids
|
28
|
+
end
|
29
|
+
end
|
28
30
|
end
|
29
31
|
end
|
@@ -1,26 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/mime_version_parser'
|
4
|
+
|
2
5
|
module Mail
|
3
|
-
class MimeVersionElement
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@major = tree.major.text_value
|
11
|
-
@minor = tree.minor.text_value
|
12
|
-
else
|
13
|
-
raise Mail::Field::ParseError.new(MimeVersionElement, string, parser.failure_reason)
|
14
|
-
end
|
6
|
+
class MimeVersionElement #:nodoc:
|
7
|
+
attr_reader :major, :minor
|
8
|
+
|
9
|
+
def initialize(string)
|
10
|
+
mime_version = Mail::Parsers::MimeVersionParser.parse(string)
|
11
|
+
@major = mime_version.major
|
12
|
+
@minor = mime_version.minor
|
15
13
|
end
|
16
|
-
|
17
|
-
def major
|
18
|
-
@major
|
19
|
-
end
|
20
|
-
|
21
|
-
def minor
|
22
|
-
@minor
|
23
|
-
end
|
24
|
-
|
25
14
|
end
|
26
15
|
end
|
@@ -1,21 +1,19 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/phrase_lists_parser'
|
4
|
+
require 'mail/utilities'
|
5
|
+
|
2
6
|
module Mail
|
3
|
-
class PhraseList
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
+
class PhraseList #:nodoc:
|
8
|
+
attr_reader :phrases
|
9
|
+
|
7
10
|
def initialize(string)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
@phrases =
|
12
|
+
if Utilities.blank? string
|
13
|
+
[]
|
14
|
+
else
|
15
|
+
Mail::Parsers::PhraseListsParser.parse(string).phrases.map { |p| Mail::Utilities.unquote(p) }
|
16
|
+
end
|
14
17
|
end
|
15
|
-
|
16
|
-
def phrases
|
17
|
-
@phrases.map { |p| unquote(p.text_value) }
|
18
|
-
end
|
19
|
-
|
20
18
|
end
|
21
19
|
end
|
@@ -1,30 +1,35 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/parsers/received_parser'
|
4
|
+
require 'mail/utilities'
|
5
|
+
require 'date'
|
6
|
+
|
2
7
|
module Mail
|
3
|
-
class ReceivedElement
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@date_time = ::DateTime.parse("#{tree.date_time.date.text_value} #{tree.date_time.time.text_value}")
|
11
|
-
@info = tree.name_val_list.text_value
|
8
|
+
class ReceivedElement #:nodoc:
|
9
|
+
attr_reader :info, :date_time
|
10
|
+
|
11
|
+
def initialize(string)
|
12
|
+
if Utilities.blank? string
|
13
|
+
@date_time = nil
|
14
|
+
@info = nil
|
12
15
|
else
|
13
|
-
|
16
|
+
received = Mail::Parsers::ReceivedParser.parse(string)
|
17
|
+
@date_time = datetime_for(received)
|
18
|
+
@info = received.info
|
14
19
|
end
|
15
20
|
end
|
16
|
-
|
17
|
-
def date_time
|
18
|
-
@date_time
|
19
|
-
end
|
20
|
-
|
21
|
-
def info
|
22
|
-
@info
|
23
|
-
end
|
24
|
-
|
21
|
+
|
25
22
|
def to_s(*args)
|
26
|
-
"#{
|
23
|
+
"#{info}; #{date_time.to_s(*args)}"
|
27
24
|
end
|
28
|
-
|
25
|
+
|
26
|
+
private
|
27
|
+
def datetime_for(received)
|
28
|
+
::DateTime.parse("#{received.date} #{received.time}")
|
29
|
+
rescue ArgumentError => e
|
30
|
+
raise e unless e.message == 'invalid date'
|
31
|
+
warn "WARNING: Invalid date field for received element (#{received.date} #{received.time}): #{e.class}: #{e.message}"
|
32
|
+
nil
|
33
|
+
end
|
29
34
|
end
|
30
35
|
end
|
data/lib/mail/elements.rb
CHANGED
data/lib/mail/encodings/7bit.rb
CHANGED
@@ -1,31 +1,27 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
require 'mail/encodings/8bit'
|
3
4
|
|
4
5
|
module Mail
|
5
6
|
module Encodings
|
7
|
+
# 7bit and 8bit are equivalent. 7bit encoding is for text only.
|
6
8
|
class SevenBit < EightBit
|
7
9
|
NAME = '7bit'
|
8
|
-
|
9
10
|
PRIORITY = 1
|
11
|
+
Encodings.register(NAME, self)
|
10
12
|
|
11
|
-
# 7bit and 8bit operate the same
|
12
|
-
|
13
|
-
# Decode the string
|
14
13
|
def self.decode(str)
|
15
|
-
|
14
|
+
::Mail::Utilities.binary_unsafe_to_lf str
|
16
15
|
end
|
17
|
-
|
18
|
-
# Encode the string
|
16
|
+
|
19
17
|
def self.encode(str)
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
# Idenity encodings have a fixed cost, 1 byte out per 1 byte in
|
24
|
-
def self.cost(str)
|
25
|
-
super
|
18
|
+
::Mail::Utilities.binary_unsafe_to_crlf str
|
26
19
|
end
|
27
20
|
|
28
|
-
|
21
|
+
# Per RFC 2045 2.7. 7bit Data, No octets with decimal values greater than 127 are allowed.
|
22
|
+
def self.compatible_input?(str)
|
23
|
+
str.ascii_only? && super
|
24
|
+
end
|
29
25
|
end
|
30
26
|
end
|
31
27
|
end
|
data/lib/mail/encodings/8bit.rb
CHANGED
@@ -1,31 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
require 'mail/encodings/binary'
|
3
4
|
|
4
5
|
module Mail
|
5
6
|
module Encodings
|
6
7
|
class EightBit < Binary
|
7
8
|
NAME = '8bit'
|
8
|
-
|
9
9
|
PRIORITY = 4
|
10
|
+
Encodings.register(NAME, self)
|
10
11
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
def self.decode(str)
|
15
|
-
str.to_lf
|
16
|
-
end
|
17
|
-
|
18
|
-
# Encode the string
|
19
|
-
def self.encode(str)
|
20
|
-
str.to_crlf
|
12
|
+
# Per RFC 2821 4.5.3.1, SMTP lines may not be longer than 1000 octets including the <CRLF>.
|
13
|
+
def self.compatible_input?(str)
|
14
|
+
!str.lines.find { |line| line.bytesize > 998 }
|
21
15
|
end
|
22
|
-
|
23
|
-
# Idenity encodings have a fixed cost, 1 byte out per 1 byte in
|
24
|
-
def self.cost(str)
|
25
|
-
1.0
|
26
|
-
end
|
27
|
-
|
28
|
-
Encodings.register(NAME, self)
|
29
16
|
end
|
30
17
|
end
|
31
18
|
end
|
@@ -1,33 +1,38 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
require 'mail/encodings/7bit'
|
3
4
|
|
4
5
|
module Mail
|
5
6
|
module Encodings
|
7
|
+
# Base64 encoding handles binary content at the cost of 4 output bytes
|
8
|
+
# per input byte.
|
6
9
|
class Base64 < SevenBit
|
7
10
|
NAME = 'base64'
|
8
|
-
|
9
11
|
PRIORITY = 3
|
10
|
-
|
12
|
+
Encodings.register(NAME, self)
|
13
|
+
|
11
14
|
def self.can_encode?(enc)
|
12
15
|
true
|
13
16
|
end
|
14
17
|
|
15
|
-
# Decode the string from Base64
|
16
18
|
def self.decode(str)
|
17
|
-
|
19
|
+
Utilities.decode_base64(str)
|
18
20
|
end
|
19
|
-
|
20
|
-
# Encode the string to Base64
|
21
|
+
|
21
22
|
def self.encode(str)
|
22
|
-
|
23
|
+
::Mail::Utilities.binary_unsafe_to_crlf(Utilities.encode_base64(str))
|
23
24
|
end
|
24
25
|
|
25
|
-
#
|
26
|
+
# 3 bytes in -> 4 bytes out
|
26
27
|
def self.cost(str)
|
27
|
-
4.0/3
|
28
|
+
4.0 / 3
|
28
29
|
end
|
29
30
|
|
30
|
-
|
31
|
+
# Ruby Base64 inserts newlines automatically, so it doesn't exceed
|
32
|
+
# SMTP line length limits.
|
33
|
+
def self.compatible_input?(str)
|
34
|
+
true
|
35
|
+
end
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -1,31 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/encodings/identity'
|
3
4
|
|
4
5
|
module Mail
|
5
6
|
module Encodings
|
6
|
-
class Binary <
|
7
|
+
class Binary < Identity
|
7
8
|
NAME = 'binary'
|
8
|
-
|
9
9
|
PRIORITY = 5
|
10
|
-
|
11
|
-
# Binary is an identiy encoding, meaning nothing to do
|
12
|
-
|
13
|
-
# Decode the string
|
14
|
-
def self.decode(str)
|
15
|
-
str
|
16
|
-
end
|
17
|
-
|
18
|
-
# Encode the string
|
19
|
-
def self.encode(str)
|
20
|
-
str
|
21
|
-
end
|
22
|
-
|
23
|
-
# Idenity encodings have a fixed cost, 1 byte out per 1 byte in
|
24
|
-
def self.cost(str)
|
25
|
-
1.0
|
26
|
-
end
|
27
|
-
|
28
|
-
Encodings.register(NAME, self)
|
10
|
+
Encodings.register(NAME, self)
|
29
11
|
end
|
30
12
|
end
|
31
13
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'mail/encodings/transfer_encoding'
|
4
|
+
|
5
|
+
module Mail
|
6
|
+
module Encodings
|
7
|
+
# Identity encodings do no encoding/decoding and have a fixed cost:
|
8
|
+
# 1 byte in -> 1 byte out.
|
9
|
+
class Identity < TransferEncoding #:nodoc:
|
10
|
+
def self.decode(str)
|
11
|
+
str
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.encode(str)
|
15
|
+
str
|
16
|
+
end
|
17
|
+
|
18
|
+
# 1 output byte per input byte.
|
19
|
+
def self.cost(str)
|
20
|
+
1.0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,36 +1,42 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
require 'mail/encodings/7bit'
|
3
4
|
|
4
5
|
module Mail
|
5
6
|
module Encodings
|
6
7
|
class QuotedPrintable < SevenBit
|
7
8
|
NAME='quoted-printable'
|
8
|
-
|
9
|
+
|
9
10
|
PRIORITY = 2
|
10
11
|
|
11
|
-
def self.can_encode?(
|
12
|
-
EightBit.can_encode?
|
12
|
+
def self.can_encode?(enc)
|
13
|
+
EightBit.can_encode? enc
|
13
14
|
end
|
14
15
|
|
15
16
|
# Decode the string from Quoted-Printable. Cope with hard line breaks
|
16
17
|
# that were incorrectly encoded as hex instead of literal CRLF.
|
17
18
|
def self.decode(str)
|
18
|
-
str.gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack("M*").first
|
19
|
+
::Mail::Utilities.to_lf ::Mail::Utilities.to_crlf(str).gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack("M*").first
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.encode(str)
|
22
|
-
[
|
23
|
+
::Mail::Utilities.to_crlf [::Mail::Utilities.to_lf(str)].pack("M")
|
23
24
|
end
|
24
25
|
|
25
26
|
def self.cost(str)
|
26
27
|
# These bytes probably do not need encoding
|
27
28
|
c = str.count("\x9\xA\xD\x20-\x3C\x3E-\x7E")
|
28
|
-
# Everything else turns into =XX where XX is a
|
29
|
+
# Everything else turns into =XX where XX is a
|
29
30
|
# two digit hex number (taking 3 bytes)
|
30
31
|
total = (str.bytesize - c)*3 + c
|
31
32
|
total.to_f/str.bytesize
|
32
33
|
end
|
33
|
-
|
34
|
+
|
35
|
+
# QP inserts newlines automatically and cannot violate the SMTP spec.
|
36
|
+
def self.compatible_input?(str)
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
34
40
|
private
|
35
41
|
|
36
42
|
Encodings.register(NAME, self)
|