mail 2.6.6 → 2.7.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +25 -6
  3. data/Dependencies.txt +0 -1
  4. data/Gemfile +5 -8
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +22 -11
  7. data/Rakefile +0 -6
  8. data/lib/mail.rb +2 -10
  9. data/lib/mail/attachments_list.rb +3 -2
  10. data/lib/mail/body.rb +3 -3
  11. data/lib/mail/core_extensions/smtp.rb +19 -16
  12. data/lib/mail/core_extensions/string.rb +0 -4
  13. data/lib/mail/elements/address.rb +9 -4
  14. data/lib/mail/elements/address_list.rb +10 -18
  15. data/lib/mail/elements/content_disposition_element.rb +8 -15
  16. data/lib/mail/elements/content_location_element.rb +5 -10
  17. data/lib/mail/elements/content_transfer_encoding_element.rb +5 -10
  18. data/lib/mail/elements/content_type_element.rb +8 -19
  19. data/lib/mail/elements/date_time_element.rb +6 -14
  20. data/lib/mail/elements/envelope_from_element.rb +14 -21
  21. data/lib/mail/elements/message_ids_element.rb +8 -12
  22. data/lib/mail/elements/mime_version_element.rb +6 -14
  23. data/lib/mail/elements/phrase_list.rb +6 -9
  24. data/lib/mail/elements/received_element.rb +9 -15
  25. data/lib/mail/encodings.rb +12 -14
  26. data/lib/mail/field.rb +7 -4
  27. data/lib/mail/fields/common/parameter_hash.rb +1 -1
  28. data/lib/mail/fields/content_type_field.rb +2 -7
  29. data/lib/mail/fields/unstructured_field.rb +2 -2
  30. data/lib/mail/header.rb +1 -0
  31. data/lib/mail/message.rb +23 -25
  32. data/lib/mail/multibyte.rb +51 -0
  33. data/lib/mail/multibyte/chars.rb +27 -27
  34. data/lib/mail/network/delivery_methods/exim.rb +10 -6
  35. data/lib/mail/network/delivery_methods/sendmail.rb +2 -6
  36. data/lib/mail/network/delivery_methods/smtp.rb +14 -6
  37. data/lib/mail/parsers.rb +16 -24
  38. data/lib/mail/parsers/address_lists_parser.rb +15321 -112
  39. data/lib/mail/parsers/address_lists_parser.rl +166 -0
  40. data/lib/mail/parsers/content_disposition_parser.rb +698 -55
  41. data/lib/mail/parsers/content_disposition_parser.rl +76 -0
  42. data/lib/mail/parsers/content_location_parser.rb +565 -23
  43. data/lib/mail/parsers/content_location_parser.rl +65 -0
  44. data/lib/mail/parsers/content_transfer_encoding_parser.rb +410 -22
  45. data/lib/mail/parsers/content_transfer_encoding_parser.rl +58 -0
  46. data/lib/mail/parsers/content_type_parser.rb +841 -54
  47. data/lib/mail/parsers/content_type_parser.rl +77 -0
  48. data/lib/mail/parsers/date_time_parser.rb +773 -26
  49. data/lib/mail/parsers/date_time_parser.rl +56 -0
  50. data/lib/mail/parsers/envelope_from_parser.rb +2051 -36
  51. data/lib/mail/parsers/envelope_from_parser.rl +76 -0
  52. data/lib/mail/parsers/message_ids_parser.rb +1494 -25
  53. data/lib/mail/parsers/message_ids_parser.rl +76 -0
  54. data/lib/mail/parsers/mime_version_parser.rb +393 -26
  55. data/lib/mail/parsers/mime_version_parser.rl +55 -0
  56. data/lib/mail/parsers/phrase_lists_parser.rb +529 -19
  57. data/lib/mail/parsers/phrase_lists_parser.rl +77 -0
  58. data/lib/mail/parsers/received_parser.rb +4711 -38
  59. data/lib/mail/parsers/received_parser.rl +78 -0
  60. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +12 -0
  61. data/lib/mail/parsers/rfc2045_content_type.rl +24 -0
  62. data/lib/mail/parsers/rfc2045_mime.rl +15 -0
  63. data/lib/mail/parsers/rfc2183_content_disposition.rl +14 -0
  64. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +16 -0
  65. data/lib/mail/parsers/rfc5322.rl +57 -0
  66. data/lib/mail/parsers/rfc5322_address.rl +70 -0
  67. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +7 -1
  68. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +56 -0
  69. data/lib/mail/part.rb +1 -1
  70. data/lib/mail/parts_list.rb +5 -6
  71. data/lib/mail/utilities.rb +4 -2
  72. data/lib/mail/version.rb +3 -3
  73. data/lib/mail/version_specific/ruby_1_8.rb +28 -2
  74. data/lib/mail/version_specific/ruby_1_9.rb +48 -8
  75. metadata +28 -45
  76. data/lib/mail/core_extensions/string/access.rb +0 -146
  77. data/lib/mail/core_extensions/string/multibyte.rb +0 -79
  78. data/lib/mail/parsers/ragel.rb +0 -18
  79. data/lib/mail/parsers/ragel/common.rl +0 -185
  80. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  81. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  82. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  83. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  84. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  85. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  86. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  87. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  88. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  89. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  90. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  91. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  92. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  93. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  94. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  95. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  96. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  97. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  98. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  99. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  100. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  101. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  102. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  103. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  104. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  105. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
