mail 2.5.5 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +8 -9
  3. data/CONTRIBUTING.md +13 -0
  4. data/Dependencies.txt +0 -1
  5. data/Gemfile +7 -24
  6. data/README.md +36 -15
  7. data/Rakefile +10 -2
  8. data/VERSION +4 -0
  9. data/lib/mail.rb +1 -1
  10. data/lib/mail/body.rb +2 -2
  11. data/lib/mail/check_delivery_params.rb +10 -47
  12. data/lib/mail/core_extensions/string.rb +12 -2
  13. data/lib/mail/elements/address.rb +38 -82
  14. data/lib/mail/elements/address_list.rb +19 -42
  15. data/lib/mail/elements/content_disposition_element.rb +3 -7
  16. data/lib/mail/elements/content_location_element.rb +2 -6
  17. data/lib/mail/elements/content_transfer_encoding_element.rb +3 -10
  18. data/lib/mail/elements/content_type_element.rb +4 -8
  19. data/lib/mail/elements/date_time_element.rb +3 -7
  20. data/lib/mail/elements/envelope_from_element.rb +3 -11
  21. data/lib/mail/elements/message_ids_element.rb +1 -6
  22. data/lib/mail/elements/mime_version_element.rb +3 -7
  23. data/lib/mail/elements/phrase_list.rb +2 -7
  24. data/lib/mail/elements/received_element.rb +3 -7
  25. data/lib/mail/encodings.rb +0 -1
  26. data/lib/mail/envelope.rb +0 -5
  27. data/lib/mail/field.rb +53 -17
  28. data/lib/mail/field_list.rb +18 -18
  29. data/lib/mail/fields/common/common_address.rb +15 -20
  30. data/lib/mail/fields/common/common_date.rb +0 -7
  31. data/lib/mail/fields/common/common_field.rb +1 -1
  32. data/lib/mail/fields/content_transfer_encoding_field.rb +0 -6
  33. data/lib/mail/fields/resent_sender_field.rb +1 -1
  34. data/lib/mail/fields/sender_field.rb +1 -1
  35. data/lib/mail/fields/unstructured_field.rb +7 -1
  36. data/lib/mail/header.rb +8 -22
  37. data/lib/mail/mail.rb +12 -0
  38. data/lib/mail/matchers/has_sent_mail.rb +34 -1
  39. data/lib/mail/message.rb +18 -11
  40. data/lib/mail/multibyte/unicode.rb +1 -1
  41. data/lib/mail/network/delivery_methods/exim.rb +10 -6
  42. data/lib/mail/network/delivery_methods/file_delivery.rb +8 -4
  43. data/lib/mail/network/delivery_methods/sendmail.rb +7 -9
  44. data/lib/mail/network/delivery_methods/smtp.rb +5 -2
  45. data/lib/mail/network/delivery_methods/smtp_connection.rb +6 -2
  46. data/lib/mail/network/delivery_methods/test_mailer.rb +8 -5
  47. data/lib/mail/network/retriever_methods/imap.rb +18 -13
  48. data/lib/mail/parsers.rb +26 -0
  49. data/lib/mail/parsers/address_lists_parser.rb +132 -0
  50. data/lib/mail/parsers/content_disposition_parser.rb +67 -0
  51. data/lib/mail/parsers/content_location_parser.rb +35 -0
  52. data/lib/mail/parsers/content_transfer_encoding_parser.rb +33 -0
  53. data/lib/mail/parsers/content_type_parser.rb +64 -0
  54. data/lib/mail/parsers/date_time_parser.rb +36 -0
  55. data/lib/mail/parsers/envelope_from_parser.rb +45 -0
  56. data/lib/mail/parsers/message_ids_parser.rb +39 -0
  57. data/lib/mail/parsers/mime_version_parser.rb +41 -0
  58. data/lib/mail/parsers/phrase_lists_parser.rb +33 -0
  59. data/lib/mail/parsers/ragel.rb +17 -0
  60. data/lib/mail/parsers/ragel/common.rl +184 -0
  61. data/lib/mail/parsers/ragel/date_time.rl +30 -0
  62. data/lib/mail/parsers/ragel/parser_info.rb +61 -0
  63. data/lib/mail/parsers/ragel/ruby.rb +29 -0
  64. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +14864 -0
  65. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +37 -0
  66. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +751 -0
  67. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +37 -0
  68. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +614 -0
  69. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +37 -0
  70. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +447 -0
  71. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +37 -0
  72. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +825 -0
  73. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +37 -0
  74. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +817 -0
  75. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +37 -0
  76. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +2129 -0
  77. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +37 -0
  78. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +1570 -0
  79. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +37 -0
  80. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +440 -0
  81. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +37 -0
  82. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +564 -0
  83. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +37 -0
  84. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +51 -0
  85. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +5144 -0
  86. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +37 -0
  87. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +37 -0
  88. data/lib/mail/parsers/received_parser.rb +47 -0
  89. data/lib/mail/parts_list.rb +4 -2
  90. data/lib/mail/patterns.rb +3 -1
  91. data/lib/mail/utilities.rb +3 -1
  92. data/lib/mail/version.rb +1 -1
  93. data/lib/mail/version_specific/ruby_1_8.rb +1 -1
  94. data/lib/mail/version_specific/ruby_1_9.rb +13 -1
  95. metadata +55 -51
  96. data/lib/VERSION +0 -4
  97. data/lib/load_parsers.rb +0 -35
  98. data/lib/mail/parsers/address_lists.rb +0 -64
  99. data/lib/mail/parsers/address_lists.treetop +0 -19
  100. data/lib/mail/parsers/content_disposition.rb +0 -535
  101. data/lib/mail/parsers/content_disposition.treetop +0 -46
  102. data/lib/mail/parsers/content_location.rb +0 -139
  103. data/lib/mail/parsers/content_location.treetop +0 -20
  104. data/lib/mail/parsers/content_transfer_encoding.rb +0 -201
  105. data/lib/mail/parsers/content_transfer_encoding.treetop +0 -18
  106. data/lib/mail/parsers/content_type.rb +0 -971
  107. data/lib/mail/parsers/content_type.treetop +0 -68
  108. data/lib/mail/parsers/date_time.rb +0 -114
  109. data/lib/mail/parsers/date_time.treetop +0 -11
  110. data/lib/mail/parsers/envelope_from.rb +0 -194
  111. data/lib/mail/parsers/envelope_from.treetop +0 -32
  112. data/lib/mail/parsers/message_ids.rb +0 -45
  113. data/lib/mail/parsers/message_ids.treetop +0 -15
  114. data/lib/mail/parsers/mime_version.rb +0 -144
  115. data/lib/mail/parsers/mime_version.treetop +0 -19
  116. data/lib/mail/parsers/phrase_lists.rb +0 -45
  117. data/lib/mail/parsers/phrase_lists.treetop +0 -15
  118. data/lib/mail/parsers/received.rb +0 -71
  119. data/lib/mail/parsers/received.treetop +0 -11
  120. data/lib/mail/parsers/rfc2045.rb +0 -421
  121. data/lib/mail/parsers/rfc2045.treetop +0 -35
  122. data/lib/mail/parsers/rfc2822.rb +0 -5397
  123. data/lib/mail/parsers/rfc2822.treetop +0 -408
  124. data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
  125. data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
  126. data/lib/tasks/corpus.rake +0 -125
  127. data/lib/tasks/treetop.rake +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 483ee321c6ec26a7fb20deb57c50254f916c5055
