1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
require 'mail/message'
require 'mail/fields/common/parameter_hash'
module Mail
class Message
attr_accessor :url_part_number
attr_accessor :rfc822_attachment # when a whole email message is attached as text
attr_accessor :within_rfc822_attachment # for parts within a message attached as text (for getting subject mainly)
attr_accessor :count_parts_count
attr_accessor :count_first_uudecode_count
# A patched version of the message initializer to work around a bug where stripping the original
# input removes meaningful spaces - e.g. in the case of uuencoded bodies.
def initialize(*args, &block)
@body = nil
@body_raw = nil
@separate_parts = false
@text_part = nil
@html_part = nil
@errors = nil
@header = nil
@charset = 'UTF-8'
@defaulted_charset = true
@perform_deliveries = true
@raise_delivery_errors = true
@delivery_handler = nil
@delivery_method = Mail.delivery_method.dup
@transport_encoding = Mail::Encodings.get_encoding('7bit')
@mark_for_delete = false
if args.flatten.first.respond_to?(:each_pair)
init_with_hash(args.flatten.first)
else
# The replacement of this commented out line is the change.
# init_with_string(args.flatten[0].to_s.strip)
init_with_string(args.flatten[0].to_s)
end
if block_given?
instance_eval(&block)
end
self
end
end
# A patched version of the parameter hash that handles nil values without throwing
# an error.
class ParameterHash < IndifferentHash
def encoded
map.sort { |a,b| a.first.to_s <=> b.first.to_s }.map do |key_name, value|
# The replacement of this commented out line is the change
# unless value.ascii_only?
unless value.nil? || value.ascii_only?
value = Mail::Encodings.param_encode(value)
key_name = "#{key_name}*"
end
%Q{#{key_name}=#{quote_token(value)}}
end.join(";\r\n\s")
end
end
# HACK: Backport encoding fixes for Ruby 1.8 from Mail 2.5
# Can be removed when we no longer support Ruby 1.8
class Ruby18
def Ruby18.b_value_decode(str)
match = str.match(/\=\?(.+)?\?[Bb]\?(.+)?\?\=/m)
if match
encoding = match[1]
str = Ruby18.decode_base64(match[2])
# Adding and removing trailing spaces is a workaround
# for Iconv.conv throwing an exception if it finds an
# invalid character at the end of the string, even
# with UTF-8//IGNORE:
# http://po-ru.com/diary/fixing-invalid-utf-8-in-ruby-revisited/
str = Iconv.conv('UTF-8//IGNORE', fix_encoding(encoding), str + " ")[0...-4]
end
str
end
def Ruby18.q_value_decode(str)
match = str.match(/\=\?(.+)?\?[Qq]\?(.+)?\?\=/m)
if match
encoding = match[1]
string = match[2].gsub(/_/, '=20')
# Remove trailing = if it exists in a Q encoding
string = string.sub(/\=$/, '')
str = Encodings::QuotedPrintable.decode(string)
# Adding and removing trailing spaces is a workaround
# for Iconv.conv throwing an exception if it finds an
# invalid character at the end of the string, even
# with UTF-8//IGNORE:
# http://po-ru.com/diary/fixing-invalid-utf-8-in-ruby-revisited/
str = Iconv.conv('UTF-8//IGNORE', fix_encoding(encoding), str + " ")[0...-4]
end
str
end
private
def Ruby18.fix_encoding(encoding)
case encoding.upcase
when 'UTF8'
'UTF-8'
else
encoding
end
end
end
class Ruby19
def Ruby19.q_value_decode(str)
match = str.match(/\=\?(.+)?\?[Qq]\?(.+)?\?\=/m)
if match
encoding = match[1]
str = Encodings::QuotedPrintable.decode(match[2].gsub(/_/, '=20'))
# Backport line from mail 2.5 to strip a trailing = character
# Remove trailing = if it exists in a Q encoding
str = str.sub(/\=$/, '')
str.force_encoding(fix_encoding(encoding))
end
decoded = str.encode("utf-8", :invalid => :replace, :replace => "")
decoded.valid_encoding? ? decoded : decoded.encode("utf-16le", :invalid => :replace, :replace => "").encode("utf-8")
end
end
end
|