@@ -1,18 +1,13 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/content_transfer_encoding_parser'
4
+
3
5
  module Mail
4
6
  class ContentTransferEncodingElement
5
-
6
- include Mail::Utilities
7
-
7
+ attr_reader :encoding
8
+
8
9
  def initialize(string)
9
- content_transfer_encoding = Mail::Parsers::ContentTransferEncodingParser.new.parse(string)
10
- @encoding = content_transfer_encoding.encoding
10
+ @encoding = Mail::Parsers::ContentTransferEncodingParser.parse(string).encoding
11
11
  end
12
-
13
- def encoding
14
- @encoding
15
- end
16
-
17
12
  end
18
13
  end
@@ -1,32 +1,21 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/content_type_parser'
4
+
3
5
  module Mail
4
6
  class ContentTypeElement # :nodoc:
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- content_type = Mail::Parsers::ContentTypeParser.new.parse(cleaned(string))
7
+ attr_reader :main_type, :sub_type, :parameters
8
+
9
+ def initialize(string)
10
+ content_type = Mail::Parsers::ContentTypeParser.parse(cleaned(string))
10
11
  @main_type = content_type.main_type
11
12
  @sub_type = content_type.sub_type
12
13
  @parameters = content_type.parameters
13
14
  end
14
-
15
- def main_type
16
- @main_type
17
- end
18
-
19
- def sub_type
20
- @sub_type
21
- end
22
-
23
- def parameters
24
- @parameters
25
- end
26
-
15
+
16
+ private
27
17
  def cleaned(string)
28
18
  string =~ /(.+);\s*$/ ? $1 : string
29
19
  end
30
-
31
20
  end
32
21
  end
@@ -1,23 +1,15 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/date_time_parser'
4
+
3
5
  module Mail
4
6
  class DateTimeElement # :nodoc:
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- date_time = Mail::Parsers::DateTimeParser.new.parse(string)
7
+ attr_reader :date_string, :time_string
8
+
9
+ def initialize(string)
10
+ date_time = Mail::Parsers::DateTimeParser.parse(string)
10
11
  @date_string = date_time.date_string
11
12
  @time_string = date_time.time_string
12
13
  end
13
-
14
- def date_string
15
- @date_string
16
- end
17
-
18
- def time_string
19
- @time_string
20
- end
21
-
22
14
  end
23
15
  end
@@ -1,40 +1,33 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/envelope_from_parser'
4
+ require 'date'
5
+
3
6
  module Mail
