kbaum-mail 2.1.2.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.
- data/CHANGELOG.rdoc +289 -0
- data/README.rdoc +575 -0
- data/Rakefile +72 -0
- data/TODO.rdoc +19 -0
- data/lib/mail.rb +113 -0
- data/lib/mail/attachments_list.rb +76 -0
- data/lib/mail/body.rb +243 -0
- data/lib/mail/configuration.rb +69 -0
- data/lib/mail/core_extensions/nil.rb +11 -0
- data/lib/mail/core_extensions/string.rb +19 -0
- data/lib/mail/elements/address.rb +306 -0
- data/lib/mail/elements/address_list.rb +74 -0
- data/lib/mail/elements/content_disposition_element.rb +30 -0
- data/lib/mail/elements/content_location_element.rb +25 -0
- data/lib/mail/elements/content_transfer_encoding_element.rb +21 -0
- data/lib/mail/elements/content_type_element.rb +35 -0
- data/lib/mail/elements/date_time_element.rb +26 -0
- data/lib/mail/elements/envelope_from_element.rb +34 -0
- data/lib/mail/elements/message_ids_element.rb +29 -0
- data/lib/mail/elements/mime_version_element.rb +26 -0
- data/lib/mail/elements/phrase_list.rb +21 -0
- data/lib/mail/elements/received_element.rb +30 -0
- data/lib/mail/encodings/base64.rb +18 -0
- data/lib/mail/encodings/encodings.rb +201 -0
- data/lib/mail/encodings/quoted_printable.rb +26 -0
- data/lib/mail/envelope.rb +35 -0
- data/lib/mail/field.rb +219 -0
- data/lib/mail/field_list.rb +33 -0
- data/lib/mail/fields/bcc_field.rb +53 -0
- data/lib/mail/fields/cc_field.rb +52 -0
- data/lib/mail/fields/comments_field.rb +41 -0
- data/lib/mail/fields/common/address_container.rb +16 -0
- data/lib/mail/fields/common/common_address.rb +128 -0
- data/lib/mail/fields/common/common_date.rb +51 -0
- data/lib/mail/fields/common/common_field.rb +64 -0
- data/lib/mail/fields/common/common_message_id.rb +57 -0
- data/lib/mail/fields/common/parameter_hash.rb +39 -0
- data/lib/mail/fields/content_description_field.rb +19 -0
- data/lib/mail/fields/content_disposition_field.rb +60 -0
- data/lib/mail/fields/content_id_field.rb +63 -0
- data/lib/mail/fields/content_location_field.rb +42 -0
- data/lib/mail/fields/content_transfer_encoding_field.rb +45 -0
- data/lib/mail/fields/content_type_field.rb +175 -0
- data/lib/mail/fields/date_field.rb +53 -0
- data/lib/mail/fields/from_field.rb +53 -0
- data/lib/mail/fields/in_reply_to_field.rb +52 -0
- data/lib/mail/fields/keywords_field.rb +43 -0
- data/lib/mail/fields/message_id_field.rb +80 -0
- data/lib/mail/fields/mime_version_field.rb +54 -0
- data/lib/mail/fields/optional_field.rb +11 -0
- data/lib/mail/fields/received_field.rb +62 -0
- data/lib/mail/fields/references_field.rb +53 -0
- data/lib/mail/fields/reply_to_field.rb +53 -0
- data/lib/mail/fields/resent_bcc_field.rb +53 -0
- data/lib/mail/fields/resent_cc_field.rb +53 -0
- data/lib/mail/fields/resent_date_field.rb +33 -0
- data/lib/mail/fields/resent_from_field.rb +53 -0
- data/lib/mail/fields/resent_message_id_field.rb +32 -0
- data/lib/mail/fields/resent_sender_field.rb +60 -0
- data/lib/mail/fields/resent_to_field.rb +53 -0
- data/lib/mail/fields/return_path_field.rb +62 -0
- data/lib/mail/fields/sender_field.rb +65 -0
- data/lib/mail/fields/structured_field.rb +36 -0
- data/lib/mail/fields/subject_field.rb +15 -0
- data/lib/mail/fields/to_field.rb +53 -0
- data/lib/mail/fields/unstructured_field.rb +117 -0
- data/lib/mail/header.rb +235 -0
- data/lib/mail/mail.rb +194 -0
- data/lib/mail/message.rb +1780 -0
- data/lib/mail/network/delivery_methods/file_delivery.rb +40 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +62 -0
- data/lib/mail/network/delivery_methods/smtp.rb +110 -0
- data/lib/mail/network/delivery_methods/test_mailer.rb +40 -0
- data/lib/mail/network/retriever_methods/imap.rb +31 -0
- data/lib/mail/network/retriever_methods/pop3.rb +149 -0
- data/lib/mail/parsers/address_lists.rb +61 -0
- data/lib/mail/parsers/address_lists.treetop +19 -0
- data/lib/mail/parsers/content_disposition.rb +369 -0
- data/lib/mail/parsers/content_disposition.treetop +46 -0
- data/lib/mail/parsers/content_location.rb +133 -0
- data/lib/mail/parsers/content_location.treetop +20 -0
- data/lib/mail/parsers/content_transfer_encoding.rb +179 -0
- data/lib/mail/parsers/content_transfer_encoding.treetop +25 -0
- data/lib/mail/parsers/content_type.rb +512 -0
- data/lib/mail/parsers/content_type.treetop +58 -0
- data/lib/mail/parsers/date_time.rb +111 -0
- data/lib/mail/parsers/date_time.treetop +11 -0
- data/lib/mail/parsers/envelope_from.rb +188 -0
- data/lib/mail/parsers/envelope_from.treetop +32 -0
- data/lib/mail/parsers/message_ids.rb +42 -0
- data/lib/mail/parsers/message_ids.treetop +15 -0
- data/lib/mail/parsers/mime_version.rb +141 -0
- data/lib/mail/parsers/mime_version.treetop +19 -0
- data/lib/mail/parsers/phrase_lists.rb +42 -0
- data/lib/mail/parsers/phrase_lists.treetop +15 -0
- data/lib/mail/parsers/received.rb +68 -0
- data/lib/mail/parsers/received.treetop +11 -0
- data/lib/mail/parsers/rfc2045.rb +406 -0
- data/lib/mail/parsers/rfc2045.treetop +35 -0
- data/lib/mail/parsers/rfc2822.rb +5081 -0
- data/lib/mail/parsers/rfc2822.treetop +410 -0
- data/lib/mail/parsers/rfc2822_obsolete.rb +3607 -0
- data/lib/mail/parsers/rfc2822_obsolete.treetop +241 -0
- data/lib/mail/part.rb +82 -0
- data/lib/mail/parts_list.rb +34 -0
- data/lib/mail/patterns.rb +43 -0
- data/lib/mail/utilities.rb +163 -0
- data/lib/mail/vendor/treetop.rb +4 -0
- data/lib/mail/version.rb +10 -0
- data/lib/mail/version_specific/ruby_1_8.rb +84 -0
- data/lib/mail/version_specific/ruby_1_9.rb +77 -0
- data/lib/tasks/corpus.rake +125 -0
- data/lib/tasks/treetop.rake +10 -0
- metadata +188 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class ContentDispositionElement # :nodoc:
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::ContentDispositionParser.new
|
|
9
|
+
if tree = parser.parse(cleaned(string))
|
|
10
|
+
@disposition_type = tree.disposition_type.text_value
|
|
11
|
+
@parameters = tree.parameters
|
|
12
|
+
else
|
|
13
|
+
raise Mail::Field::ParseError, "ContentDispositionElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def disposition_type
|
|
18
|
+
@disposition_type
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parameters
|
|
22
|
+
@parameters
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def cleaned(string)
|
|
26
|
+
string =~ /(.+);\s*$/ ? $1 : string
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class ContentLocationElement # :nodoc:
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::ContentLocationParser.new
|
|
9
|
+
if tree = parser.parse(string)
|
|
10
|
+
@location = tree.location.text_value
|
|
11
|
+
else
|
|
12
|
+
raise Mail::Field::ParseError, "ContentLocationElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def location
|
|
17
|
+
@location
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s(*args)
|
|
21
|
+
location.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class ContentTransferEncodingElement
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::ContentTransferEncodingParser.new
|
|
9
|
+
if tree = parser.parse(string.downcase)
|
|
10
|
+
@encoding = tree.encoding.text_value
|
|
11
|
+
else
|
|
12
|
+
raise Mail::Field::ParseError, "ContentTransferEncodingElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def encoding
|
|
17
|
+
@encoding
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class ContentTypeElement # :nodoc:
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::ContentTypeParser.new
|
|
9
|
+
if tree = parser.parse(cleaned(string))
|
|
10
|
+
@main_type = tree.main_type.text_value
|
|
11
|
+
@sub_type = tree.sub_type.text_value
|
|
12
|
+
@parameters = tree.parameters
|
|
13
|
+
else
|
|
14
|
+
raise Mail::Field::ParseError, "ContentTypeElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def main_type
|
|
19
|
+
@main_type
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def sub_type
|
|
23
|
+
@sub_type
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def parameters
|
|
27
|
+
@parameters
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def cleaned(string)
|
|
31
|
+
string =~ /(.+);\s*$/ ? $1 : string
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class DateTimeElement # :nodoc:
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::DateTimeParser.new
|
|
9
|
+
if tree = parser.parse(string)
|
|
10
|
+
@date_string = tree.date.text_value
|
|
11
|
+
@time_string = tree.time.text_value
|
|
12
|
+
else
|
|
13
|
+
raise Mail::Field::ParseError, "DateTimeElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def date_string
|
|
18
|
+
@date_string
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def time_string
|
|
22
|
+
@time_string
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class EnvelopeFromElement
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::EnvelopeFromParser.new
|
|
9
|
+
if @tree = parser.parse(string)
|
|
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, "EnvelopeFromElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
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
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s(*args)
|
|
30
|
+
"#{@info}; #{@date_time.to_s(*args)}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class MessageIdsElement
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
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, "MessageIdsElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def message_ids
|
|
17
|
+
@message_ids
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def message_id
|
|
21
|
+
@message_ids.first
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def clean_msg_id( val )
|
|
25
|
+
val =~ /.*<(.*)>.*/ ; $1
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class MimeVersionElement
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::MimeVersionParser.new
|
|
9
|
+
if tree = parser.parse(string)
|
|
10
|
+
@major = tree.major.text_value
|
|
11
|
+
@minor = tree.minor.text_value
|
|
12
|
+
else
|
|
13
|
+
raise Mail::Field::ParseError, "MimeVersionElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def major
|
|
18
|
+
@major
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def minor
|
|
22
|
+
@minor
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class PhraseList
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize(string)
|
|
8
|
+
parser = Mail::PhraseListsParser.new
|
|
9
|
+
if tree = parser.parse(string)
|
|
10
|
+
@phrases = tree.phrases
|
|
11
|
+
else
|
|
12
|
+
raise Mail::Field::ParseError, "PhraseList can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def phrases
|
|
17
|
+
@phrases.map { |p| unquote(p.text_value) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
class ReceivedElement
|
|
4
|
+
|
|
5
|
+
include Mail::Utilities
|
|
6
|
+
|
|
7
|
+
def initialize( string )
|
|
8
|
+
parser = Mail::ReceivedParser.new
|
|
9
|
+
if tree = parser.parse(string)
|
|
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
|
|
12
|
+
else
|
|
13
|
+
raise Mail::Field::ParseError, "ReceivedElement can not parse |#{string}|\nReason was: #{parser.failure_reason}\n"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def date_time
|
|
18
|
+
@date_time
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def info
|
|
22
|
+
@info
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_s(*args)
|
|
26
|
+
"#{@info}; #{@date_time.to_s(*args)}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
module Encodings
|
|
4
|
+
class Base64
|
|
5
|
+
|
|
6
|
+
# Decode the string from Base64
|
|
7
|
+
def self.decode(str)
|
|
8
|
+
RubyVer.decode_base64( str )
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Encode the string to Base64
|
|
12
|
+
def self.encode(str)
|
|
13
|
+
RubyVer.encode_base64( str )
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
# Raised when attempting to decode an unknown encoding type
|
|
4
|
+
class UnknownEncodingType < StandardError #:nodoc:
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module Encodings
|
|
8
|
+
|
|
9
|
+
include Mail::Patterns
|
|
10
|
+
|
|
11
|
+
# Is the encoding we want defined?
|
|
12
|
+
#
|
|
13
|
+
# Example:
|
|
14
|
+
#
|
|
15
|
+
# Encodings.defined?(:base64) #=> true
|
|
16
|
+
def Encodings.defined?( str )
|
|
17
|
+
string = str.to_s.split(/[_-]/).map { |v| v.capitalize }.join('')
|
|
18
|
+
RubyVer.has_constant?(Mail::Encodings, string)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Gets a defined encoding type, QuotedPrintable or Base64 for now.
|
|
22
|
+
#
|
|
23
|
+
# Each encoding needs to be defined as a Mail::Encodings::ClassName for
|
|
24
|
+
# this to work, allows us to add other encodings in the future.
|
|
25
|
+
#
|
|
26
|
+
# Example:
|
|
27
|
+
#
|
|
28
|
+
# Encodings.get_encoding(:base64) #=> Mail::Encodings::Base64
|
|
29
|
+
def Encodings.get_encoding( str )
|
|
30
|
+
string = str.to_s.split(/[_-]/).map { |v| v.capitalize }.join('')
|
|
31
|
+
RubyVer.get_constant(Mail::Encodings, string)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Encodes a parameter value using URI Escaping, note the language field 'en' can
|
|
35
|
+
# be set using Mail::Configuration, like so:
|
|
36
|
+
#
|
|
37
|
+
# Mail.defaults.do
|
|
38
|
+
# param_encode_language 'jp'
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
# The character set used for encoding will either be the value of $KCODE for
|
|
42
|
+
# Ruby < 1.9 or the encoding on the string passed in.
|
|
43
|
+
#
|
|
44
|
+
# Example:
|
|
45
|
+
#
|
|
46
|
+
# Mail::Encodings.param_encode("This is fun") #=> "us-ascii'en'This%20is%20fun"
|
|
47
|
+
def Encodings.param_encode(str)
|
|
48
|
+
case
|
|
49
|
+
when str.ascii_only? && str =~ TOKEN_UNSAFE
|
|
50
|
+
%Q{"#{str}"}
|
|
51
|
+
when str.ascii_only?
|
|
52
|
+
str
|
|
53
|
+
else
|
|
54
|
+
RubyVer.param_encode(str)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Decodes a parameter value using URI Escaping.
|
|
59
|
+
#
|
|
60
|
+
# Example:
|
|
61
|
+
#
|
|
62
|
+
# Mail::Encodings.param_decode("This%20is%20fun", 'us-ascii') #=> "This is fun"
|
|
63
|
+
#
|
|
64
|
+
# str = Mail::Encodings.param_decode("This%20is%20fun", 'iso-8559-1')
|
|
65
|
+
# str.encoding #=> 'ISO-8859-1' ## Only on Ruby 1.9
|
|
66
|
+
# str #=> "This is fun"
|
|
67
|
+
def Encodings.param_decode(str, encoding)
|
|
68
|
+
RubyVer.param_decode(str, encoding)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Decodes or encodes a string as needed for either Base64 or QP encoding types in
|
|
72
|
+
# the =?<encoding>?[QB]?<string>?=" format.
|
|
73
|
+
#
|
|
74
|
+
# The output type needs to be :decode to decode the input string or :encode to
|
|
75
|
+
# encode the input string. The character set used for encoding will either be
|
|
76
|
+
# the value of $KCODE for Ruby < 1.9 or the encoding on the string passed in.
|
|
77
|
+
#
|
|
78
|
+
# On encoding, will only send out Base64 encoded strings.
|
|
79
|
+
def Encodings.decode_encode(str, output_type)
|
|
80
|
+
case
|
|
81
|
+
when output_type == :decode
|
|
82
|
+
Encodings.value_decode(str)
|
|
83
|
+
else
|
|
84
|
+
if str.ascii_only?
|
|
85
|
+
str
|
|
86
|
+
else
|
|
87
|
+
Encodings.b_value_encode(str, find_encoding(str))
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Decodes a given string as Base64 or Quoted Printable, depending on what
|
|
93
|
+
# type it is.
|
|
94
|
+
#
|
|
95
|
+
# String has to be of the format =?<encoding>?[QB]?<string>?=
|
|
96
|
+
def Encodings.value_decode(str)
|
|
97
|
+
str.gsub!(/\?=(\s*)=\?/, '?==?') # Remove whitespaces between 'encoded-word's
|
|
98
|
+
str.gsub(/(.*?)(=\?.*?\?.\?.*?\?=)|$/m) do
|
|
99
|
+
before = $1.to_s
|
|
100
|
+
text = $2.to_s
|
|
101
|
+
|
|
102
|
+
case
|
|
103
|
+
when text =~ /=\?.+\?[Bb]\?/m
|
|
104
|
+
before + b_value_decode(text)
|
|
105
|
+
when text =~ /=\?.+\?[Qq]\?/m
|
|
106
|
+
before + q_value_decode(text)
|
|
107
|
+
else
|
|
108
|
+
before + text
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Takes an encoded string of the format =?<encoding>?[QB]?<string>?=
|
|
114
|
+
def Encodings.unquote_and_convert_to(str, to_encoding)
|
|
115
|
+
original_encoding, string = split_encoding_from_string( str )
|
|
116
|
+
|
|
117
|
+
output = value_decode( str ).to_s
|
|
118
|
+
|
|
119
|
+
if original_encoding.to_s.downcase.gsub("-", "") == to_encoding.to_s.downcase.gsub("-", "")
|
|
120
|
+
output
|
|
121
|
+
elsif original_encoding && to_encoding
|
|
122
|
+
begin
|
|
123
|
+
require 'iconv'
|
|
124
|
+
Iconv.iconv(to_encoding, original_encoding, output).first
|
|
125
|
+
rescue Iconv::IllegalSequence, Iconv::InvalidEncoding, Errno::EINVAL
|
|
126
|
+
# the 'from' parameter specifies a charset other than what the text
|
|
127
|
+
# actually is...not much we can do in this case but just return the
|
|
128
|
+
# unconverted text.
|
|
129
|
+
#
|
|
130
|
+
# Ditto if either parameter represents an unknown charset, like
|
|
131
|
+
# X-UNKNOWN.
|
|
132
|
+
output
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
output
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Encode a string with Base64 Encoding and returns it ready to be inserted
|
|
140
|
+
# as a value for a field, that is, in the =?<charset>?B?<string>?= format
|
|
141
|
+
#
|
|
142
|
+
# Example:
|
|
143
|
+
#
|
|
144
|
+
# Encodings.b_value_encode('This is あ string', 'UTF-8')
|
|
145
|
+
# #=> "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?="
|
|
146
|
+
def Encodings.b_value_encode(str, encoding = nil)
|
|
147
|
+
string, encoding = RubyVer.b_value_encode(str, encoding)
|
|
148
|
+
string.split("\n").map do |str|
|
|
149
|
+
"=?#{encoding}?B?#{str.chomp}?="
|
|
150
|
+
end.join(" ")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Encode a string with Quoted-Printable Encoding and returns it ready to be inserted
|
|
154
|
+
# as a value for a field, that is, in the =?<charset>?Q?<string>?= format
|
|
155
|
+
#
|
|
156
|
+
# Example:
|
|
157
|
+
#
|
|
158
|
+
# Encodings.q_value_encode('This is あ string', 'UTF-8')
|
|
159
|
+
# #=> "=?UTF-8?Q?This_is_=E3=81=82_string?="
|
|
160
|
+
def Encodings.q_value_encode(str, encoding = nil)
|
|
161
|
+
string, encoding = RubyVer.q_value_encode(str, encoding)
|
|
162
|
+
"=?#{encoding}?Q?#{string.chomp.gsub(/ /, '_')}?="
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
# Decodes a Base64 string from the "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=" format
|
|
168
|
+
#
|
|
169
|
+
# Example:
|
|
170
|
+
#
|
|
171
|
+
# Encodings.b_value_encode("=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=")
|
|
172
|
+
# #=> 'This is あ string'
|
|
173
|
+
def Encodings.b_value_decode(str)
|
|
174
|
+
RubyVer.b_value_decode(str)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Decodes a Quoted-Printable string from the "=?UTF-8?Q?This_is_=E3=81=82_string?=" format
|
|
178
|
+
#
|
|
179
|
+
# Example:
|
|
180
|
+
#
|
|
181
|
+
# Encodings.b_value_encode("=?UTF-8?Q?This_is_=E3=81=82_string?=")
|
|
182
|
+
# #=> 'This is あ string'
|
|
183
|
+
def Encodings.q_value_decode(str)
|
|
184
|
+
RubyVer.q_value_decode(str).gsub(/_/, ' ')
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def Encodings.split_encoding_from_string( str )
|
|
188
|
+
match = str.match(/\=\?(.+)?\?[QB]\?(.+)?\?\=/mi)
|
|
189
|
+
if match
|
|
190
|
+
[match[1], match[2]]
|
|
191
|
+
else
|
|
192
|
+
nil
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def Encodings.find_encoding(str)
|
|
197
|
+
RUBY_VERSION >= '1.9' ? str.encoding : $KCODE
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
201
|
+
end
|