4
- data.tar.gz: 49bbe456db7b901b8f9a17cc404ed6cdd4ac84f2
3
+ metadata.gz: ecb5e9115e61802f251480eef90c6698ac665d0b
4
+ data.tar.gz: a1105d5defc2c7b374598a392e5f5dc4d1452a21
5
5
  SHA512:
6
- metadata.gz: bc79fcc391b2358f8aecd403453c934399a561bd2cf0c3cb32bf850815a6c99086c47104e0680a7d77a62585453bef8ca27d885f0345d102e0191a1f5354973d
7
- data.tar.gz: cd1ea707e1b61aa29bb452d3b2eaa7a245721b28d17448061cef63beff93c794f3a05d0c104afa79a9cb7026f0b20376f422b76747170d35fe72a59ed64e40e6
6
+ metadata.gz: 103d2126c02d1aeb5ffd4982f261407af16652fd181f6e0fc63bf12702e5aa1ea3c7f863a3c39f822ba3b8e8cf704782d1beb7c4e2e28cba5f4fc2931151cf0e
7
+ data.tar.gz: 6f25c0decaf77a0314b42d0fbf6c61edfc7f2fe9b4bbeef004e34a7127882093b660108cd7728a108f26b1b3dcf2664beac4e5e6d0d0d3e68565f78fdd273d4e
data/CHANGELOG.rdoc CHANGED
@@ -1,15 +1,10 @@
1
- == Version 2.5.5 - 2017-06-09 Jeremy Daer <jeremydaer@gmail.com>
1
+ == HEAD
2
2
 