4
7
  class EnvelopeFromElement
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- @envelope_from = Mail::Parsers::EnvelopeFromParser.new.parse(string)
10
- @address = @envelope_from.address
11
- @date_time = ::DateTime.parse(@envelope_from.ctime_date)
12
- end
13
-
14
- def date_time
15
- @date_time
16
- end
17
-
18
- def address
19
- @address
8
+ attr_reader :date_time, :address
9
+
10
+ def initialize(string)
11
+ envelope_from = Mail::Parsers::EnvelopeFromParser.parse(string)
12
+ @address = envelope_from.address
13
+ @date_time = ::DateTime.parse(envelope_from.ctime_date)
20
14
  end
21
-
15
+
22
16
  # RFC 4155:
23
17
  # a timestamp indicating the UTC date and time when the message
24
18
  # was originally received, conformant with the syntax of the
25
19
  # traditional UNIX 'ctime' output sans timezone (note that the
26
20
  # use of UTC precludes the need for a timezone indicator);
27
21
  def formatted_date_time
28
- if @date_time.respond_to?(:ctime)
29
- @date_time.ctime
22
+ if date_time.respond_to?(:ctime)
23
+ date_time.ctime
30
24
  else
31
- @date_time.strftime '%a %b %e %T %Y'
25
+ date_time.strftime '%a %b %e %T %Y'
32
26
  end
33
27
  end
34
28
 
35
29
  def to_s
36
- "#{@address} #{formatted_date_time}"
30
+ "#{address} #{formatted_date_time}"
37
31
  end
38
-
39
32
  end
40
33
  end
@@ -1,26 +1,22 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/message_ids_parser'
4
+
3
5
  module Mail
4
6
  class MessageIdsElement
5
-
6
- include Mail::Utilities
7
+ attr_reader :message_ids
7
8
 
8
9
  def initialize(string)
9
- raise Mail::Field::ParseError.new(Mail::MessageIdsElement, string, 'nil is invalid') if string.nil?
10
- @message_ids = Mail::Parsers::MessageIdsParser.new.parse(string).message_ids.map { |msg_id| clean_msg_id(msg_id) }
11
- end
12
-
13
- def message_ids
14
- @message_ids
10
+ @message_ids = Mail::Parsers::MessageIdsParser.parse(string).message_ids.map { |msg_id| clean_msg_id(msg_id) }
15
11
  end
16
12
 
17
13
  def message_id
18
- @message_ids.first
14
+ message_ids.first
19
15
  end
20
16
 
21
- def clean_msg_id( val )
22
- val =~ /.*<(.*)>.*/ ; $1
17
+ private
18
+ def clean_msg_id(val)
19
+ val =~ /.*<(.*)>.*/ ? $1 : val
23
20
  end
24
-
25
21
  end
26
22
  end
@@ -1,23 +1,15 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/mime_version_parser'
4
+
3
5
  module Mail
4
6
  class MimeVersionElement
5
-
6
- include Mail::Utilities
7
-
8
- def initialize( string )
9
- mime_version = Mail::Parsers::MimeVersionParser.new.parse(string)
7
+ attr_reader :major, :minor
8
+
9
+ def initialize(string)
10
+ mime_version = Mail::Parsers::MimeVersionParser.parse(string)
10
11
  @major = mime_version.major
11
12
  @minor = mime_version.minor
12
13
  end
13
-
14
- def major
15
- @major
16
- end
17
-
18
- def minor
19
- @minor
20
- end
21
-
22
14
  end
23
15
  end
@@ -1,17 +1,14 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/phrase_lists_parser'
4
+ require 'mail/utilities'
5
+
3
6
  module Mail
4
7
  class PhraseList
5
-
6
- include Mail::Utilities
7
-
8
+ attr_reader :phrases
9
+
8
10
  def initialize(string)
