mail 2.6.6 → 2.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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