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.

@@ -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)
@@ -1,4 +1,4 @@
1
- patch:12
1
+ patch:13
2
2
  major:2
3
3
  build:
4
4
  minor:2
@@ -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
- default_values = { :content_type => "#{set_mime_type(name)}; filename=\"#{name}\"",
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=\"#{name}\"" }
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&amp;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
 
@@ -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\d\-]+)'(\w\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\d\-_]+)\/([\w\d\-_]+)\s*;;+(.*)$/i
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\d\-_]+)\/([\w\d\-_]+)\s*;\s?(ISO[\w\d\-_]+)$/i
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\d\-_]+\/[\w\d\-_]+);\scharset="charset="(\w+)""/i
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\d\-_]+\/[\w\d\-_]+);\s+(.*)/i
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\d\-_]+)\/([\w\d\-_]+);.+$/i
191
+ when val =~ /^([\w\-]+)\/([\w\-]+);.+$/i
192
192
  "#{$1}/#{$2}"
193
193
  else
194
194
  'text/plain'
@@ -41,6 +41,8 @@ module Mail
41
41
  value = ::DateTime.parse(value.to_s.squeeze(" ")).strftime('%a, %d %b %Y %H:%M:%S %z')
42
42
  end
43
43
  super(CAPITALIZED_FIELD, value, charset)
44
+ rescue ArgumentError => e
45
+ raise e unless "invalid date"==e.message
44
46
  end
45
47
 
46
48
  def encoded
@@ -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
- reply.references = (references.to_a.map { |r| "<#{r}>" } << bracketed_message_id).join(' ')
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
- yield new_message
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
- imap.login(settings[:user_name], settings[:password])
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
@@ -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}#{lwsp}]/n
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}#{lwsp}]/n
33
+ TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{sp}]/n
33
34
  end
34
35
  end
@@ -37,7 +37,7 @@ module Mail
37
37
  end
38
38
 
39
39
  def Ruby18.decode_base64(str)
40
- Base64.decode64(str)
40
+ Base64.decode64(str) if str
41
41
  end
42
42
 
43
43
  def Ruby18.encode_base64(str)
@@ -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: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 2
9
- - 12
10
- version: 2.2.12
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-05 00:00:00 +11:00
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