9
- @phrase_lists = Mail::Parsers::PhraseListsParser.new.parse(string)
11
+ @phrases = Mail::Parsers::PhraseListsParser.parse(string).phrases.map { |p| Mail::Utilities.unquote(p) }
10
12
  end
11
-
12
- def phrases
13
- @phrase_lists.phrases.map { |p| unquote(p) }
14
- end
15
-
16
13
  end
17
14
  end
@@ -1,27 +1,21 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/parsers/received_parser'
4
+ require 'date'
5
+
3
6
  module Mail
4
7
  class ReceivedElement
5
-
6
8
  include Mail::Utilities
7
-
8
- def initialize( string )
9
- received = Mail::Parsers::ReceivedParser.new.parse(string)
9
+ attr_reader :date_time, :info
10
+
11
+ def initialize(string)
12
+ received = Mail::Parsers::ReceivedParser.parse(string)
10
13
  @date_time = ::DateTime.parse("#{received.date} #{received.time}")
11
14
  @info = received.info
12
15
  end
13
-
14
- def date_time
15
- @date_time
16
- end
17
-
18
- def info
19
- @info
20
- end
21
-
16
+
22
17
  def to_s(*args)
23
- "#{@info}; #{@date_time.to_s(*args)}"
18
+ "#{info}; #{date_time.to_s(*args)}"
24
19
  end
25
-
26
20
  end
27
21
  end
@@ -178,9 +178,8 @@ module Mail
178
178
 
179
179
  def Encodings.encode_non_usascii(address, charset)
180
180
  return address if address.ascii_only? or charset.nil?
