mail 2.2.12 → 2.2.13
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 +17 -0
- data/lib/VERSION +1 -1
- data/lib/mail.rb +3 -1
- data/lib/mail/attachments_list.rb +4 -4
- data/lib/mail/core_extensions/smtp.rb +24 -0
- data/lib/mail/elements/address.rb +5 -5
- data/lib/mail/encodings.rb +1 -1
- data/lib/mail/fields/common/common_field.rb +10 -9
- data/lib/mail/fields/common/parameter_hash.rb +1 -1
- data/lib/mail/fields/content_type_field.rb +5 -5
- data/lib/mail/fields/date_field.rb +2 -0
- data/lib/mail/message.rb +16 -14
- data/lib/mail/network/retriever_methods/imap.rb +12 -2
- data/lib/mail/patterns.rb +3 -2
- data/lib/mail/version_specific/ruby_1_8.rb +1 -1
- data/lib/mail/version_specific/ruby_1_9.rb +8 -8
- metadata +5 -4
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
== Thu 23 Dec 2010 09:15:58 UTC Mikel Lindsaar <mikel@rubyx.com>
|
2
|
+
|
3
|
+
* Added backport fix for net/smtp bug (Aaron Patterson)
|
4
|
+
* Changed "Mail#text_part" so that it does not return a plain text attachment (Anton Mironov)
|
5
|
+
* Added in rescue blocks for badly formatted dates as well as encoding problems (Karl Baum)
|
6
|
+
* Fixed warning errors of duplicated regular expressions (Kouhei Sutou)
|
7
|
+
* Removed duplication from Regex's containing [\w\d]+ as \w contains \d (mikel)
|
8
|
+
* Add authentication selection for imap retriever (Björn Albers)
|
9
|
+
* Removing warning on @name not being initialized (mikel)
|
10
|
+
* Version bump to 2.2.13 and gem release
|
11
|
+
|
12
|
+
== Fri 10 Dec 2010 09:06:49 UTC Mikel Lindsaar <mikel@rubyx.com>
|
13
|
+
|
14
|
+
* Fixing problems with multibyte filenamed attachment (amatsuda)
|
15
|
+
* Providing IMAP uid and imap object as options to IMAP calls (dball)
|
16
|
+
* Fixing filename for windows (mikel)
|
17
|
+
|
1
18
|
== Sun Dec 5 02:24:55 UTC 2010 Mikel Lindsaar <mikel@rubyx.com>
|
2
19
|
|
3
20
|
* Updating requirement on i18n to be more relaxed for now until we nuke ActiveSupport dependency (Mikel)
|
data/lib/VERSION
CHANGED
data/lib/mail.rb
CHANGED
@@ -4,6 +4,7 @@ module Mail # :doc:
|
|
4
4
|
require 'date'
|
5
5
|
|
6
6
|
require 'active_support'
|
7
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
7
8
|
require 'active_support/core_ext/hash/indifferent_access'
|
8
9
|
require 'active_support/core_ext/object/blank'
|
9
10
|
require 'active_support/core_ext/string'
|
@@ -32,6 +33,7 @@ module Mail # :doc:
|
|
32
33
|
|
33
34
|
require 'mail/core_extensions/nil'
|
34
35
|
require 'mail/core_extensions/string'
|
36
|
+
require 'mail/core_extensions/smtp' if RUBY_VERSION < '1.9.3'
|
35
37
|
|
36
38
|
require 'mail/patterns'
|
37
39
|
require 'mail/utilities'
|
@@ -52,7 +54,7 @@ module Mail # :doc:
|
|
52
54
|
require 'mail/envelope'
|
53
55
|
|
54
56
|
parsers = %w[ rfc2822_obsolete rfc2822 address_lists phrase_lists
|
55
|
-
date_time received message_ids envelope_from rfc2045
|
57
|
+
date_time received message_ids envelope_from rfc2045
|
56
58
|
mime_version content_type content_disposition
|
57
59
|
content_transfer_encoding content_location ]
|
58
60
|
|
@@ -37,9 +37,10 @@ module Mail
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def []=(name, value)
|
40
|
-
|
40
|
+
encoded_name = Mail::Encodings.decode_encode name, :encode
|
41
|
+
default_values = { :content_type => "#{set_mime_type(name)}; filename=\"#{encoded_name}\"",
|
41
42
|
:content_transfer_encoding => "#{guess_encoding}",
|
42
|
-
:content_disposition => "#{@content_disposition_type}; filename=\"#{
|
43
|
+
:content_disposition => "#{@content_disposition_type}; filename=\"#{encoded_name}\"" }
|
43
44
|
|
44
45
|
if value.is_a?(Hash)
|
45
46
|
|
@@ -73,7 +74,7 @@ module Mail
|
|
73
74
|
hash[:body].force_encoding("BINARY")
|
74
75
|
end
|
75
76
|
end
|
76
|
-
|
77
|
+
|
77
78
|
attachment = Part.new(hash)
|
78
79
|
attachment.add_content_id(hash[:content_id])
|
79
80
|
|
@@ -102,4 +103,3 @@ module Mail
|
|
102
103
|
|
103
104
|
end
|
104
105
|
end
|
105
|
-
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Net
|
2
|
+
class SMTP
|
3
|
+
# This is a backport of r30294 from ruby trunk because of a bug in net/smtp.
|
4
|
+
# http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=30294
|
5
|
+
#
|
6
|
+
# Fixed in what will be Ruby 1.9.3
|
7
|
+
remove_method :tlsconnect
|
8
|
+
|
9
|
+
def tlsconnect(s)
|
10
|
+
verified = false
|
11
|
+
s = OpenSSL::SSL::SSLSocket.new s, @ssl_context
|
12
|
+
logging "TLS connection started"
|
13
|
+
s.sync_close = true
|
14
|
+
s.connect
|
15
|
+
if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
16
|
+
s.post_connection_check(@address)
|
17
|
+
end
|
18
|
+
verified = true
|
19
|
+
s
|
20
|
+
ensure
|
21
|
+
s.close unless verified
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -184,11 +184,11 @@ module Mail
|
|
184
184
|
|
185
185
|
|
186
186
|
def get_domain
|
187
|
-
if tree.respond_to?(:angle_addr)
|
187
|
+
if tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:domain)
|
188
188
|
@domain_text ||= tree.angle_addr.addr_spec.domain.text_value.strip
|
189
189
|
elsif tree.respond_to?(:domain)
|
190
190
|
@domain_text ||= tree.domain.text_value.strip
|
191
|
-
elsif tree.respond_to?(:addr_spec)
|
191
|
+
elsif tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:domain)
|
192
192
|
tree.addr_spec.domain.text_value.strip
|
193
193
|
else
|
194
194
|
nil
|
@@ -292,12 +292,12 @@ module Mail
|
|
292
292
|
case
|
293
293
|
when tree.respond_to?(:local_dot_atom_text)
|
294
294
|
tree.local_dot_atom_text.text_value
|
295
|
-
when tree.respond_to?(:angle_addr)
|
295
|
+
when tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:local_part)
|
296
296
|
tree.angle_addr.addr_spec.local_part.text_value
|
297
|
-
when tree.respond_to?(:addr_spec)
|
297
|
+
when tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:local_part)
|
298
298
|
tree.addr_spec.local_part.text_value
|
299
299
|
else
|
300
|
-
tree ? tree.local_part.text_value : nil
|
300
|
+
tree && tree.respond_to?(:local_part) ? tree.local_part.text_value : nil
|
301
301
|
end
|
302
302
|
end
|
303
303
|
|
data/lib/mail/encodings.rb
CHANGED
@@ -180,7 +180,7 @@ module Mail
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def Encodings.encode_non_usascii(address, charset)
|
183
|
-
return address if address.ascii_only?
|
183
|
+
return address if address.ascii_only? or charset.nil?
|
184
184
|
us_ascii = %Q{\x00-\x7f}
|
185
185
|
# Encode any non usascii strings embedded inside of quotes
|
186
186
|
address.gsub!(/(".*?[^#{us_ascii}].+?")/) { |s| Encodings.b_value_encode(unquote(s), charset) }
|
@@ -1,41 +1,42 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mail
|
3
3
|
module CommonField # :nodoc:
|
4
|
+
|
4
5
|
def name=(value)
|
5
6
|
@name = value
|
6
7
|
end
|
7
|
-
|
8
|
+
|
8
9
|
def name
|
9
|
-
@name
|
10
|
+
@name ||= nil
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
def value=(value)
|
13
14
|
@length = nil
|
14
15
|
@tree = nil
|
15
16
|
@element = nil
|
16
17
|
@value = value
|
17
18
|
end
|
18
|
-
|
19
|
+
|
19
20
|
def value
|
20
21
|
@value
|
21
22
|
end
|
22
|
-
|
23
|
+
|
23
24
|
def to_s
|
24
25
|
decoded
|
25
26
|
end
|
26
|
-
|
27
|
+
|
27
28
|
def default
|
28
29
|
decoded
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
def field_length
|
32
33
|
@length ||= "#{name}: #{encode(decoded)}".length
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
def responsible_for?( val )
|
36
37
|
name.to_s.downcase == val.to_s.downcase
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
private
|
40
41
|
|
41
42
|
def strip_field(field_name, value)
|
@@ -29,7 +29,7 @@ module Mail
|
|
29
29
|
super(exact || key_name)
|
30
30
|
else # Dealing with a multiple value pair or a single encoded value pair
|
31
31
|
string = pairs.sort { |a,b| a.first <=> b.first }.map { |v| v.last }.join('')
|
32
|
-
if mt = string.match(/([\w
|
32
|
+
if mt = string.match(/([\w\-]+)'(\w\w)'(.*)/)
|
33
33
|
string = mt[3]
|
34
34
|
encoding = mt[1]
|
35
35
|
else
|
@@ -153,10 +153,10 @@ module Mail
|
|
153
153
|
end
|
154
154
|
|
155
155
|
case
|
156
|
-
when val.chomp =~ /^\s*([\w
|
156
|
+
when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;;+(.*)$/i
|
157
157
|
# Handles 'text/plain;; format="flowed"' (double semi colon)
|
158
158
|
"#{$1}/#{$2}; #{$3}"
|
159
|
-
when val.chomp =~ /^\s*([\w
|
159
|
+
when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
|
160
160
|
# Microsoft helper:
|
161
161
|
# Handles 'type/subtype;ISO-8559-1'
|
162
162
|
"#{$1}/#{$2}; charset=#{quote_atom($3)}"
|
@@ -166,10 +166,10 @@ module Mail
|
|
166
166
|
when val.chomp =~ /^(\w+);\s(.*)$/i
|
167
167
|
# Handles 'text; <parameters>'
|
168
168
|
"text/plain; #{$2}"
|
169
|
-
when val =~ /([\w
|
169
|
+
when val =~ /([\w\-]+\/[\w\-]+);\scharset="charset="(\w+)""/i
|
170
170
|
# Handles text/html; charset="charset="GB2312""
|
171
171
|
"#{$1}; charset=#{quote_atom($2)}"
|
172
|
-
when val =~ /([\w
|
172
|
+
when val =~ /([\w\-]+\/[\w\-]+);\s+(.*)/i
|
173
173
|
type = $1
|
174
174
|
# Handles misquoted param values
|
175
175
|
# e.g: application/octet-stream; name=archiveshelp1[1].htm
|
@@ -188,7 +188,7 @@ module Mail
|
|
188
188
|
|
189
189
|
def get_mime_type( val )
|
190
190
|
case
|
191
|
-
when val =~ /^([\w
|
191
|
+
when val =~ /^([\w\-]+)\/([\w\-]+);.+$/i
|
192
192
|
"#{$1}/#{$2}"
|
193
193
|
else
|
194
194
|
'text/plain'
|
data/lib/mail/message.rb
CHANGED
@@ -115,7 +115,7 @@ module Mail
|
|
115
115
|
@delivery_method = Mail.delivery_method.dup
|
116
116
|
|
117
117
|
@transport_encoding = Mail::Encodings.get_encoding('7bit')
|
118
|
-
|
118
|
+
|
119
119
|
@mark_for_delete = false
|
120
120
|
|
121
121
|
if args.flatten.first.respond_to?(:each_pair)
|
@@ -259,7 +259,9 @@ module Mail
|
|
259
259
|
bracketed_message_id = "<#{message_id}>"
|
260
260
|
reply.in_reply_to = bracketed_message_id
|
261
261
|
if !references.nil?
|
262
|
-
|
262
|
+
refs = [references].flatten.map { |r| "<#{r}>" }
|
263
|
+
refs << bracketed_message_id
|
264
|
+
reply.references = refs.join(' ')
|
263
265
|
elsif !in_reply_to.nil? && !in_reply_to.kind_of?(Array)
|
264
266
|
reply.references = "<#{in_reply_to}> #{bracketed_message_id}"
|
265
267
|
end
|
@@ -1758,9 +1760,9 @@ module Mail
|
|
1758
1760
|
end
|
1759
1761
|
|
1760
1762
|
def find_first_mime_type(mt)
|
1761
|
-
all_parts.detect { |p| p.mime_type == mt }
|
1763
|
+
all_parts.detect { |p| p.mime_type == mt && !p.attachment? }
|
1762
1764
|
end
|
1763
|
-
|
1765
|
+
|
1764
1766
|
# Skips the deletion of this message. All other messages
|
1765
1767
|
# flagged for delete still will be deleted at session close (i.e. when
|
1766
1768
|
# #find exits). Only has an effect if you're using #find_and_delete
|
@@ -1768,28 +1770,28 @@ module Mail
|
|
1768
1770
|
def skip_deletion
|
1769
1771
|
@mark_for_delete = false
|
1770
1772
|
end
|
1771
|
-
|
1772
|
-
# Sets whether this message should be deleted at session close (i.e.
|
1773
|
+
|
1774
|
+
# Sets whether this message should be deleted at session close (i.e.
|
1773
1775
|
# after #find). Message will only be deleted if messages are retrieved
|
1774
|
-
# using the #find_and_delete method, or by calling #find with
|
1775
|
-
# :delete_after_find set to true.
|
1776
|
+
# using the #find_and_delete method, or by calling #find with
|
1777
|
+
# :delete_after_find set to true.
|
1776
1778
|
def mark_for_delete=(value = true)
|
1777
1779
|
@mark_for_delete = value
|
1778
1780
|
end
|
1779
|
-
|
1781
|
+
|
1780
1782
|
# Returns whether message will be marked for deletion.
|
1781
|
-
# If so, the message will be deleted at session close (i.e. after #find
|
1782
|
-
# exits), but only if also using the #find_and_delete method, or by
|
1783
|
+
# If so, the message will be deleted at session close (i.e. after #find
|
1784
|
+
# exits), but only if also using the #find_and_delete method, or by
|
1783
1785
|
# calling #find with :delete_after_find set to true.
|
1784
1786
|
#
|
1785
1787
|
# Side-note: Just to be clear, this method will return true even if
|
1786
|
-
# the message hasn't yet been marked for delete on the mail server.
|
1788
|
+
# the message hasn't yet been marked for delete on the mail server.
|
1787
1789
|
# However, if this method returns true, it *will be* marked on the
|
1788
|
-
# server after each block yields back to #find or #find_and_delete.
|
1790
|
+
# server after each block yields back to #find or #find_and_delete.
|
1789
1791
|
def is_marked_for_delete?
|
1790
1792
|
return @mark_for_delete
|
1791
1793
|
end
|
1792
|
-
|
1794
|
+
|
1793
1795
|
private
|
1794
1796
|
|
1795
1797
|
# 2.1. General Description
|
@@ -74,7 +74,11 @@ module Mail
|
|
74
74
|
fetchdata = imap.uid_fetch(message_id, ['RFC822'])[0]
|
75
75
|
new_message = Mail.new(fetchdata.attr['RFC822'])
|
76
76
|
new_message.mark_for_delete = true if options[:delete_after_find]
|
77
|
-
|
77
|
+
if block.arity == 3
|
78
|
+
yield new_message, imap, message_id
|
79
|
+
else
|
80
|
+
yield new_message
|
81
|
+
end
|
78
82
|
imap.uid_store(message_id, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find] && new_message.is_marked_for_delete?
|
79
83
|
end
|
80
84
|
imap.expunge if options[:delete_after_find]
|
@@ -135,7 +139,13 @@ module Mail
|
|
135
139
|
raise ArgumentError.new("Mail::Retrievable#imap_start takes a block") unless block_given?
|
136
140
|
|
137
141
|
imap = Net::IMAP.new(settings[:address], settings[:port], settings[:enable_ssl], nil, false)
|
138
|
-
|
142
|
+
if settings[:authentication].nil?
|
143
|
+
imap.login(settings[:user_name], settings[:password])
|
144
|
+
else
|
145
|
+
# Note that Net::IMAP#authenticate('LOGIN', ...) is not equal with Net::IMAP#login(...)!
|
146
|
+
# (see also http://www.ensta.fr/~diam/ruby/online/ruby-doc-stdlib/libdoc/net/imap/rdoc/classes/Net/IMAP.html#M000718)
|
147
|
+
imap.authenticate(settings[:authentication], settings[:user_name], settings[:password])
|
148
|
+
end
|
139
149
|
|
140
150
|
yield imap
|
141
151
|
ensure
|
data/lib/mail/patterns.rb
CHANGED
@@ -9,6 +9,7 @@ module Mail
|
|
9
9
|
aspecial = %Q|()<>[]:;@\\,."| # RFC5322
|
10
10
|
tspecial = %Q|()<>@,;:\\"/[]?=| # RFC2045
|
11
11
|
lwsp = %Q| \t\r\n|
|
12
|
+
sp = %Q| |
|
12
13
|
control = %Q|\x00-\x1f\x7f-\xff|
|
13
14
|
|
14
15
|
if control.respond_to?(:force_encoding)
|
@@ -27,8 +28,8 @@ module Mail
|
|
27
28
|
QP_UNSAFE = /[^#{qp_safe}]/
|
28
29
|
QP_SAFE = /[#{qp_safe}]/
|
29
30
|
CONTROL_CHAR = /[#{control}]/n
|
30
|
-
ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{
|
31
|
+
ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{sp}]/n
|
31
32
|
PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
|
32
|
-
TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{
|
33
|
+
TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{sp}]/n
|
33
34
|
end
|
34
35
|
end
|
@@ -14,7 +14,7 @@ module Mail
|
|
14
14
|
str = escape_paren( str )
|
15
15
|
'(' + str + ')'
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def Ruby19.escape_bracket( str )
|
19
19
|
re = /(?<!\\)([\<\>])/ # Only match unescaped brackets
|
20
20
|
str.gsub(re) { |s| '\\' + s }
|
@@ -29,34 +29,34 @@ module Mail
|
|
29
29
|
def Ruby19.decode_base64(str)
|
30
30
|
str.unpack( 'm' ).first.force_encoding(Encoding::BINARY)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def Ruby19.encode_base64(str)
|
34
34
|
[str].pack( 'm' )
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def Ruby19.has_constant?(klass, string)
|
38
38
|
klass.constants.include?( string.to_sym )
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def Ruby19.get_constant(klass, string)
|
42
42
|
klass.const_get( string.to_sym )
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def Ruby19.b_value_encode(str, encoding = nil)
|
46
46
|
encoding = str.encoding.to_s
|
47
47
|
[Ruby19.encode_base64(str), encoding]
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def Ruby19.b_value_decode(str)
|
51
51
|
match = str.match(/\=\?(.+)?\?[Bb]\?(.+)?\?\=/m)
|
52
52
|
if match
|
53
53
|
encoding = match[1]
|
54
|
-
str = Ruby19.decode_base64(match[2])
|
54
|
+
str = Ruby19.decode_base64(match[2].to_s)
|
55
55
|
str.force_encoding(encoding)
|
56
56
|
end
|
57
57
|
str
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def Ruby19.q_value_encode(str, encoding = nil)
|
61
61
|
encoding = str.encoding.to_s
|
62
62
|
[Encodings::QuotedPrintable.encode(str), encoding]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 2.2.
|
9
|
+
- 13
|
10
|
+
version: 2.2.13
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mikel Lindsaar
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-23 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -99,6 +99,7 @@ files:
|
|
99
99
|
- lib/mail/body.rb
|
100
100
|
- lib/mail/configuration.rb
|
101
101
|
- lib/mail/core_extensions/nil.rb
|
102
|
+
- lib/mail/core_extensions/smtp.rb
|
102
103
|
- lib/mail/core_extensions/string.rb
|
103
104
|
- lib/mail/elements/address.rb
|
104
105
|
- lib/mail/elements/address_list.rb
|