mail 2.6.6 → 2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +134 -119
- data/lib/mail/attachments_list.rb +10 -9
- data/lib/mail/body.rb +73 -84
- data/lib/mail/check_delivery_params.rb +28 -21
- data/lib/mail/configuration.rb +2 -0
- data/lib/mail/constants.rb +27 -5
- data/lib/mail/elements/address.rb +53 -47
- 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 +3 -1
- data/lib/mail/encodings.rb +81 -54
- data/lib/mail/envelope.rb +11 -14
- data/lib/mail/field.rb +119 -98
- data/lib/mail/field_list.rb +60 -7
- data/lib/mail/fields/bcc_field.rb +34 -52
- data/lib/mail/fields/cc_field.rb +28 -49
- data/lib/mail/fields/comments_field.rb +27 -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 +7 -14
- data/lib/mail/fields/content_disposition_field.rb +13 -38
- data/lib/mail/fields/content_id_field.rb +24 -51
- data/lib/mail/fields/content_location_field.rb +11 -25
- data/lib/mail/fields/content_transfer_encoding_field.rb +31 -31
- data/lib/mail/fields/content_type_field.rb +50 -80
- data/lib/mail/fields/date_field.rb +23 -52
- data/lib/mail/fields/from_field.rb +28 -49
- data/lib/mail/fields/in_reply_to_field.rb +38 -49
- data/lib/mail/fields/keywords_field.rb +18 -31
- data/lib/mail/fields/message_id_field.rb +25 -71
- data/lib/mail/fields/mime_version_field.rb +19 -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 +9 -7
- data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +13 -11
- data/lib/mail/fields/received_field.rb +43 -57
- data/lib/mail/fields/references_field.rb +35 -49
- data/lib/mail/fields/reply_to_field.rb +28 -49
- data/lib/mail/fields/resent_bcc_field.rb +28 -49
- data/lib/mail/fields/resent_cc_field.rb +28 -49
- data/lib/mail/fields/resent_date_field.rb +5 -30
- data/lib/mail/fields/resent_from_field.rb +28 -49
- data/lib/mail/fields/resent_message_id_field.rb +5 -29
- data/lib/mail/fields/resent_sender_field.rb +27 -56
- data/lib/mail/fields/resent_to_field.rb +28 -49
- data/lib/mail/fields/return_path_field.rb +50 -54
- data/lib/mail/fields/sender_field.rb +34 -55
- data/lib/mail/fields/structured_field.rb +3 -30
- data/lib/mail/fields/subject_field.rb +9 -11
- data/lib/mail/fields/to_field.rb +28 -49
- data/lib/mail/fields/unstructured_field.rb +32 -47
- data/lib/mail/header.rb +71 -110
- data/lib/mail/mail.rb +2 -10
- data/lib/mail/matchers/attachment_matchers.rb +15 -0
- data/lib/mail/matchers/has_sent_mail.rb +21 -1
- data/lib/mail/message.rb +113 -117
- data/lib/mail/multibyte/chars.rb +21 -178
- data/lib/mail/multibyte/unicode.rb +10 -10
- data/lib/mail/multibyte/utils.rb +26 -43
- data/lib/mail/multibyte.rb +55 -16
- data/lib/mail/network/delivery_methods/exim.rb +5 -4
- data/lib/mail/network/delivery_methods/file_delivery.rb +11 -10
- data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +62 -21
- data/lib/mail/network/delivery_methods/smtp.rb +75 -50
- data/lib/mail/network/delivery_methods/smtp_connection.rb +3 -4
- data/lib/mail/network/delivery_methods/test_mailer.rb +4 -2
- data/lib/mail/network/retriever_methods/base.rb +8 -8
- data/lib/mail/network/retriever_methods/imap.rb +20 -7
- data/lib/mail/network/retriever_methods/pop3.rb +5 -3
- data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
- data/lib/mail/network.rb +1 -0
- data/lib/mail/parser_tools.rb +15 -0
- data/lib/mail/parsers/address_lists_parser.rb +33225 -116
- data/lib/mail/parsers/address_lists_parser.rl +179 -0
- data/lib/mail/parsers/content_disposition_parser.rb +882 -49
- data/lib/mail/parsers/content_disposition_parser.rl +89 -0
- data/lib/mail/parsers/content_location_parser.rb +809 -23
- data/lib/mail/parsers/content_location_parser.rl +78 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +509 -21
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
- data/lib/mail/parsers/content_type_parser.rb +1037 -56
- data/lib/mail/parsers/content_type_parser.rl +90 -0
- data/lib/mail/parsers/date_time_parser.rb +877 -25
- data/lib/mail/parsers/date_time_parser.rl +69 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3669 -40
- data/lib/mail/parsers/envelope_from_parser.rl +89 -0
- data/lib/mail/parsers/message_ids_parser.rb +5146 -25
- data/lib/mail/parsers/message_ids_parser.rl +93 -0
- data/lib/mail/parsers/mime_version_parser.rb +497 -26
- data/lib/mail/parsers/mime_version_parser.rl +68 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +870 -22
- data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
- data/lib/mail/parsers/received_parser.rb +8776 -43
- 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 +11 -25
- data/lib/mail/part.rb +6 -10
- data/lib/mail/parts_list.rb +62 -6
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +343 -74
- data/lib/mail/version.rb +2 -2
- data/lib/mail/yaml.rb +30 -0
- data/lib/mail.rb +5 -35
- metadata +111 -66
- data/CHANGELOG.rdoc +0 -803
- data/CONTRIBUTING.md +0 -60
- data/Dependencies.txt +0 -2
- data/Gemfile +0 -14
- data/Rakefile +0 -29
- data/TODO.rdoc +0 -9
- 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 -226
@@ -1,37 +0,0 @@
|
|
1
|
-
%%{
|
2
|
-
machine received;
|
3
|
-
|
4
|
-
include rb_actions "rb_actions.rl";
|
5
|
-
include common "../../common.rl";
|
6
|
-
|
7
|
-
getkey data_unpacked[p];
|
8
|
-
|
9
|
-
main := received;
|
10
|
-
}%%
|
11
|
-
|
12
|
-
module Mail
|
13
|
-
module Parsers
|
14
|
-
module Ragel
|
15
|
-
module ReceivedMachine
|
16
|
-
%%write data;
|
17
|
-
|
18
|
-
def self.parse(data)
|
19
|
-
p = 0
|
20
|
-
eof = data.length
|
21
|
-
stack = []
|
22
|
-
|
23
|
-
actions = []
|
24
|
-
data_unpacked = data.bytes.to_a
|
25
|
-
%%write init;
|
26
|
-
%%write exec;
|
27
|
-
|
28
|
-
if p == eof && cs >= %%{ write first_final; }%%
|
29
|
-
return actions, nil
|
30
|
-
else
|
31
|
-
return [], "Only able to parse up to #{data[0..p]}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
%%{
|
2
|
-
machine <%= parser_name %>;
|
3
|
-
|
4
|
-
include rb_actions "rb_actions.rl";
|
5
|
-
include common "../../common.rl";
|
6
|
-
|
7
|
-
getkey data_unpacked[p];
|
8
|
-
|
9
|
-
main := <%= parser_name %>;
|
10
|
-
}%%
|
11
|
-
|
12
|
-
module Mail
|
13
|
-
module Parsers
|
14
|
-
module Ragel
|
15
|
-
module <%= parser_name_cc %>
|
16
|
-
%%write data;
|
17
|
-
|
18
|
-
def self.parse(data)
|
19
|
-
p = 0
|
20
|
-
eof = data.length
|
21
|
-
stack = []
|
22
|
-
|
23
|
-
actions = []
|
24
|
-
data_unpacked = data.bytes.to_a
|
25
|
-
%%write init;
|
26
|
-
%%write exec;
|
27
|
-
|
28
|
-
if p == eof && cs >= %%{ write first_final; }%%
|
29
|
-
return actions, nil
|
30
|
-
else
|
31
|
-
return [], "Only able to parse up to #{data[0..p]}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Mail
|
2
|
-
module Parsers
|
3
|
-
module Ragel
|
4
|
-
module Ruby
|
5
|
-
def self.silence_warnings
|
6
|
-
old, $VERBOSE = $VERBOSE, nil
|
7
|
-
yield
|
8
|
-
ensure
|
9
|
-
$VERBOSE = old
|
10
|
-
end
|
11
|
-
|
12
|
-
# Ragel-generated parsers give a lot of warnings
|
13
|
-
# and may cause logs to balloon in size
|
14
|
-
silence_warnings do
|
15
|
-
Mail::Parsers::Ragel::FIELD_PARSERS.each do |field_parser|
|
16
|
-
require "mail/parsers/ragel/ruby/machines/#{field_parser}_machine"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
MACHINE_LIST = {
|
21
|
-
:address_lists => AddressListsMachine,
|
22
|
-
:phrase_lists => PhraseListsMachine,
|
23
|
-
:date_time => DateTimeMachine,
|
24
|
-
:received => ReceivedMachine,
|
25
|
-
:message_ids => MessageIdsMachine,
|
26
|
-
:envelope_from => EnvelopeFromMachine,
|
27
|
-
:mime_version => MimeVersionMachine,
|
28
|
-
:content_type => ContentTypeMachine,
|
29
|
-
:content_disposition => ContentDispositionMachine,
|
30
|
-
:content_transfer_encoding => ContentTransferEncodingMachine,
|
31
|
-
:content_location => ContentLocationMachine
|
32
|
-
}
|
33
|
-
|
34
|
-
def self.parse(machine, string)
|
35
|
-
MACHINE_LIST[machine].parse(string)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/lib/mail/parsers/ragel.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Mail
|
3
|
-
module Parsers
|
4
|
-
module Ragel
|
5
|
-
require 'mail/parsers/ragel/parser_info'
|
6
|
-
require "mail/parsers/ragel/ruby"
|
7
|
-
|
8
|
-
def self.parse(machine, string)
|
9
|
-
@machine_module ||= Ruby
|
10
|
-
@machine_module.parse(machine, string)
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.machine_module=(m)
|
14
|
-
@machine_module = m
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module Mail
|
5
|
-
class Ruby18
|
6
|
-
require 'base64'
|
7
|
-
require 'iconv'
|
8
|
-
|
9
|
-
# Escapes any parenthesis in a string that are unescaped. This can't
|
10
|
-
# use the Ruby 1.9.1 regexp feature of negative look behind so we have
|
11
|
-
# to do two replacement, first unescape everything, then re-escape it
|
12
|
-
def Ruby18.escape_paren( str )
|
13
|
-
re = /\\\)/
|
14
|
-
str = str.gsub(re) { |s| ')'}
|
15
|
-
re = /\\\(/
|
16
|
-
str = str.gsub(re) { |s| '('}
|
17
|
-
re = /([\(\)])/ # Only match unescaped parens
|
18
|
-
str.gsub(re) { |s| '\\' + s }
|
19
|
-
end
|
20
|
-
|
21
|
-
def Ruby18.paren( str )
|
22
|
-
str = $1 if str =~ /^\((.*)?\)$/
|
23
|
-
str = escape_paren( str )
|
24
|
-
'(' + str + ')'
|
25
|
-
end
|
26
|
-
|
27
|
-
def Ruby18.escape_bracket( str )
|
28
|
-
re = /\\\>/
|
29
|
-
str = str.gsub(re) { |s| '>'}
|
30
|
-
re = /\\\</
|
31
|
-
str = str.gsub(re) { |s| '<'}
|
32
|
-
re = /([\<\>])/ # Only match unescaped parens
|
33
|
-
str.gsub(re) { |s| '\\' + s }
|
34
|
-
end
|
35
|
-
|
36
|
-
def Ruby18.bracket( str )
|
37
|
-
str = $1 if str =~ /^\<(.*)?\>$/
|
38
|
-
str = escape_bracket( str )
|
39
|
-
'<' + str + '>'
|
40
|
-
end
|
41
|
-
|
42
|
-
def Ruby18.decode_base64(str)
|
43
|
-
Base64.decode64(str) if str
|
44
|
-
end
|
45
|
-
|
46
|
-
def Ruby18.encode_base64(str)
|
47
|
-
Base64.encode64(str)
|
48
|
-
end
|
49
|
-
|
50
|
-
def Ruby18.has_constant?(klass, string)
|
51
|
-
klass.constants.include?( string )
|
52
|
-
end
|
53
|
-
|
54
|
-
def Ruby18.get_constant(klass, string)
|
55
|
-
klass.const_get( string )
|
56
|
-
end
|
57
|
-
|
58
|
-
def Ruby18.transcode_charset(str, from_encoding, to_encoding = 'UTF-8')
|
59
|
-
Iconv.conv("#{normalize_iconv_charset_encoding(to_encoding)}//IGNORE", normalize_iconv_charset_encoding(from_encoding), str)
|
60
|
-
end
|
61
|
-
|
62
|
-
def Ruby18.b_value_encode(str, encoding)
|
63
|
-
# Ruby 1.8 requires an encoding to work
|
64
|
-
raise ArgumentError, "Must supply an encoding" if encoding.nil?
|
65
|
-
encoding = encoding.to_s.upcase.gsub('_', '-')
|
66
|
-
[Encodings::Base64.encode(str), normalize_iconv_charset_encoding(encoding)]
|
67
|
-
end
|
68
|
-
|
69
|
-
def Ruby18.b_value_decode(str)
|
70
|
-
match = str.match(/\=\?(.+)?\?[Bb]\?(.*)\?\=/m)
|
71
|
-
if match
|
72
|
-
encoding = match[1]
|
73
|
-
str = Ruby18.decode_base64(match[2])
|
74
|
-
str = transcode_charset(str, encoding)
|
75
|
-
end
|
76
|
-
str
|
77
|
-
end
|
78
|
-
|
79
|
-
def Ruby18.q_value_encode(str, encoding)
|
80
|
-
# Ruby 1.8 requires an encoding to work
|
81
|
-
raise ArgumentError, "Must supply an encoding" if encoding.nil?
|
82
|
-
encoding = encoding.to_s.upcase.gsub('_', '-')
|
83
|
-
[Encodings::QuotedPrintable.encode(str), encoding]
|
84
|
-
end
|
85
|
-
|
86
|
-
def Ruby18.q_value_decode(str)
|
87
|
-
match = str.match(/\=\?(.+)?\?[Qq]\?(.*)\?\=/m)
|
88
|
-
if match
|
89
|
-
encoding = match[1]
|
90
|
-
string = match[2].gsub(/_/, '=20')
|
91
|
-
# Remove trailing = if it exists in a Q encoding
|
92
|
-
string = string.sub(/\=$/, '')
|
93
|
-
str = Encodings::QuotedPrintable.decode(string)
|
94
|
-
str = transcode_charset(str, encoding)
|
95
|
-
end
|
96
|
-
str
|
97
|
-
end
|
98
|
-
|
99
|
-
def Ruby18.param_decode(str, encoding)
|
100
|
-
URI.unescape(str)
|
101
|
-
end
|
102
|
-
|
103
|
-
def Ruby18.param_encode(str)
|
104
|
-
encoding = $KCODE.to_s.downcase
|
105
|
-
language = Configuration.instance.param_encode_language
|
106
|
-
"#{encoding}'#{language}'#{URI.escape(str)}"
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
|
111
|
-
def Ruby18.normalize_iconv_charset_encoding(encoding)
|
112
|
-
case encoding.upcase
|
113
|
-
when 'UTF8', 'UTF_8'
|
114
|
-
'UTF-8'
|
115
|
-
when 'UTF16', 'UTF-16'
|
116
|
-
'UTF-16BE'
|
117
|
-
when 'UTF32', 'UTF-32'
|
118
|
-
'UTF-32BE'
|
119
|
-
when 'KS_C_5601-1987'
|
120
|
-
'CP949'
|
121
|
-
else
|
122
|
-
encoding
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
@@ -1,226 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module Mail
|
5
|
-
class Ruby19
|
6
|
-
class StrictCharsetEncoder
|
7
|
-
def encode(string, charset)
|
8
|
-
string.force_encoding(Mail::Ruby19.pick_encoding(charset))
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class BestEffortCharsetEncoder
|
13
|
-
def encode(string, charset)
|
14
|
-
string.force_encoding(pick_encoding(charset))
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def pick_encoding(charset)
|
20
|
-
charset = case charset
|
21
|
-
when /ansi_x3.110-1983/
|
22
|
-
'ISO-8859-1'
|
23
|
-
when /Windows-?1258/i # Windows-1258 is similar to 1252
|
24
|
-
"Windows-1252"
|
25
|
-
else
|
26
|
-
charset
|
27
|
-
end
|
28
|
-
Mail::Ruby19.pick_encoding(charset)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class << self
|
33
|
-
attr_accessor :charset_encoder
|
34
|
-
end
|
35
|
-
self.charset_encoder = StrictCharsetEncoder.new
|
36
|
-
|
37
|
-
# Escapes any parenthesis in a string that are unescaped this uses
|
38
|
-
# a Ruby 1.9.1 regexp feature of negative look behind
|
39
|
-
def Ruby19.escape_paren( str )
|
40
|
-
re = /(?<!\\)([\(\)])/ # Only match unescaped parens
|
41
|
-
str.gsub(re) { |s| '\\' + s }
|
42
|
-
end
|
43
|
-
|
44
|
-
def Ruby19.paren( str )
|
45
|
-
str = $1 if str =~ /^\((.*)?\)$/
|
46
|
-
str = escape_paren( str )
|
47
|
-
'(' + str + ')'
|
48
|
-
end
|
49
|
-
|
50
|
-
def Ruby19.escape_bracket( str )
|
51
|
-
re = /(?<!\\)([\<\>])/ # Only match unescaped brackets
|
52
|
-
str.gsub(re) { |s| '\\' + s }
|
53
|
-
end
|
54
|
-
|
55
|
-
def Ruby19.bracket( str )
|
56
|
-
str = $1 if str =~ /^\<(.*)?\>$/
|
57
|
-
str = escape_bracket( str )
|
58
|
-
'<' + str + '>'
|
59
|
-
end
|
60
|
-
|
61
|
-
def Ruby19.decode_base64(str)
|
62
|
-
if !str.end_with?("=") && str.length % 4 != 0
|
63
|
-
str = str.ljust((str.length + 3) & ~3, "=")
|
64
|
-
end
|
65
|
-
str.unpack( 'm' ).first
|
66
|
-
end
|
67
|
-
|
68
|
-
def Ruby19.encode_base64(str)
|
69
|
-
[str].pack( 'm' )
|
70
|
-
end
|
71
|
-
|
72
|
-
def Ruby19.has_constant?(klass, string)
|
73
|
-
klass.const_defined?( string, false )
|
74
|
-
end
|
75
|
-
|
76
|
-
def Ruby19.get_constant(klass, string)
|
77
|
-
klass.const_get( string )
|
78
|
-
end
|
79
|
-
|
80
|
-
def Ruby19.transcode_charset(str, from_encoding, to_encoding = Encoding::UTF_8)
|
81
|
-
charset_encoder.encode(str.dup, from_encoding).encode(to_encoding, :undef => :replace, :invalid => :replace, :replace => '')
|
82
|
-
end
|
83
|
-
|
84
|
-
def Ruby19.b_value_encode(str, encoding = nil)
|
85
|
-
encoding = str.encoding.to_s
|
86
|
-
[Ruby19.encode_base64(str), encoding]
|
87
|
-
end
|
88
|
-
|
89
|
-
def Ruby19.b_value_decode(str)
|
90
|
-
match = str.match(/\=\?(.+)?\?[Bb]\?(.*)\?\=/m)
|
91
|
-
if match
|
92
|
-
charset = match[1]
|
93
|
-
str = Ruby19.decode_base64(match[2])
|
94
|
-
str = charset_encoder.encode(str, charset)
|
95
|
-
end
|
96
|
-
decoded = str.encode(Encoding::UTF_8, :invalid => :replace, :replace => "")
|
97
|
-
decoded.valid_encoding? ? decoded : decoded.encode(Encoding::UTF_16LE, :invalid => :replace, :replace => "").encode(Encoding::UTF_8)
|
98
|
-
rescue Encoding::UndefinedConversionError, ArgumentError, Encoding::ConverterNotFoundError
|
99
|
-
warn "Encoding conversion failed #{$!}"
|
100
|
-
str.dup.force_encoding(Encoding::UTF_8)
|
101
|
-
end
|
102
|
-
|
103
|
-
def Ruby19.q_value_encode(str, encoding = nil)
|
104
|
-
encoding = str.encoding.to_s
|
105
|
-
[Encodings::QuotedPrintable.encode(str), encoding]
|
106
|
-
end
|
107
|
-
|
108
|
-
def Ruby19.q_value_decode(str)
|
109
|
-
match = str.match(/\=\?(.+)?\?[Qq]\?(.*)\?\=/m)
|
110
|
-
if match
|
111
|
-
charset = match[1]
|
112
|
-
string = match[2].gsub(/_/, '=20')
|
113
|
-
# Remove trailing = if it exists in a Q encoding
|
114
|
-
string = string.sub(/\=$/, '')
|
115
|
-
str = Encodings::QuotedPrintable.decode(string)
|
116
|
-
str = charset_encoder.encode(str, charset)
|
117
|
-
# We assume that binary strings hold utf-8 directly to work around
|
118
|
-
# jruby/jruby#829 which subtly changes String#encode semantics.
|
119
|
-
str.force_encoding(Encoding::UTF_8) if str.encoding == Encoding::ASCII_8BIT
|
120
|
-
end
|
121
|
-
decoded = str.encode(Encoding::UTF_8, :invalid => :replace, :replace => "")
|
122
|
-
decoded.valid_encoding? ? decoded : decoded.encode(Encoding::UTF_16LE, :invalid => :replace, :replace => "").encode(Encoding::UTF_8)
|
123
|
-
rescue Encoding::UndefinedConversionError, ArgumentError, Encoding::ConverterNotFoundError
|
124
|
-
warn "Encoding conversion failed #{$!}"
|
125
|
-
str.dup.force_encoding(Encoding::UTF_8)
|
126
|
-
end
|
127
|
-
|
128
|
-
def Ruby19.param_decode(str, encoding)
|
129
|
-
str = uri_parser.unescape(str)
|
130
|
-
str = charset_encoder.encode(str, encoding) if encoding
|
131
|
-
str
|
132
|
-
end
|
133
|
-
|
134
|
-
def Ruby19.param_encode(str)
|
135
|
-
encoding = str.encoding.to_s.downcase
|
136
|
-
language = Configuration.instance.param_encode_language
|
137
|
-
"#{encoding}'#{language}'#{uri_parser.escape(str)}"
|
138
|
-
end
|
139
|
-
|
140
|
-
def Ruby19.uri_parser
|
141
|
-
@uri_parser ||= URI::Parser.new
|
142
|
-
end
|
143
|
-
|
144
|
-
# Pick a Ruby encoding corresponding to the message charset. Most
|
145
|
-
# charsets have a Ruby encoding, but some need manual aliasing here.
|
146
|
-
#
|
147
|
-
# TODO: add this as a test somewhere:
|
148
|
-
# Encoding.list.map { |e| [e.to_s.upcase == pick_encoding(e.to_s.downcase.gsub("-", "")), e.to_s] }.select {|a,b| !b}
|
149
|
-
# Encoding.list.map { |e| [e.to_s == pick_encoding(e.to_s), e.to_s] }.select {|a,b| !b}
|
150
|
-
def Ruby19.pick_encoding(charset)
|
151
|
-
charset = charset.to_s
|
152
|
-
encoding = case charset.downcase
|
153
|
-
|
154
|
-
# ISO-8859-8-I etc. http://en.wikipedia.org/wiki/ISO-8859-8-I
|
155
|
-
when /^iso[-_]?8859-(\d+)(-i)?$/
|
156
|
-
"ISO-8859-#{$1}"
|
157
|
-
|
158
|
-
# ISO-8859-15, ISO-2022-JP and alike
|
159
|
-
when /^iso[-_]?(\d{4})-?(\w{1,2})$/
|
160
|
-
"ISO-#{$1}-#{$2}"
|
161
|
-
|
162
|
-
# "ISO-2022-JP-KDDI" and alike
|
163
|
-
when /^iso[-_]?(\d{4})-?(\w{1,2})-?(\w*)$/
|
164
|
-
"ISO-#{$1}-#{$2}-#{$3}"
|
165
|
-
|
166
|
-
# UTF-8, UTF-32BE and alike
|
167
|
-
when /^utf[\-_]?(\d{1,2})?(\w{1,2})$/
|
168
|
-
"UTF-#{$1}#{$2}".gsub(/\A(UTF-(?:16|32))\z/, '\\1BE')
|
169
|
-
|
170
|
-
# Windows-1252 and alike
|
171
|
-
when /^windows-?(.*)$/
|
172
|
-
"Windows-#{$1}"
|
173
|
-
|
174
|
-
when '8bit'
|
175
|
-
Encoding::ASCII_8BIT
|
176
|
-
|
177
|
-
# alternatives/misspellings of us-ascii seen in the wild
|
178
|
-
when /^iso[-_]?646(-us)?$/, 'us=ascii'
|
179
|
-
Encoding::ASCII
|
180
|
-
|
181
|
-
# Microsoft-specific alias for MACROMAN
|
182
|
-
when 'macintosh'
|
183
|
-
Encoding::MACROMAN
|
184
|
-
|
185
|
-
# Microsoft-specific alias for CP949 (Korean)
|
186
|
-
when 'ks_c_5601-1987'
|
187
|
-
Encoding::CP949
|
188
|
-
|
189
|
-
# Wrongly written Shift_JIS (Japanese)
|
190
|
-
when 'shift-jis'
|
191
|
-
Encoding::Shift_JIS
|
192
|
-
|
193
|
-
# GB2312 (Chinese charset) is a subset of GB18030 (its replacement)
|
194
|
-
when 'gb2312'
|
195
|
-
Encoding::GB18030
|
196
|
-
|
197
|
-
when 'cp-850'
|
198
|
-
Encoding::CP850
|
199
|
-
|
200
|
-
when 'latin2'
|
201
|
-
Encoding::ISO_8859_2
|
202
|
-
|
203
|
-
else
|
204
|
-
charset
|
205
|
-
end
|
206
|
-
|
207
|
-
convert_to_encoding(encoding)
|
208
|
-
end
|
209
|
-
|
210
|
-
class << self
|
211
|
-
private
|
212
|
-
|
213
|
-
def convert_to_encoding(encoding)
|
214
|
-
if encoding.is_a?(Encoding)
|
215
|
-
encoding
|
216
|
-
else
|
217
|
-
begin
|
218
|
-
Encoding.find(encoding)
|
219
|
-
rescue ArgumentError
|
220
|
-
Encoding::BINARY
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|