181
- us_ascii = %Q{\x00-\x7f}
182
- # Encode any non usascii strings embedded inside of quotes
183
- address = address.gsub(/(".*?[^#{us_ascii}].*?")/) { |s| Encodings.b_value_encode(unquote(s), charset) }
181
+ # Encode all strings embedded inside of quotes
182
+ address = address.gsub(/("[^"]*")/) { |s| Encodings.b_value_encode(unquote(s), charset) }
184
183
  # Then loop through all remaining items and encode as needed
185
184
  tokens = address.split(/\s/)
186
185
  map_with_index(tokens) do |word, i|
@@ -258,24 +257,23 @@ module Mail
258
257
  str[ENCODED_VALUE, 1]
259
258
  end
260
259
 
261
- # When the encoded string consists of multiple lines, lines with the same
262
- # encoding (Q or B) can be joined together.
260
+ # Split header line into proper encoded and unencoded parts.
263
261
  #
264
262
  # String has to be of the format =?<encoding>?[QB]?<string>?=
263
+ #
264
+ # Omit unencoded space after an encoded-word.
265
265
  def Encodings.collapse_adjacent_encodings(str)
266
266
  results = []
267
- previous_encoding = nil
267
+ last_encoded = nil # Track whether to preserve or drop whitespace
268
+
268
269
  lines = str.split(FULL_ENCODED_VALUE)
269
270
  lines.each_slice(2) do |unencoded, encoded|
270
- if encoded
271
- encoding = value_encoding_from_string(encoded)
272
- if encoding == previous_encoding && Utilities.blank?(unencoded)
273
- results.last << encoded
274
- else
275
- results << unencoded unless unencoded == EMPTY
276
- results << encoded
271
+ if last_encoded = encoded
272
+ if !Utilities.blank?(unencoded) || (!last_encoded && unencoded != EMPTY)
273
+ results << unencoded
277
274
  end
278
- previous_encoding = encoding
275
+
276
+ results << encoded
279
277
  else
280
278
  results << unencoded
281
279
  end
data/lib/mail/field.rb CHANGED
@@ -218,10 +218,13 @@ module Mail
218
218
  private
219
219
 
220
220
  def split(raw_field)
221
- match_data = raw_field.mb_chars.match(FIELD_SPLIT)
222
- [match_data[1].to_s.mb_chars.strip, match_data[2].to_s.mb_chars.strip.to_s]
221
+ match_data = Mail::Multibyte.mb_chars(raw_field).match(FIELD_SPLIT)
222
+ [
223
+ Mail::Multibyte.mb_chars(match_data[1].to_s).strip,
224
+ Mail::Multibyte.mb_chars(match_data[2].to_s).strip.to_s
225
+ ]
223
226
  rescue
224
- STDERR.puts "WARNING: Could not parse (and so ignoring) '#{raw_field}'"
227
+ $stderr.puts "WARNING: Could not parse (and so ignoring) '#{raw_field}'"
225
228
  end
226
229
 
227
230
  # 2.2.3. Long Header Fields
@@ -233,7 +236,7 @@ module Mail
233
236
  # treated in its unfolded form for further syntactic and semantic
234
237
  # evaluation.
235
238
  def unfold(string)
236
- string.gsub(/[\r\n \t]+/m, ' ')
239
+ string.gsub(/#{CRLF}(#{WSP})/m, '\1')
237
240
  end
238
241
 
239
242
  def create_field(name, value, charset)
@@ -30,7 +30,7 @@ module Mail
30
30
  super(exact || key_name)
31
31
  else # Dealing with a multiple value pair or a single encoded value pair
32
32
  string = pairs.sort { |a,b| a.first.to_s <=> b.first.to_s }.map { |v| v.last }.join('')
33
- if mt = string.match(/([\w\-]+)'(\w\w)'(.*)/)
33
+ if mt = string.match(/([\w\-]+)?'(\w\w)?'(.*)/)
34
34
  string = mt[3]
35
35
  encoding = mt[1]
36
36
  else
@@ -145,9 +145,7 @@ module Mail
145
145
  # TODO: check if there are cases where whitespace is not a separator
146
146
  val = val.
147
147
  gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
148
- tr(' ',';').
149
- squeeze(';').
150
- gsub(';', '; '). #use '; ' as a separator (or EOL)
148
+ gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL)
151
149
  gsub(/;\s*$/,'') #remove trailing to keep examples below
152
150
 
153
151
  if val =~ /(boundary=(\S*))/i
@@ -157,9 +155,6 @@ module Mail
157
155
  end
158
156
 
159
157
  case
160
- when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;;+(.*)$/i
161
- # Handles 'text/plain;; format="flowed"' (double semi colon)
162
- "#{$1}/#{$2}; #{$3}"
163
158
  when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
164
159
  # Microsoft helper:
165
160
  # Handles 'type/subtype;ISO-8559-1'
@@ -186,7 +181,7 @@ module Mail
186
181
  when val =~ /^\s*$/
187
182
  'text/plain'
188
183
  else
189
- ''
184
+ val
190
185
  end
191
186
  end
192
187
 
@@ -121,7 +121,7 @@ module Mail
121
121
  def fold(prepend = 0) # :nodoc:
122
122
  encoding = normalized_encoding
123
123
  decoded_string = decoded.to_s
124
- should_encode = decoded_string.not_ascii_only?
124
+ should_encode = !decoded_string.ascii_only?
125
125
  if should_encode
126
126
  first = true
127
127
  words = decoded_string.split(/[ \t]/).map do |word|
@@ -130,7 +130,7 @@ module Mail
130
130
  else
131
131
  word = " #{word}"
132
132
  end
133
- if word.not_ascii_only?
133
+ if !word.ascii_only?
134
134
  word
135
135
  else
136
136
  word.scan(/.{7}|.+$/)
data/lib/mail/header.rb CHANGED
@@ -57,6 +57,7 @@ module Mail
57
57
  def initialize_copy(original)
58
58
  super
59
59
  @fields = @fields.dup
60
+ @fields.map!(&:dup)
60
61
  end
61
62
 
62
63
  # The preserved raw source of the header as you passed it in, untouched
data/lib/mail/message.rb CHANGED
@@ -213,7 +213,7 @@ module Mail
213
213
  self.default_charset = 'UTF-8'
214
214
 
215
215
  def register_for_delivery_notification(observer)
216
- STDERR.puts("Message#register_for_delivery_notification is deprecated, please call Mail.register_observer instead")
216
+ $stderr.puts("Message#register_for_delivery_notification is deprecated, please call Mail.register_observer instead")
217
217
  Mail.register_observer(observer)
218
218
  end
219
219
 
@@ -360,13 +360,8 @@ module Mail
360
360
  if self.message_id && other.message_id
361
361
  self.encoded == other.encoded
362
362
  else
363
- self_message_id, other_message_id = self.message_id, other.message_id
364
- begin
365
- self.message_id, other.message_id = '<temp@test>', '<temp@test>'
366
- self.encoded == other.encoded
367
- ensure
368
- self.message_id, other.message_id = self_message_id, other_message_id
369
- end
363
+ dup.tap { |m| m.message_id = '<temp@test>' }.encoded ==
364
+ other.dup.tap { |m| m.message_id = '<temp@test>' }.encoded
370
365
  end
371
366
  end
372
367
 
@@ -1420,7 +1415,7 @@ module Mail
1420
1415
  end
1421
1416
 
1422
1417
  def has_transfer_encoding? # :nodoc:
1423
- STDERR.puts(":has_transfer_encoding? is deprecated in Mail 1.4.3. Please use has_content_transfer_encoding?\n#{caller}")
1418
+ $stderr.puts(":has_transfer_encoding? is deprecated in Mail 1.4.3. Please use has_content_transfer_encoding?\n#{caller}")
1424
1419
  has_content_transfer_encoding?
1425
1420
  end
1426
1421
 
@@ -1468,9 +1463,9 @@ module Mail
1468
1463
  if !body.empty?
1469
1464
  # Only give a warning if this isn't an attachment, has non US-ASCII and the user
1470
1465
  # has not specified an encoding explicitly.
1471
- if @defaulted_charset && body.raw_source.not_ascii_only? && !self.attachment?
1466
+ if @defaulted_charset && !body.raw_source.ascii_only? && !self.attachment?
1472
1467
  warning = "Non US-ASCII detected and no charset defined.\nDefaulting to UTF-8, set your own if this is incorrect.\n"
1473
- STDERR.puts(warning)
1468
+ $stderr.puts(warning)
1474
1469
  end
1475
1470
  header[:content_type].parameters['charset'] = @charset
1476
1471
  end
@@ -1484,18 +1479,18 @@ module Mail
1484
1479
  header[:content_transfer_encoding] = '7bit'
1485
1480
  else
1486
1481
  warning = "Non US-ASCII detected and no content-transfer-encoding defined.\nDefaulting to 8bit, set your own if this is incorrect.\n"
1487
- STDERR.puts(warning)
1482
+ $stderr.puts(warning)
1488
1483
  header[:content_transfer_encoding] = '8bit'
1489
1484
  end
1490
1485
  end
1491
1486
 
1492
1487
  def add_transfer_encoding # :nodoc:
1493
- STDERR.puts(":add_transfer_encoding is deprecated in Mail 1.4.3. Please use add_content_transfer_encoding\n#{caller}")
1488
+ $stderr.puts(":add_transfer_encoding is deprecated in Mail 1.4.3. Please use add_content_transfer_encoding\n#{caller}")
1494
1489
  add_content_transfer_encoding
1495
1490
  end
1496
1491
 
1497
1492
  def transfer_encoding # :nodoc:
1498
- STDERR.puts(":transfer_encoding is deprecated in Mail 1.4.3. Please use content_transfer_encoding\n#{caller}")
1493
+ $stderr.puts(":transfer_encoding is deprecated in Mail 1.4.3. Please use content_transfer_encoding\n#{caller}")
1499
1494
  content_transfer_encoding
1500
1495
  end
1501
1496
 
@@ -1505,7 +1500,7 @@ module Mail
1505
1500
  end
1506
1501
 
1507
1502
  def message_content_type
1508
- STDERR.puts(":message_content_type is deprecated in Mail 1.4.3. Please use mime_type\n#{caller}")
1503
+ $stderr.puts(":message_content_type is deprecated in Mail 1.4.3. Please use mime_type\n#{caller}")
1509
1504
  mime_type
1510
1505
  end
1511
1506
 
@@ -1537,7 +1532,7 @@ module Mail
1537
1532
 
1538
1533
  # Returns the content type parameters
1539
1534
  def mime_parameters
1540
- STDERR.puts(':mime_parameters is deprecated in Mail 1.4.3, please use :content_type_parameters instead')
1535
+ $stderr.puts(':mime_parameters is deprecated in Mail 1.4.3, please use :content_type_parameters instead')
1541
1536
  content_type_parameters
1542
1537
  end
1543
1538
 
@@ -1563,7 +1558,14 @@ module Mail
1563
1558
 
1564
1559
  # returns the part in a multipart/report email that has the content-type delivery-status
1565
1560
  def delivery_status_part
1566
- @delivery_stats_part ||= parts.select { |p| p.delivery_status_report_part? }.first
1561
+ unless defined? @delivery_status_part
1562
+ @delivery_status_part =
1563
+ if delivery_status_report?
1564
+ parts.detect(&:delivery_status_report_part?)
1565
+ end
1566
+ end
1567
+
1568
+ @delivery_status_part
1567
1569
  end
1568
1570
 
1569
1571
  def bounced?
@@ -1798,7 +1800,6 @@ module Mail
1798
1800
  # ready to send
1799
1801
  def ready_to_send!
1800
1802
  identify_and_set_transfer_encoding
1801
- parts.sort!([ "text/plain", "text/enriched", "text/html", "multipart/alternative" ])
1802
1803
  parts.each do |part|
1803
1804
  part.transport_encoding = transport_encoding
1804
1805
  part.ready_to_send!
@@ -1807,7 +1808,7 @@ module Mail
1807
1808
  end
1808
1809
 
1809
1810
  def encode!
1810
- STDERR.puts("Deprecated in 1.1.0 in favour of :ready_to_send! as it is less confusing with encoding and decoding.")
1811
+ $stderr.puts("Deprecated in 1.1.0 in favour of :ready_to_send! as it is less confusing with encoding and decoding.")
1811
1812
  ready_to_send!
1812
1813
  end
1813
1814
 
@@ -1975,7 +1976,7 @@ module Mail
1975
1976
 
1976
1977
  private
1977
1978
 
1978
- HEADER_SEPARATOR = /#{CRLF}#{CRLF}|#{CRLF}#{WSP}*#{CRLF}(?!#{WSP})/m
1979
+ HEADER_SEPARATOR = /#{CRLF}#{CRLF}/
1979
1980
 
1980
1981
  # 2.1. General Description
1981
1982
  # A message consists of header fields (collectively called "the header
@@ -1984,9 +1985,6 @@ module Mail
1984
1985
  # this standard. The body is simply a sequence of characters that
1985
1986
  # follows the header and is separated from the header by an empty line
1986
1987
  # (i.e., a line with nothing preceding the CRLF).
1987
- #
1988
- # Additionally, I allow for the case where someone might have put whitespace
1989
- # on the "gap line"
1990
1988
  def parse_message
1991
1989
  header_part, body_part = raw_source.lstrip.split(HEADER_SEPARATOR, 2)
1992
1990
  self.header = header_part
@@ -2130,10 +2128,10 @@ module Mail
2130
2128
  content_disp_name = header[:content_disposition].filename rescue nil
2131
2129
  content_loc_name = header[:content_location].location rescue nil
2132
2130
  case
2133
- when content_type && content_type_name
2134
- filename = content_type_name
2135
2131
  when content_disposition && content_disp_name
2136
2132
  filename = content_disp_name
2133
+ when content_type && content_type_name
2134
+ filename = content_type_name
2137
2135
  when content_location && content_loc_name
2138
2136
  filename = content_loc_name
2139
2137
  else