mail 2.5.3 → 2.5.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mail might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +65 -0
- data/CONTRIBUTING.md +4 -4
- data/Gemfile +7 -20
- data/MIT-LICENSE +20 -0
- data/README.md +10 -9
- data/Rakefile +3 -20
- data/lib/VERSION +1 -1
- data/lib/mail.rb +0 -1
- data/lib/mail/attachments_list.rb +2 -2
- data/lib/mail/body.rb +4 -4
- data/lib/mail/check_delivery_params.rb +12 -22
- data/lib/mail/core_extensions/object.rb +8 -8
- data/lib/mail/core_extensions/smtp.rb +12 -13
- data/lib/mail/core_extensions/string.rb +4 -4
- data/lib/mail/elements/address.rb +13 -5
- data/lib/mail/elements/envelope_from_element.rb +15 -2
- data/lib/mail/encodings.rb +61 -28
- data/lib/mail/encodings/quoted_printable.rb +4 -3
- data/lib/mail/field.rb +10 -11
- data/lib/mail/fields/bcc_field.rb +2 -2
- data/lib/mail/fields/cc_field.rb +2 -2
- data/lib/mail/fields/comments_field.rb +1 -1
- data/lib/mail/fields/common/common_address.rb +13 -3
- data/lib/mail/fields/common/common_field.rb +4 -4
- data/lib/mail/fields/content_id_field.rb +1 -2
- data/lib/mail/fields/content_transfer_encoding_field.rb +2 -2
- data/lib/mail/fields/content_type_field.rb +1 -1
- data/lib/mail/fields/date_field.rb +1 -1
- data/lib/mail/fields/from_field.rb +2 -2
- data/lib/mail/fields/in_reply_to_field.rb +2 -1
- data/lib/mail/fields/message_id_field.rb +2 -3
- data/lib/mail/fields/references_field.rb +2 -1
- data/lib/mail/fields/reply_to_field.rb +2 -2
- data/lib/mail/fields/resent_bcc_field.rb +2 -2
- data/lib/mail/fields/resent_cc_field.rb +2 -2
- data/lib/mail/fields/resent_from_field.rb +2 -2
- data/lib/mail/fields/resent_sender_field.rb +2 -2
- data/lib/mail/fields/resent_to_field.rb +2 -2
- data/lib/mail/fields/sender_field.rb +7 -7
- data/lib/mail/fields/to_field.rb +2 -2
- data/lib/mail/fields/unstructured_field.rb +1 -1
- data/lib/mail/header.rb +5 -1
- data/lib/mail/message.rb +133 -37
- data/lib/mail/multibyte/chars.rb +2 -2
- data/lib/mail/multibyte/unicode.rb +5 -3
- data/lib/mail/network/delivery_methods/exim.rb +1 -6
- data/lib/mail/network/delivery_methods/file_delivery.rb +1 -1
- data/lib/mail/network/delivery_methods/sendmail.rb +32 -10
- data/lib/mail/network/delivery_methods/smtp.rb +35 -34
- data/lib/mail/network/delivery_methods/smtp_connection.rb +6 -6
- data/lib/mail/network/delivery_methods/test_mailer.rb +2 -2
- data/lib/mail/parsers/content_transfer_encoding.rb +81 -42
- data/lib/mail/parsers/content_transfer_encoding.treetop +4 -6
- data/lib/mail/parsers/content_type.rb +16 -12
- data/lib/mail/parsers/content_type.treetop +2 -2
- data/lib/mail/parsers/rfc2045.rb +12 -55
- data/lib/mail/parsers/rfc2045.treetop +1 -2
- data/lib/mail/parsers/rfc2822.rb +50 -50
- data/lib/mail/parsers/rfc2822.treetop +19 -21
- data/lib/mail/part.rb +6 -2
- data/lib/mail/patterns.rb +1 -0
- data/lib/mail/utilities.rb +25 -17
- data/lib/mail/version_specific/ruby_1_8.rb +5 -1
- data/lib/mail/version_specific/ruby_1_9.rb +46 -21
- metadata +57 -8
- data/lib/mail/core_extensions/shell_escape.rb +0 -56
data/lib/mail/multibyte/chars.rb
CHANGED
@@ -364,7 +364,7 @@ module Mail #:nodoc:
|
|
364
364
|
# "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
|
365
365
|
# "日本語".mb_chars.titleize # => "日本語"
|
366
366
|
def titleize
|
367
|
-
chars(downcase.to_s.gsub(/\b('
|
367
|
+
chars(downcase.to_s.gsub(/\b('?\S)/u) { Unicode.apply_mapping $1, :uppercase_mapping })
|
368
368
|
end
|
369
369
|
alias_method :titlecase, :titleize
|
370
370
|
|
@@ -412,7 +412,7 @@ module Mail #:nodoc:
|
|
412
412
|
chars(Unicode.tidy_bytes(@wrapped_string, force))
|
413
413
|
end
|
414
414
|
|
415
|
-
|
415
|
+
%w(capitalize downcase lstrip reverse rstrip slice strip tidy_bytes upcase).each do |method|
|
416
416
|
# Only define a corresponding bang method for methods defined in the proxy; On 1.9 the proxy will
|
417
417
|
# exclude lstrip!, rstrip! and strip! because they are already work as expected on multibyte strings.
|
418
418
|
if public_method_defined?(method)
|
@@ -391,8 +391,10 @@ module Mail
|
|
391
391
|
end
|
392
392
|
end
|
393
393
|
|
394
|
-
|
395
|
-
|
396
|
-
|
394
|
+
unless defined?(ActiveSupport)
|
395
|
+
module ActiveSupport
|
396
|
+
unless const_defined?(:Multibyte)
|
397
|
+
Multibyte = Mail::Multibyte
|
398
|
+
end
|
397
399
|
end
|
398
400
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'mail/check_delivery_params'
|
2
|
-
|
3
1
|
module Mail
|
4
2
|
|
5
3
|
# A delivery method implementation which sends via exim.
|
@@ -38,16 +36,13 @@ module Mail
|
|
38
36
|
#
|
39
37
|
# mail.deliver!
|
40
38
|
class Exim < Sendmail
|
41
|
-
include Mail::CheckDeliveryParams
|
42
|
-
|
43
39
|
def initialize(values)
|
44
40
|
self.settings = { :location => '/usr/sbin/exim',
|
45
41
|
:arguments => '-i -t' }.merge(values)
|
46
42
|
end
|
47
43
|
|
48
44
|
def self.call(path, arguments, destinations, mail)
|
49
|
-
|
50
|
-
IO.popen("#{path} #{arguments}", "w+") do |io|
|
45
|
+
popen "#{path} #{arguments}" do |io|
|
51
46
|
io.puts mail.encoded.to_lf
|
52
47
|
io.flush
|
53
48
|
end
|
@@ -41,27 +41,49 @@ module Mail
|
|
41
41
|
|
42
42
|
def initialize(values)
|
43
43
|
self.settings = { :location => '/usr/sbin/sendmail',
|
44
|
-
:arguments => '-i
|
44
|
+
:arguments => '-i' }.merge(values)
|
45
45
|
end
|
46
46
|
|
47
47
|
attr_accessor :settings
|
48
48
|
|
49
49
|
def deliver!(mail)
|
50
|
-
|
50
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
from = "-f #{self.class.shellquote(smtp_from)}"
|
53
|
+
to = smtp_to.map { |to| self.class.shellquote(to) }.join(' ')
|
54
54
|
|
55
|
-
arguments =
|
56
|
-
|
57
|
-
self.class.call(settings[:location], arguments, mail.destinations.collect(&:escape_for_shell).join(" "), mail)
|
55
|
+
arguments = "#{settings[:arguments]} #{from} --"
|
56
|
+
self.class.call(settings[:location], arguments, to, message)
|
58
57
|
end
|
59
58
|
|
60
|
-
def self.call(path, arguments, destinations,
|
61
|
-
|
62
|
-
io.puts
|
59
|
+
def self.call(path, arguments, destinations, encoded_message)
|
60
|
+
popen "#{path} #{arguments} #{destinations}" do |io|
|
61
|
+
io.puts encoded_message.to_lf
|
63
62
|
io.flush
|
64
63
|
end
|
65
64
|
end
|
65
|
+
|
66
|
+
if RUBY_VERSION < '1.9.0'
|
67
|
+
def self.popen(command, &block)
|
68
|
+
IO.popen "#{command} 2>&1", 'w+', &block
|
69
|
+
end
|
70
|
+
else
|
71
|
+
def self.popen(command, &block)
|
72
|
+
IO.popen command, 'w+', :err => :out, &block
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# The following is an adaptation of ruby 1.9.2's shellwords.rb file,
|
77
|
+
# it is modified to include '+' in the allowed list to allow for
|
78
|
+
# sendmail to accept email addresses as the sender with a + in them.
|
79
|
+
def self.shellquote(address)
|
80
|
+
# Process as a single byte sequence because not all shell
|
81
|
+
# implementations are multibyte aware.
|
82
|
+
#
|
83
|
+
# A LF cannot be escaped with a backslash because a backslash + LF
|
84
|
+
# combo is regarded as line continuation and simply ignored. Strip it.
|
85
|
+
escaped = address.gsub(/([^A-Za-z0-9_\s\+\-.,:\/@])/n, "\\\\\\1").gsub("\n", '')
|
86
|
+
%("#{escaped}")
|
87
|
+
end
|
66
88
|
end
|
67
89
|
end
|
@@ -89,57 +89,58 @@ module Mail
|
|
89
89
|
:tls => nil
|
90
90
|
}.merge!(values)
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
attr_accessor :settings
|
94
|
-
|
94
|
+
|
95
95
|
# Send the message via SMTP.
|
96
96
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
97
97
|
def deliver!(mail)
|
98
|
-
|
98
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
99
99
|
|
100
100
|
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
101
101
|
if settings[:tls] || settings[:ssl]
|
102
102
|
if smtp.respond_to?(:enable_tls)
|
103
|
-
|
104
|
-
smtp.enable_tls
|
105
|
-
else
|
106
|
-
openssl_verify_mode = settings[:openssl_verify_mode]
|
107
|
-
if openssl_verify_mode.kind_of?(String)
|
108
|
-
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
109
|
-
end
|
110
|
-
context = Net::SMTP.default_ssl_context
|
111
|
-
context.verify_mode = openssl_verify_mode
|
112
|
-
smtp.enable_tls(context)
|
113
|
-
end
|
103
|
+
smtp.enable_tls(ssl_context)
|
114
104
|
end
|
115
105
|
elsif settings[:enable_starttls_auto]
|
116
|
-
if smtp.respond_to?(:enable_starttls_auto)
|
117
|
-
|
118
|
-
smtp.enable_starttls_auto
|
119
|
-
else
|
120
|
-
openssl_verify_mode = settings[:openssl_verify_mode]
|
121
|
-
if openssl_verify_mode.kind_of?(String)
|
122
|
-
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
123
|
-
end
|
124
|
-
if RUBY_VERSION >= '1.9.0'
|
125
|
-
context = Net::SMTP.default_ssl_context
|
126
|
-
context.verify_mode = openssl_verify_mode
|
127
|
-
smtp.enable_tls(context)
|
128
|
-
else
|
129
|
-
smtp.enable_tls(openssl_verify_mode)
|
130
|
-
end
|
131
|
-
end
|
106
|
+
if smtp.respond_to?(:enable_starttls_auto)
|
107
|
+
smtp.enable_starttls_auto(ssl_context)
|
132
108
|
end
|
133
109
|
end
|
134
|
-
|
110
|
+
|
135
111
|
response = nil
|
136
112
|
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp_obj|
|
137
|
-
response = smtp_obj.sendmail(message,
|
113
|
+
response = smtp_obj.sendmail(message, smtp_from, smtp_to)
|
138
114
|
end
|
139
115
|
|
140
|
-
|
116
|
+
if settings[:return_response]
|
117
|
+
response
|
118
|
+
else
|
119
|
+
self
|
120
|
+
end
|
141
121
|
end
|
142
122
|
|
143
|
-
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
# Allow SSL context to be configured via settings, for Ruby >= 1.9
|
127
|
+
# Just returns openssl verify mode for Ruby 1.8.x
|
128
|
+
def ssl_context
|
129
|
+
openssl_verify_mode = settings[:openssl_verify_mode]
|
130
|
+
|
131
|
+
if openssl_verify_mode.kind_of?(String)
|
132
|
+
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
133
|
+
end
|
134
|
+
|
135
|
+
if RUBY_VERSION < '1.9.0'
|
136
|
+
openssl_verify_mode
|
137
|
+
else
|
138
|
+
context = Net::SMTP.default_ssl_context
|
139
|
+
context.verify_mode = openssl_verify_mode
|
140
|
+
context.ca_path = settings[:ca_path] if settings[:ca_path]
|
141
|
+
context.ca_file = settings[:ca_file] if settings[:ca_file]
|
142
|
+
context
|
143
|
+
end
|
144
|
+
end
|
144
145
|
end
|
145
146
|
end
|
@@ -44,18 +44,18 @@ module Mail
|
|
44
44
|
self.smtp = values[:connection]
|
45
45
|
self.settings = values
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
attr_accessor :smtp
|
49
49
|
attr_accessor :settings
|
50
|
-
|
50
|
+
|
51
51
|
# Send the message via SMTP.
|
52
52
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
53
53
|
def deliver!(mail)
|
54
|
-
|
55
|
-
response = smtp.sendmail(message,
|
54
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
55
|
+
response = smtp.sendmail(message, smtp_from, smtp_to)
|
56
56
|
|
57
|
-
settings[:return_response] ? response : self
|
57
|
+
settings[:return_response] ? response : self
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
end
|
61
61
|
end
|
@@ -30,13 +30,13 @@ module Mail
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def initialize(values)
|
33
|
-
@settings =
|
33
|
+
@settings = values.dup
|
34
34
|
end
|
35
35
|
|
36
36
|
attr_accessor :settings
|
37
37
|
|
38
38
|
def deliver!(mail)
|
39
|
-
|
39
|
+
check_delivery_params(mail)
|
40
40
|
Mail::TestMailer.deliveries << mail
|
41
41
|
end
|
42
42
|
|
@@ -85,19 +85,6 @@ module Mail
|
|
85
85
|
r0
|
86
86
|
end
|
87
87
|
|
88
|
-
module Encoding0
|
89
|
-
def ietf_token
|
90
|
-
elements[0]
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
module Encoding1
|
96
|
-
def text_value
|
97
|
-
ietf_token.text_value
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
88
|
def _nt_encoding
|
102
89
|
start_index = index
|
103
90
|
if node_cache[:encoding].has_key?(index)
|
@@ -110,41 +97,93 @@ module Mail
|
|
110
97
|
end
|
111
98
|
|
112
99
|
i0 = index
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
if r2
|
117
|
-
if has_terminal?("s", false, index)
|
118
|
-
r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
119
|
-
@index += 1
|
120
|
-
else
|
121
|
-
terminal_parse_failure("s")
|
122
|
-
r4 = nil
|
123
|
-
end
|
124
|
-
if r4
|
125
|
-
r3 = r4
|
126
|
-
else
|
127
|
-
r3 = instantiate_node(SyntaxNode,input, index...index)
|
128
|
-
end
|
129
|
-
s1 << r3
|
130
|
-
end
|
131
|
-
if s1.last
|
132
|
-
r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
|
133
|
-
r1.extend(Encoding0)
|
134
|
-
r1.extend(Encoding1)
|
100
|
+
if has_terminal?("7bits", false, index)
|
101
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + 5))
|
102
|
+
@index += 5
|
135
103
|
else
|
136
|
-
|
104
|
+
terminal_parse_failure("7bits")
|
137
105
|
r1 = nil
|
138
106
|
end
|
139
107
|
if r1
|
140
108
|
r0 = r1
|
141
109
|
else
|
142
|
-
|
143
|
-
|
144
|
-
|
110
|
+
if has_terminal?("8bits", false, index)
|
111
|
+
r2 = instantiate_node(SyntaxNode,input, index...(index + 5))
|
112
|
+
@index += 5
|
113
|
+
else
|
114
|
+
terminal_parse_failure("8bits")
|
115
|
+
r2 = nil
|
116
|
+
end
|
117
|
+
if r2
|
118
|
+
r0 = r2
|
145
119
|
else
|
146
|
-
|
147
|
-
|
120
|
+
if has_terminal?("7bit", false, index)
|
121
|
+
r3 = instantiate_node(SyntaxNode,input, index...(index + 4))
|
122
|
+
@index += 4
|
123
|
+
else
|
124
|
+
terminal_parse_failure("7bit")
|
125
|
+
r3 = nil
|
126
|
+
end
|
127
|
+
if r3
|
128
|
+
r0 = r3
|
129
|
+
else
|
130
|
+
if has_terminal?("8bit", false, index)
|
131
|
+
r4 = instantiate_node(SyntaxNode,input, index...(index + 4))
|
132
|
+
@index += 4
|
133
|
+
else
|
134
|
+
terminal_parse_failure("8bit")
|
135
|
+
r4 = nil
|
136
|
+
end
|
137
|
+
if r4
|
138
|
+
r0 = r4
|
139
|
+
else
|
140
|
+
if has_terminal?("binary", false, index)
|
141
|
+
r5 = instantiate_node(SyntaxNode,input, index...(index + 6))
|
142
|
+
@index += 6
|
143
|
+
else
|
144
|
+
terminal_parse_failure("binary")
|
145
|
+
r5 = nil
|
146
|
+
end
|
147
|
+
if r5
|
148
|
+
r0 = r5
|
149
|
+
else
|
150
|
+
if has_terminal?("quoted-printable", false, index)
|
151
|
+
r6 = instantiate_node(SyntaxNode,input, index...(index + 16))
|
152
|
+
@index += 16
|
153
|
+
else
|
154
|
+
terminal_parse_failure("quoted-printable")
|
155
|
+
r6 = nil
|
156
|
+
end
|
157
|
+
if r6
|
158
|
+
r0 = r6
|
159
|
+
else
|
160
|
+
if has_terminal?("base64", false, index)
|
161
|
+
r7 = instantiate_node(SyntaxNode,input, index...(index + 6))
|
162
|
+
@index += 6
|
163
|
+
else
|
164
|
+
terminal_parse_failure("base64")
|
165
|
+
r7 = nil
|
166
|
+
end
|
167
|
+
if r7
|
168
|
+
r0 = r7
|
169
|
+
else
|
170
|
+
r8 = _nt_ietf_token
|
171
|
+
if r8
|
172
|
+
r0 = r8
|
173
|
+
else
|
174
|
+
r9 = _nt_custom_x_token
|
175
|
+
if r9
|
176
|
+
r0 = r9
|
177
|
+
else
|
178
|
+
@index = i0
|
179
|
+
r0 = nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
148
187
|
end
|
149
188
|
end
|
150
189
|
|
@@ -159,4 +198,4 @@ module Mail
|
|
159
198
|
include ContentTransferEncoding
|
160
199
|
end
|
161
200
|
|
162
|
-
end
|
201
|
+
end
|
@@ -9,12 +9,10 @@ module Mail
|
|
9
9
|
end
|
10
10
|
|
11
11
|
rule encoding
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
} / custom_x_token
|
12
|
+
"7bits" / "8bits" /
|
13
|
+
"7bit" / "8bit" / "binary" / "quoted-printable" / "base64" /
|
14
|
+
ietf_token / custom_x_token
|
17
15
|
end
|
18
16
|
|
19
17
|
end
|
20
|
-
end
|
18
|
+
end
|
@@ -82,18 +82,22 @@ module Mail
|
|
82
82
|
r6 = _nt_CFWS
|
83
83
|
s5 << r6
|
84
84
|
if r6
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
85
|
+
s7, i7 = [], index
|
86
|
+
loop do
|
87
|
+
if has_terminal?(";", false, index)
|
88
|
+
r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
89
|
+
@index += 1
|
90
|
+
else
|
91
|
+
terminal_parse_failure(";")
|
92
|
+
r8 = nil
|
93
|
+
end
|
94
|
+
if r8
|
95
|
+
s7 << r8
|
96
|
+
else
|
97
|
+
break
|
98
|
+
end
|
96
99
|
end
|
100
|
+
r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
|
97
101
|
s5 << r7
|
98
102
|
if r7
|
99
103
|
r9 = _nt_parameter
|
@@ -964,4 +968,4 @@ module Mail
|
|
964
968
|
include ContentType
|
965
969
|
end
|
966
970
|
|
967
|
-
end
|
971
|
+
end
|