3
- Security:
4
- * #1097 – SMTP security: prevent command injection via To/From addresses. (jeremy)
5
-
6
- Bugs:
7
- * #633 – Cope with message parts that have an empty Content-Type (ThomasKoppensteiner, zeepeeare)
8
- * #689 - Fix Exim delivery method broken by #477 in 2.5.4. (jethrogb)
9
-
10
- == Version 2.5.4 - Tue May 14 14:45:00 +1100 2013 Mikel Lindsaar <mikel@lindsaar.net>
3
+ == Version 2.6.0 - Mon Jun 2 22:49 +1100 2014 Mikel Lindsaar <mikel@reinteractive.net>
11
4
 
12
5
  Features:
6
+ * Allow interceptors and observers to be unregistered (zuhao)
7
+ * Added feature to find the mail in uid (taketin)
13
8
  * Save settings passed to TestMailer#new (svanderbleek)
14
9
  * Allow the setting of envelope from directly (jeremy)
15
10
  * Accept other IETF/IANA-registered Content-Types and Content-Transfer-Encodings (jeremy)
@@ -25,9 +20,13 @@ Features:
25
20
  * Close pull request 389 - Don't add superfluous message headers to MIME parts (djmaze, jeremy)
26
21
 
27
22
  Performance:
23
+ * Migrate to RAGEL based parser, awesome work by (bpot)
24
+ * Performance improvements for people parsing email headers (ConradIrwin)
28
25
  * Close pull request 488 - Speed up field construction & comparison (bpot)
29
26
 
30
27
  Bugs:
28
+ * Fix for when content looks like field name (kjg)
29
+ * Don't change original when you change a copy (TylerRick)
31
30
  * Don't include separating semicolon in paramter value when sanitizing (bpot)
32
31
  * Fix fencepost encoding problem with binhex strings and only one token (drasch)
33
32
  * Fix sendmail delivery to addresses with a leading hyphen (lifo, jeremy)
data/CONTRIBUTING.md CHANGED
@@ -43,3 +43,16 @@ Syntax:
43
43
  * Follow the conventions you see used in the source already.
44
44
 
45
45
  And in case we didn't emphasize it enough: we love specs!
