mail 2.5.5 → 2.6.0

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 (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