46
+
47
+ ### Testing against mime-types versions:
48
+
49
+ Use [appraisal](https://github.com/thoughtbot/appraisal) to run against all supported versions of mime-types.
50
+
51
+ 1. Run `(bundle check || bundle) && appraisal` so that all the 'appraised' gemfiles are bundled.
52
+ 2. Run either `appraisal rake` or `rake appraisal` to run all the tests.
53
+
54
+ To run only one 'appraised' gemfile, run. e.g. `BUNDLE_GEMFILE=gemfiles/mime_types_edge.gemfile (bundle check || bundle) && rake`
55
+
56
+ To change the appraisals, modify the `Appraisals` file, run `appraisal`, commit the generated gemfiles, and modify the .travis.yml matrix.
57
+
58
+ To run on all rubies / gemfiles, just like TravisCI, see [WWTD](https://github.com/grosser/wwtd).
data/Dependencies.txt CHANGED
@@ -1,3 +1,2 @@
1
- treetop: we need to include this in the gem spec
2
1
  tlsmail: if ruby < 1.8.6... we could make it optional, or embed it in Mail
3
2
  mime/types: I think we embed a simplified version, or help maintain it, it is old (2006)
data/Gemfile CHANGED
@@ -1,32 +1,15 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- if RUBY_VERSION < '1.9.3'
6
- gem 'activesupport', '< 4'
7
- elsif RUBY_VERSION < '2.2.2'
8
- gem 'activesupport', '< 5'
9
- end
10
- gem 'i18n', '< 0.7.0' if RUBY_VERSION < '1.9.3'
11
- gem "tlsmail" if RUBY_VERSION <= '1.8.6'
12
- gem "mime-types", "~> 1.16"
13
- gem "treetop", "~> 1.4.10"
5
+ gem "tlsmail", "~> 0.0.1" if RUBY_VERSION <= "1.8.6"
6
+ gem "jruby-openssl", :platforms => :jruby
14
7
 
15
- gem 'jruby-openssl', :platform => :jruby
8
+ group :development, :test do
9
+ gem "appraisal", "~> 1.0"
10
+ end
16
11
 
17
12
  # For gems not required to run tests
18
13
  group :local_development, :test do
19
- gem 'rake', '> 0.8.7', '< 11.0.1'
20
- gem 'rdoc', '< 4.3' if RUBY_VERSION < '1.9.3'
21
- gem "rspec", "~> 2.8.0"
22
- case
23
- when defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
24
- # Skip it
25
- when RUBY_PLATFORM == 'java'
26
- # Skip it
27
- when RUBY_VERSION < '1.9'
28
- gem "ruby-debug"
29
- else
30
- # Skip it
31
- end
14
+ gem "ruby-debug", :platforms => :mri_18
32
15
  end
data/README.md CHANGED
@@ -42,15 +42,25 @@ me a nice email :)
42
42
  Compatibility
43
43
  -------------
44
44
 
45
- Mail supports Ruby 1.8.7+, including JRuby and Rubinius.
45
+ Every Mail commit is tested by Travis on the [following platforms](https://github.com/mikel/mail/blob/master/.travis.yml)
46
46
 
47
- Every Mail commit is tested by Travis on [all supported Ruby versions](https://github.com/mikel/mail/blob/master/.travis.yml).
47
+ * ruby-1.8.7-p374 [ i686 ]
48
+ * ruby-1.9.2-p320 [ x86_64 ]
49
+ * ruby-1.9.3-p327 [ x86_64 ]
50
+ * ruby-2.0.0-p451 [ x86_64 ]
51
+ * ruby-2.1.2 [ x86_64 ]
52
+ * ruby-head [ x86_64 ]
53
+ * jruby [ x86_64 ]
54
+ * jruby-head [ x86_64 ]
55
+ * rbx-2 [ x86_64 ]
56
+
57
+ Testing a specific mime type (needed for 1.8.7 for example) can be done manually with:
58
+
59
+ $ BUNDLE_GEMFILE=gemfiles/mime_types_1.16.gemfile bundle check
60
+ $ BUNDLE_GEMFILE=gemfiles/mime_types_1.16.gemfile bundle
61
+ $ BUNDLE_GEMFILE=gemfiles/mime_types_1.16.gemfile rake
48
62
 
49
- Testing a specific version of mime-types (needed for Ruby 1.8.7, for example) can be done manually with:
50
63
 
51
- ```sh
52
- BUNDLE_GEMFILE=gemfiles/mime_types_1.16.gemfile bundle && rake
53
- ```
54
64
 
55
65
  Discussion
56
66
  ----------
@@ -185,6 +195,8 @@ mail['from'] = 'mikel@test.lindsaar.net'
185
195
  mail[:to] = 'you@test.lindsaar.net'
186
196
  mail.subject = 'This is a test email'
187
197
 
198
+ mail.header['X-Custom-Header'] = 'custom value'
199
+
188
200
  mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
189
201
  ```
190
202
 
@@ -227,10 +239,10 @@ easy as:
227
239
 
228
240
  ```ruby
229
241
  Mail.deliver do
230
- from 'me@test.lindsaar.net'
231
- to 'you@test.lindsaar.net'
232
- subject 'Here is the image you wanted'
233
- body File.read('body.txt')
242
+ from 'me@test.lindsaar.net'
243
+ to 'you@test.lindsaar.net'
244
+ subject 'Here is the image you wanted'
245
+ body File.read('body.txt')
234
246
  add_file '/full/path/to/somefile.png'
235
247
  end
236
248
  ```
@@ -265,6 +277,15 @@ mail.delivery_method :sendmail
265
277
  mail.deliver
266
278
  ```
267
279
 
280
+ Sending via smtp (for example to [mailcatcher](https://github.com/sj26/mailcatcher))
281
+ ```ruby
282
+
283
+ Mail.defaults do
284
+ delivery_method :smtp, address: "localhost", port: 1025
285
+ end
286
+ ```
287
+
288
+
268
289
  Exim requires its own delivery manager, and can be used like so:
269
290
 
270
291
  ```ruby
@@ -318,7 +339,7 @@ emails.length #=> LOTS!
318
339
  ```ruby
319
340
  mail = Mail.read('/path/to/message.eml')
320
341
 
321
- mail.envelope.from #=> 'mikel@test.lindsaar.net'
342
+ mail.envelope_from #=> 'mikel@test.lindsaar.net'
322
343
  mail.from.addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
323
344
  mail.sender.address #=> 'mikel@test.lindsaar.net'
324
345
  mail.to #=> 'bob@test.lindsaar.net'
@@ -349,7 +370,7 @@ mail.parts[1].content_type_parameters #=> {'name' => 'my.pdf'}
349
370
  Mail generates a tree of parts. Each message has many or no parts. Each part
350
371
  is another message which can have many or no parts.
351
372
 
352
- A message will only have parts if it is a multipart/mixed or related/mixed
373
+ A message will only have parts if it is a multipart/mixed or multipart/related
353
374
  content type and has a boundary defined.
354
375
 
355
376
  ### Testing and extracting attachments
@@ -362,7 +383,7 @@ mail.attachments.each do | attachment |
362
383
  filename = attachment.filename
363
384
  begin
364
385
  File.open(images_dir + filename, "w+b", 0644) {|f| f.write attachment.body.decoded}
365
- rescue Exception => e
386
+ rescue => e
366
387
  puts "Unable to save data for #{filename} because #{e.message}"
367
388
  end
368
389
  end
@@ -545,7 +566,7 @@ Using Mail with Testing or Spec'ing Libraries
545
566
  If mail is part of your system, you'll need a way to test it without actually
546
567
  sending emails, the TestMailer can do this for you.
547
568
 
548
- ```
569
+ ```ruby
549
570
  require 'mail'
550
571
  => true
551
572
  Mail.defaults do
@@ -571,7 +592,7 @@ Mail::TestMailer.deliveries.clear
571
592
 
572
593
  There is also a set of RSpec matchers stolen fr^H^H^H^H^H^H^H^H inspired by Shoulda's ActionMailer matchers (you'll want to set <code>delivery_method</code> as above too):
573
594
 
574
- ```
595
+ ```ruby
575
596
  Mail.defaults do
576
597
  delivery_method :test # in practice you'd do this in spec_helper.rb
577
598
  end
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
- ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', __FILE__)
1
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
3
+ end
2
4
  require 'rubygems'
3
5
  require 'bundler/setup'
4
6
 
@@ -17,5 +19,11 @@ RSpec::Core::RakeTask.new(:spec) do |t|
17
19
  t.rspec_opts = %w(--backtrace --color)
18
20
  end
19
21
 
22
+ begin
23
+ require "appraisal"
24
+ rescue LoadError
25
+ warn "Appraisal is only available in test/development"
26
+ end
27
+
20
28
  # load custom rake tasks
21
- Dir["#{File.dirname(__FILE__)}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
29
+ Dir["#{File.dirname(__FILE__)}/tasks/**/*.rake"].sort.each { |ext| load ext }
data/VERSION ADDED
@@ -0,0 +1,4 @@
1
+ major:2
2
+ minor:6
3
+ patch:0
4
+ build:
data/lib/mail.rb CHANGED
@@ -76,7 +76,7 @@ module Mail # :doc:
76
76
 
77
77
  require 'mail/envelope'
78
78
 
79
- require 'load_parsers'
79
+ require 'mail/parsers'
80
80
 
81
81
  # Autoload header field elements and transfer encodings.
82
82
  require 'mail/elements'
data/lib/mail/body.rb CHANGED
@@ -127,9 +127,9 @@ module Mail
127
127
  def sort_parts!
128
128
  @parts.each do |p|
129
129
  p.body.set_sort_order(@part_sort_order)
130
- @parts.sort!(@part_sort_order)
131
130
  p.body.sort_parts!
132
131
  end
132
+ @parts.sort!(@part_sort_order)
133
133
  end
134
134
 
135
135
  # Returns the raw source that the body was initialized with, without
@@ -257,7 +257,7 @@ module Mail
257
257
 
258
258
  def split!(boundary)
259
259
  self.boundary = boundary
260
- parts = raw_source.split(/(?:\A|\r\n)--#{Regexp.escape(boundary)}(?=(?:--)?\s*$)/)
260
+ parts = raw_source.split(/(?:\A|\r\n)--#{Regexp.escape(boundary || "")}(?=(?:--)?\s*$)/)
261
261
  # Make the preamble equal to the preamble (if any)
262
262
  self.preamble = parts[0].to_s.strip
263
263
  # Make the epilogue equal to the epilogue (if any)
@@ -1,57 +1,20 @@
1
1
  module Mail
2
- module CheckDeliveryParams #:nodoc:
3
- class << self
4
- def check(mail)
5
- [ check_from(mail.smtp_envelope_from),
6
- check_to(mail.smtp_envelope_to),
7
- check_message(mail) ]
2
+ module CheckDeliveryParams
3
+ def check_delivery_params(mail)
4
+ if mail.smtp_envelope_from.blank?
5
+ raise ArgumentError.new('An SMTP From address is required to send a message. Set the message smtp_envelope_from, return_path, sender, or from address.')
8
6
  end
9
7
 
10
- def check_from(addr)
11
- if addr.blank?
12
- raise ArgumentError, "SMTP From address may not be blank: #{addr.inspect}"
13
- end
14
-
15
- check_addr 'From', addr
16
- end
17
-
18
- def check_to(addrs)
19
- if addrs.blank?
20
- raise ArgumentError, "SMTP To address may not be blank: #{addrs.inspect}"
21
- end
22
-
23
- Array(addrs).map do |addr|
24
- check_addr 'To', addr
25
- end
8
+ if mail.smtp_envelope_to.blank?
9
+ raise ArgumentError.new('An SMTP To address is required to send a message. Set the message smtp_envelope_to, to, cc, or bcc address.')
26
10
  end
27
11
 
28
- def check_addr(addr_name, addr)
29
- validate_smtp_addr addr do |error_message|
30
- raise ArgumentError, "SMTP #{addr_name} address #{error_message}: #{addr.inspect}"
31
- end
12
+ message = mail.encoded if mail.respond_to?(:encoded)
13
+ if message.blank?
14
+ raise ArgumentError.new('An encoded message is required to send an email')
32
15
  end
33
16
 
34
- def validate_smtp_addr(addr)
35
- if addr.bytesize > 2048
36
- yield 'may not exceed 2kB'
37
- end
38
-
39
- if /[\r\n]/ =~ addr
40
- yield 'may not contain CR or LF line breaks'
41
- end
42
-
43
- addr
44
- end
45
-
46
- def check_message(message)
47
- message = message.encoded if message.respond_to?(:encoded)
48
-
49
- if message.blank?
50
- raise ArgumentError, 'An encoded message is required to send an email'
51
- end
52
-
53
- message
54
- end
17
+ [mail.smtp_envelope_from, mail.smtp_envelope_to, message]
55
18
  end
56
19
  end
57
20
  end
@@ -1,11 +1,21 @@
1
1
  # encoding: utf-8
2
2
  class String #:nodoc:
3
+
4
+ if RUBY_VERSION >= '1.9'
5
+ # This 1.9 only regex can save a reasonable amount of time (~20%)
6
+ # by not matching "\r\n" so the string is returned unchanged in
7
+ # the common case.
8
+ CRLF_REGEX = Regexp.new("(?<!\r)\n|\r(?!\n)")
9
+ else
10
+ CRLF_REGEX = /\n|\r\n|\r/
11
+ end
12
+
3
13
  def to_crlf
4
- to_str.gsub(/\n|\r\n|\r/) { "\r\n" }
14
+ to_str.gsub(CRLF_REGEX, "\r\n")
5
15
  end
6
16
 
7
17
  def to_lf
8
- to_str.gsub(/\n|\r\n|\r/) { "\n" }
18
+ to_str.gsub(/\r\n|\r/, "\n")
9
19
  end
10
20
 
11
21
  unless String.instance_methods(false).map {|m| m.to_sym}.include?(:blank?)
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  module Mail
3
3
  class Address
4
-
4
+
5
5
  include Mail::Utilities
6
6
 
7
7
  # Mail::Address handles all email addresses in Mail. It takes an email address string
@@ -22,21 +22,19 @@ module Mail
22
22
  # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
23
23
  def initialize(value = nil)
24
24
  @output_type = :decode
25
- @tree = nil
26
- @raw_text = value
27
- case
28
- when value.nil?
25
+ if value.nil?
29
26
  @parsed = false
27
+ @data = nil
30
28
  return
31
29
  else
32
30
  parse(value)
33
31
  end
34
32
  end
35
33
 
36
- # Returns the raw imput of the passed in string, this is before it is passed
34
+ # Returns the raw input of the passed in string, this is before it is passed
37
35
  # by the parser.
38
36
  def raw
39
- @raw_text
37
+ @data.raw
40
38
  end
41
39
 
42
40
  # Returns a correctly formatted address for the email going out. If given
@@ -48,15 +46,14 @@ module Mail
48
46
  # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
49
47
  def format
50
48
  parse unless @parsed
51
- case
52
- when tree.nil?
49
+ if @data.nil?
53
50
  ''
54
- when display_name
51
+ elsif display_name
55
52
  [quote_phrase(display_name), "<#{address}>", format_comments].compact.join(" ")
56
- when address
53
+ elsif address
57
54
  [address, format_comments].compact.join(" ")
58
55
  else
59
- tree.text_value
56
+ raw
60
57
  end
61
58
  end
62
59
 
@@ -106,7 +103,7 @@ module Mail
106
103
  # a.local #=> 'mikel'
107
104
  def local
108
105
  parse unless @parsed
109
- "#{obs_domain_list}#{get_local.strip}" if get_local
106
+ "#{@data.obs_domain_list}#{get_local.strip}" if get_local
110
107
  end
111
108
 
112
109
  # Returns the domain part (the right hand side of the @ sign in the email address) of
@@ -174,29 +171,24 @@ module Mail
174
171
 
175
172
  def parse(value = nil)
176
173
  @parsed = true
177
- case
178
- when value.nil?
174
+
175
+ case value
176
+ when NilClass
177
+ @data = nil
179
178
  nil
180
- when value.class == String
181
- self.tree = Mail::AddressList.new(value).address_nodes.first
182
- else
183
- self.tree = value
179
+ when Mail::Parsers::AddressStruct
180
+ @data = value
181
+ when String
182
+ @raw_text = value
183
+ if value.blank?
184
+ @data = nil
185
+ else
186
+ address_list = Mail::Parsers::AddressListsParser.new.parse(value)
187
+ @data = address_list.addresses.first
188
+ end
184
189
  end
185
190
  end
186
191
 
187
-
188
- def get_domain
189
- if tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:domain)
190
- @domain_text ||= tree.angle_addr.addr_spec.domain.text_value.strip
191
- elsif tree.respond_to?(:domain)
192
- @domain_text ||= tree.domain.text_value.strip
193
- elsif tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:domain)
194
- tree.addr_spec.domain.text_value.strip
195
- else
196
- nil
197
- end
198
- end
199
-
200
192
  def strip_all_comments(string)
201
193
  unless comments.blank?
202
194
  comments.each do |comment|
@@ -209,7 +201,7 @@ module Mail
209
201
  def strip_domain_comments(value)
210
202
  unless comments.blank?
211
203
  comments.each do |comment|
212
- if get_domain && get_domain.include?("(#{comment})")
204
+ if @data.domain && @data.domain.include?("(#{comment})")
213
205
  value = value.gsub("(#{comment})", '')
214
206
  end
215
207
  end
@@ -217,20 +209,11 @@ module Mail
217
209
  value.to_s.strip
218
210
  end
219
211
 
220
- def get_comments
221
- if tree.respond_to?(:comments)
222
- @comments = tree.comments.map { |c| unparen(c.text_value.to_str) }
223
- else
224
- @comments = []
225
- end
226
- end
227
-
228
212
  def get_display_name
229
- if tree.respond_to?(:display_name)
230
- name = unquote(tree.display_name.text_value.strip)
231
- str = strip_all_comments(name.to_s)
232
- elsif comments
233
- if domain
213
+ if @data.display_name
214
+ str = strip_all_comments(@data.display_name.to_s)
215
+ elsif @data.comments
216
+ if @data.domain
234
217
  str = strip_domain_comments(format_comments)
235
218
  else
236
219
  str = nil
@@ -263,15 +246,6 @@ module Mail
263
246
  end
264
247
  end
265
248
 
266
- # Provides access to the Treetop parse tree for this address
267
- def tree
268
- @tree
269
- end
270
-
271
- def tree=(value)
272
- @tree = value
273
- end
274
-
275
249
  def format_comments
276
250
  if comments
277
251
  comment_text = comments.map {|c| escape_paren(c) }.join(' ').squeeze(" ")
@@ -280,35 +254,17 @@ module Mail
280
254
  nil
281
255
  end
282
256
  end
283
-
284
- def obs_domain_list
285
- if tree.respond_to?(:angle_addr)
286
- obs = tree.angle_addr.elements.select { |e| e.respond_to?(:obs_domain_list) }
287
- !obs.empty? ? obs.first.text_value : nil
288
- else
289
- nil
290
- end
291
- end
292
-
257
+
293
258
  def get_local
294
- case
295
- when tree.respond_to?(:local_dot_atom_text)
296
- tree.local_dot_atom_text.text_value
297
- when tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:local_part)
298
- tree.angle_addr.addr_spec.local_part.text_value
299
- when tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:local_part)
300
- tree.addr_spec.local_part.text_value
301
- when tree.respond_to?(:angle_addr) && tree.angle_addr.respond_to?(:addr_spec) && tree.angle_addr.addr_spec.respond_to?(:local_dot_atom_text)
302
- # Ignore local dot atom text when in angle brackets
303
- nil
304
- when tree.respond_to?(:addr_spec) && tree.addr_spec.respond_to?(:local_dot_atom_text)
305
- # Ignore local dot atom text when in angle brackets
306
- nil
307
- else
308
- tree && tree.respond_to?(:local_part) ? tree.local_part.text_value : nil
309
- end
259
+ @data && @data.local
260
+ end
261
+
262
+ def get_domain
263
+ @data && @data.domain
310
264
  end
311
265
 
312
-
266
+ def get_comments
267
+ @data && @data.comments
268
+ end
313
269
  end
314
270
  end