mail 2.6.1 → 2.7.1

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 (179) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +92 -80
  4. data/lib/mail/attachments_list.rb +11 -5
  5. data/lib/mail/body.rb +81 -44
  6. data/lib/mail/check_delivery_params.rb +50 -10
  7. data/lib/mail/configuration.rb +3 -0
  8. data/lib/mail/{patterns.rb → constants.rb} +26 -6
  9. data/lib/mail/core_extensions/smtp.rb +20 -16
  10. data/lib/mail/core_extensions/string.rb +1 -27
  11. data/lib/mail/elements/address.rb +81 -93
  12. data/lib/mail/elements/address_list.rb +12 -29
  13. data/lib/mail/elements/content_disposition_element.rb +9 -15
  14. data/lib/mail/elements/content_location_element.rb +8 -12
  15. data/lib/mail/elements/content_transfer_encoding_element.rb +6 -10
  16. data/lib/mail/elements/content_type_element.rb +9 -19
  17. data/lib/mail/elements/date_time_element.rb +7 -14
  18. data/lib/mail/elements/envelope_from_element.rb +15 -21
  19. data/lib/mail/elements/message_ids_element.rb +12 -14
  20. data/lib/mail/elements/mime_version_element.rb +7 -14
  21. data/lib/mail/elements/phrase_list.rb +7 -9
  22. data/lib/mail/elements/received_element.rb +10 -15
  23. data/lib/mail/elements.rb +1 -0
  24. data/lib/mail/encodings/7bit.rb +6 -15
  25. data/lib/mail/encodings/8bit.rb +5 -18
  26. data/lib/mail/encodings/base64.rb +15 -10
  27. data/lib/mail/encodings/binary.rb +4 -22
  28. data/lib/mail/encodings/identity.rb +24 -0
  29. data/lib/mail/encodings/quoted_printable.rb +13 -7
  30. data/lib/mail/encodings/transfer_encoding.rb +47 -28
  31. data/lib/mail/encodings/unix_to_unix.rb +20 -0
  32. data/lib/mail/encodings.rb +121 -82
  33. data/lib/mail/envelope.rb +2 -1
  34. data/lib/mail/field.rb +114 -62
  35. data/lib/mail/field_list.rb +2 -1
  36. data/lib/mail/fields/bcc_field.rb +17 -5
  37. data/lib/mail/fields/cc_field.rb +2 -2
  38. data/lib/mail/fields/comments_field.rb +2 -1
  39. data/lib/mail/fields/common/address_container.rb +3 -2
  40. data/lib/mail/fields/common/common_address.rb +40 -14
  41. data/lib/mail/fields/common/common_date.rb +2 -1
  42. data/lib/mail/fields/common/common_field.rb +6 -11
  43. data/lib/mail/fields/common/common_message_id.rb +3 -2
  44. data/lib/mail/fields/common/parameter_hash.rb +5 -4
  45. data/lib/mail/fields/content_description_field.rb +2 -1
  46. data/lib/mail/fields/content_disposition_field.rb +14 -13
  47. data/lib/mail/fields/content_id_field.rb +5 -4
  48. data/lib/mail/fields/content_location_field.rb +3 -2
  49. data/lib/mail/fields/content_transfer_encoding_field.rb +3 -2
  50. data/lib/mail/fields/content_type_field.rb +7 -11
  51. data/lib/mail/fields/date_field.rb +4 -4
  52. data/lib/mail/fields/from_field.rb +2 -2
  53. data/lib/mail/fields/in_reply_to_field.rb +2 -1
  54. data/lib/mail/fields/keywords_field.rb +3 -3
  55. data/lib/mail/fields/message_id_field.rb +3 -2
  56. data/lib/mail/fields/mime_version_field.rb +4 -3
  57. data/lib/mail/fields/optional_field.rb +5 -1
  58. data/lib/mail/fields/received_field.rb +5 -4
  59. data/lib/mail/fields/references_field.rb +2 -1
  60. data/lib/mail/fields/reply_to_field.rb +2 -2
  61. data/lib/mail/fields/resent_bcc_field.rb +2 -2
  62. data/lib/mail/fields/resent_cc_field.rb +2 -2
  63. data/lib/mail/fields/resent_date_field.rb +2 -2
  64. data/lib/mail/fields/resent_from_field.rb +2 -2
  65. data/lib/mail/fields/resent_message_id_field.rb +2 -1
  66. data/lib/mail/fields/resent_sender_field.rb +2 -2
  67. data/lib/mail/fields/resent_to_field.rb +2 -2
  68. data/lib/mail/fields/return_path_field.rb +2 -2
  69. data/lib/mail/fields/sender_field.rb +2 -2
  70. data/lib/mail/fields/structured_field.rb +1 -0
  71. data/lib/mail/fields/subject_field.rb +2 -1
  72. data/lib/mail/fields/to_field.rb +2 -2
  73. data/lib/mail/fields/unstructured_field.rb +28 -10
  74. data/lib/mail/fields.rb +1 -0
  75. data/lib/mail/header.rb +18 -14
  76. data/lib/mail/indifferent_hash.rb +1 -0
  77. data/lib/mail/mail.rb +6 -11
  78. data/lib/mail/matchers/attachment_matchers.rb +29 -0
  79. data/lib/mail/matchers/has_sent_mail.rb +53 -9
  80. data/lib/mail/message.rb +99 -89
  81. data/lib/mail/multibyte/chars.rb +32 -30
  82. data/lib/mail/multibyte/unicode.rb +31 -26
  83. data/lib/mail/multibyte/utils.rb +1 -0
  84. data/lib/mail/multibyte.rb +65 -15
  85. data/lib/mail/network/delivery_methods/exim.rb +7 -10
  86. data/lib/mail/network/delivery_methods/file_delivery.rb +5 -8
  87. data/lib/mail/network/delivery_methods/logger_delivery.rb +37 -0
  88. data/lib/mail/network/delivery_methods/sendmail.rb +17 -11
  89. data/lib/mail/network/delivery_methods/smtp.rb +60 -53
  90. data/lib/mail/network/delivery_methods/smtp_connection.rb +11 -6
  91. data/lib/mail/network/delivery_methods/test_mailer.rb +6 -8
  92. data/lib/mail/network/retriever_methods/base.rb +1 -0
  93. data/lib/mail/network/retriever_methods/imap.rb +19 -5
  94. data/lib/mail/network/retriever_methods/pop3.rb +4 -1
  95. data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
  96. data/lib/mail/network.rb +2 -0
  97. data/lib/mail/parser_tools.rb +15 -0
  98. data/lib/mail/parsers/address_lists_parser.rb +33208 -104
  99. data/lib/mail/parsers/address_lists_parser.rl +172 -0
  100. data/lib/mail/parsers/content_disposition_parser.rb +877 -49
  101. data/lib/mail/parsers/content_disposition_parser.rl +82 -0
  102. data/lib/mail/parsers/content_location_parser.rb +804 -23
  103. data/lib/mail/parsers/content_location_parser.rl +71 -0
  104. data/lib/mail/parsers/content_transfer_encoding_parser.rb +502 -19
  105. data/lib/mail/parsers/content_transfer_encoding_parser.rl +64 -0
  106. data/lib/mail/parsers/content_type_parser.rb +1024 -46
  107. data/lib/mail/parsers/content_type_parser.rl +83 -0
  108. data/lib/mail/parsers/date_time_parser.rb +872 -23
  109. data/lib/mail/parsers/date_time_parser.rl +62 -0
  110. data/lib/mail/parsers/envelope_from_parser.rb +3570 -34
  111. data/lib/mail/parsers/envelope_from_parser.rl +82 -0
  112. data/lib/mail/parsers/message_ids_parser.rb +2840 -25
  113. data/lib/mail/parsers/message_ids_parser.rl +82 -0
  114. data/lib/mail/parsers/mime_version_parser.rb +492 -26
  115. data/lib/mail/parsers/mime_version_parser.rl +61 -0
  116. data/lib/mail/parsers/phrase_lists_parser.rb +862 -17
  117. data/lib/mail/parsers/phrase_lists_parser.rl +83 -0
  118. data/lib/mail/parsers/received_parser.rb +8765 -36
  119. data/lib/mail/parsers/received_parser.rl +84 -0
  120. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  121. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  122. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  123. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  124. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  125. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  126. data/lib/mail/parsers/rfc5322.rl +59 -0
  127. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  128. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
  129. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  130. data/lib/mail/parsers.rb +17 -24
  131. data/lib/mail/part.rb +8 -5
  132. data/lib/mail/parts_list.rb +31 -14
  133. data/lib/mail/utilities.rb +112 -13
  134. data/lib/mail/values/unicode_tables.dat +0 -0
  135. data/lib/mail/version.rb +8 -15
  136. data/lib/mail/version_specific/ruby_1_8.rb +52 -8
  137. data/lib/mail/version_specific/ruby_1_9.rb +143 -24
  138. data/lib/mail.rb +8 -14
  139. metadata +71 -81
  140. data/CHANGELOG.rdoc +0 -752
  141. data/CONTRIBUTING.md +0 -60
  142. data/Dependencies.txt +0 -2
  143. data/Gemfile +0 -15
  144. data/Rakefile +0 -29
  145. data/TODO.rdoc +0 -9
  146. data/VERSION +0 -4
  147. data/lib/mail/core_extensions/nil.rb +0 -19
  148. data/lib/mail/core_extensions/object.rb +0 -13
  149. data/lib/mail/core_extensions/string/access.rb +0 -145
  150. data/lib/mail/core_extensions/string/multibyte.rb +0 -78
  151. data/lib/mail/multibyte/exceptions.rb +0 -8
  152. data/lib/mail/parsers/ragel/common.rl +0 -184
  153. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  154. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  155. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  156. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  157. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  158. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  159. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  160. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  161. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  162. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  163. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  164. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  165. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  166. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2129
  167. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  168. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  169. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  170. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  171. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  172. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  173. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  174. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  175. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  176. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  177. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  178. data/lib/mail/parsers/ragel/ruby.rb +0 -39
  179. data/lib/mail/parsers/ragel.rb +0 -17
data/CONTRIBUTING.md DELETED
@@ -1,60 +0,0 @@
1
- Contributing to Mail
2
- ====================
3
-
4
- Hi there, I welcome pull requests! Here are some thoughts on how to get your
5
- pull request merged quickly:
6
-
7
- 1. Check the Reference RFCs, they are in the References directory, so no excuses.
8
- 2. Check for a ticket on GitHub, maybe someone else has the problem too
9
- 3. Make a fork of my GitHub repository
10
- 4. Run the specs. We only take pull requests with passing tests, and it's great
11
- to know that you have a clean slate: `bundle && bundle exec rake`
12
- 5. Add a spec for your change. Only refactoring and documentation changes
13
- require no new specs. If you are adding functionality or fixing a bug, we need
14
- a spec!
15
- 6. Test the spec _at_ _least_ against MRI-1.9.3 and MRI-1.8.7
16
- 7. Update the README if needed to reflect your change / addition
17
- 8. Update the CHANGELOG and give yourself credit
18
- 9. With all specs passing push your changes back to your fork
19
- 10. Send me a pull request.
20
- - If it needs any changes, please push or force push to the same branch you made the pull request from. GitHub will just update the pull request with your changes.
21
-
22
- Note, specs that break MRI 1.8.7 or 1.9.3 will not be accepted.
23
-
24
- At this point you're waiting on us. We like to at least comment on, if not
25
- accept, pull requests within three business days (and, typically, one business
26
- day). We may suggest some changes or improvements or alternatives.
27
-
28
- Some things that will increase the chance that your pull request is accepted,
29
- taken straight from the Ruby on Rails guide:
30
-
31
- * Tell me you have tested it against more than one version of Ruby, RVM is great for
32
- this. I test against 7 rubies before I push into master.
33
- * Use good, idiomatic, structured and modular code
34
- * Include tests that fail without your code, and pass with it
35
- * Update the documentation, the surrounding one, examples elsewhere, guides,
36
- whatever is affected by your contribution
37
-
38
- Syntax:
39
-
40
- * Two spaces, no tabs.
41
- * No trailing whitespace. Blank lines should not have any space.
42
- * Prefer &&/|| over and/or.
43
- * MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
44
- * a = b and not a=b.
45
- * Follow the conventions you see used in the source already.
46
-
47
- And in case we didn't emphasize it enough: we love specs!
48
-
49
- ### Testing against mime-types versions:
50
-
51
- Use [appraisal](https://github.com/thoughtbot/appraisal) to run against all supported versions of mime-types.
52
-
53
- 1. Run `(bundle check || bundle) && appraisal` so that all the 'appraised' gemfiles are bundled.
54
- 2. Run either `appraisal rake` or `rake appraisal` to run all the tests.
55
-
56
- To run only one 'appraised' gemfile, run. e.g. `BUNDLE_GEMFILE=gemfiles/mime_types_edge.gemfile (bundle check || bundle) && rake`
57
-
58
- To change the appraisals, modify the `Appraisals` file, run `appraisal`, commit the generated gemfiles, and modify the .travis.yml matrix.
59
-
60
- To run on all rubies / gemfiles, just like TravisCI, see [WWTD](https://github.com/grosser/wwtd).
data/Dependencies.txt DELETED
@@ -1,2 +0,0 @@
1
- tlsmail: if ruby < 1.8.6... we could make it optional, or embed it in Mail
2
- mime/types: I think we embed a simplified version, or help maintain it, it is old (2006)
data/Gemfile DELETED
@@ -1,15 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
4
-
5
- gem "tlsmail", "~> 0.0.1" if RUBY_VERSION <= "1.8.6"
6
- gem "jruby-openssl", :platforms => :jruby
7
-
8
- group :development, :test do
9
- gem "appraisal", "~> 1.0"
10
- end
11
-
12
- # For gems not required to run tests
13
- group :local_development, :test do
14
- gem "ruby-debug", :platforms => :mri_18
15
- end
data/Rakefile DELETED
@@ -1,29 +0,0 @@
1
- if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
2
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
3
- end
4
- require 'rubygems'
5
- require 'bundler/setup'
6
-
7
- require 'rake/testtask'
8
- require 'rspec/core/rake_task'
9
-
10
- desc "Build a gem file"
11
- task :build do
12
- system "gem build mail.gemspec"
13
- end
14
-
15
- task :default => :spec
16
-
17
- RSpec::Core::RakeTask.new(:spec) do |t|
18
- t.ruby_opts = '-w'
19
- t.rspec_opts = %w(--backtrace --color)
20
- end
21
-
22
- begin
23
- require "appraisal"
24
- rescue LoadError
25
- warn "Appraisal is only available in test/development"
26
- end
27
-
28
- # load custom rake tasks
29
- Dir["#{File.dirname(__FILE__)}/tasks/**/*.rake"].sort.each { |ext| load ext }
data/TODO.rdoc DELETED
@@ -1,9 +0,0 @@
1
- == Not really in any order:
2
-
3
- * Add multibyte handling to fields, if they get a multibyte string, try encoding it into
4
- UTF-8 B first, if this fails, throw an error.
5
-
6
- * Cleanup the treetop parsers......... do I _really_ need that many entrance files?
7
-
8
- * Simplify the relationship of Headers and Fields. Doing too much of the Field work
9
- in the Header class on instantiating fields. Header should just say "Field, do it!"
data/VERSION DELETED
@@ -1,4 +0,0 @@
1
- major:2
2
- minor:6
3
- patch:1
4
- build:
@@ -1,19 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # This is not loaded if ActiveSupport is already loaded
4
-
5
- class NilClass #:nodoc:
6
- unless nil.respond_to? :blank?
7
- def blank?
8
- true
9
- end
10
- end
11
-
12
- def to_crlf
13
- ''
14
- end
15
-
16
- def to_lf
17
- ''
18
- end
19
- end
@@ -1,13 +0,0 @@
1
- # encoding: utf-8
2
-
3
- unless Object.method_defined? :blank?
4
- class Object
5
- def blank?
6
- if respond_to?(:empty?)
7
- empty?
8
- else
9
- !self
10
- end
11
- end
12
- end
13
- end
@@ -1,145 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # This is not loaded if ActiveSupport is already loaded
4
-
5
- # This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
6
- # itself does not depend on ActiveSupport to avoid versioning conflicts
7
-
8
- class String
9
- unless '1.9'.respond_to?(:force_encoding)
10
- # Returns the character at the +position+ treating the string as an array (where 0 is the first character).
11
- #
12
- # Examples:
13
- # "hello".at(0) # => "h"
14
- # "hello".at(4) # => "o"
15
- # "hello".at(10) # => ERROR if < 1.9, nil in 1.9
16
- def at(position)
17
- mb_chars[position, 1].to_s
18
- end
19
-
20
- # Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character).
21
- #
22
- # Examples:
23
- # "hello".from(0) # => "hello"
24
- # "hello".from(2) # => "llo"
25
- # "hello".from(10) # => "" if < 1.9, nil in 1.9
26
- def from(position)
27
- mb_chars[position..-1].to_s
28
- end
29
-
30
- # Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character).
31
- #
32
- # Examples:
33
- # "hello".to(0) # => "h"
34
- # "hello".to(2) # => "hel"
35
- # "hello".to(10) # => "hello"
36
- def to(position)
37
- mb_chars[0..position].to_s
38
- end
39
-
40
- # Returns the first character of the string or the first +limit+ characters.
41
- #
42
- # Examples:
43
- # "hello".first # => "h"
44
- # "hello".first(2) # => "he"
45
- # "hello".first(10) # => "hello"
46
- def first(limit = 1)
47
- if limit == 0
48
- ''
49
- elsif limit >= size
50
- self
51
- else
52
- mb_chars[0...limit].to_s
53
- end
54
- end
55
-
56
- # Returns the last character of the string or the last +limit+ characters.
57
- #
58
- # Examples:
59
- # "hello".last # => "o"
60
- # "hello".last(2) # => "lo"
61
- # "hello".last(10) # => "hello"
62
- def last(limit = 1)
63
- if limit == 0
64
- ''
65
- elsif limit >= size
66
- self
67
- else
68
- mb_chars[(-limit)..-1].to_s
69
- end
70
- end
71
- else
72
- def at(position)
73
- self[position]
74
- end
75
-
76
- def from(position)
77
- self[position..-1]
78
- end
79
-
80
- def to(position)
81
- self[0..position]
82
- end
83
-
84
- def first(limit = 1)
85
- if limit == 0
86
- ''
87
- elsif limit >= size
88
- self
89
- else
90
- to(limit - 1)
91
- end
92
- end
93
-
94
- def last(limit = 1)
95
- if limit == 0
96
- ''
97
- elsif limit >= size
98
- self
99
- else
100
- from(-limit)
101
- end
102
- end
103
- end
104
-
105
- if Module.method(:const_get).arity == 1
106
- # Tries to find a constant with the name specified in the argument string:
107
- #
108
- # "Module".constantize # => Module
109
- # "Test::Unit".constantize # => Test::Unit
110
- #
111
- # The name is assumed to be the one of a top-level constant, no matter whether
112
- # it starts with "::" or not. No lexical context is taken into account:
113
- #
114
- # C = 'outside'
115
- # module M
116
- # C = 'inside'
117
- # C # => 'inside'
118
- # "C".constantize # => 'outside', same as ::C
119
- # end
120
- #
121
- # NameError is raised when the name is not in CamelCase or the constant is
122
- # unknown.
123
- def constantize
124
- names = self.split('::')
125
- names.shift if names.empty? || names.first.empty?
126
-
127
- constant = Object
128
- names.each do |name|
129
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
130
- end
131
- constant
132
- end
133
- else
134
- def constantize #:nodoc:
135
- names = self.split('::')
136
- names.shift if names.empty? || names.first.empty?
137
-
138
- constant = Object
139
- names.each do |name|
140
- constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
141
- end
142
- constant
143
- end
144
- end
145
- end
@@ -1,78 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # This is not loaded if ActiveSupport is already loaded
4
-
5
- # This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
6
- # itself does not depend on ActiveSupport to avoid versioning conflicts
7
-
8
- require 'mail/multibyte'
9
-
10
- class String
11
- if RUBY_VERSION >= "1.9"
12
- # == Multibyte proxy
13
- #
14
- # +mb_chars+ is a multibyte safe proxy for string methods.
15
- #
16
- # In Ruby 1.8 and older it creates and returns an instance of the Mail::Multibyte::Chars class which
17
- # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
18
- # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
19
- #
20
- # name = 'Claus Müller'
21
- # name.reverse # => "rell??M sualC"
22
- # name.length # => 13
23
- #
24
- # name.mb_chars.reverse.to_s # => "rellüM sualC"
25
- # name.mb_chars.length # => 12
26
- #
27
- # In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
28
- # it becomes easy to run one version of your code on multiple Ruby versions.
29
- #
30
- # == Method chaining
31
- #
32
- # All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
33
- # method chaining on the result of any of these methods.
34
- #
35
- # name.mb_chars.reverse.length # => 12
36
- #
37
- # == Interoperability and configuration
38
- #
39
- # The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
40
- # String and Char work like expected. The bang! methods change the internal string representation in the Chars
41
- # object. Interoperability problems can be resolved easily with a +to_s+ call.
42
- #
43
- # For more information about the methods defined on the Chars proxy see Mail::Multibyte::Chars. For
44
- # information about how to change the default Multibyte behaviour see Mail::Multibyte.
45
- def mb_chars
46
- if Mail::Multibyte.proxy_class.consumes?(self)
47
- Mail::Multibyte.proxy_class.new(self)
48
- else
49
- self
50
- end
51
- end
52
-
53
- def is_utf8? #:nodoc
54
- case encoding
55
- when Encoding::UTF_8
56
- valid_encoding?
57
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
58
- dup.force_encoding(Encoding::UTF_8).valid_encoding?
59
- else
60
- false
61
- end
62
- end
63
- else
64
- def mb_chars
65
- if Mail::Multibyte.proxy_class.wants?(self)
66
- Mail::Multibyte.proxy_class.new(self)
67
- else
68
- self
69
- end
70
- end
71
-
72
- # Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
73
- # them), returns false otherwise.
74
- def is_utf8?
75
- Mail::Multibyte::Chars.consumes?(self)
76
- end
77
- end
78
- end
@@ -1,8 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mail #:nodoc:
4
- module Multibyte #:nodoc:
5
- # Raised when a problem with the encoding was found.
6
- class EncodingError < StandardError; end
7
- end
8
- end
@@ -1,184 +0,0 @@
1
- %%{
2
-
3
- machine common;
4
-
5
- action comment_begin { fcall comment_tail; }
6
- action comment_exit { fret; }
7
-
8
- # RFC5322: address_lists, date_time, message_ids, phrase_lists, received
9
-
10
- obs_NO_WS_CTL = 0x01..0x08 | 0x0b | 0x0c | 0x0e..0x1f | 0x7f;
11
- LF = "\n";
12
- CR = "\r";
13
- CRLF = "\r\n";
14
- WSP = 0x09 | 0x20;
15
- obs_ctext = obs_NO_WS_CTL;
16
- VCHAR = 0x21..0x7e;
17
- obs_qp = "\\" (0x00 | obs_NO_WS_CTL | LF | CR);
18
- obs_FWS = (CRLF? WSP)+;
19
- ctext = 0x21..0x27 | 0x2a..0x5b | 0x5d..0x7e | obs_ctext;
20
- quoted_pair = ("\\" (VCHAR | WSP)) | obs_qp;
21
- FWS = (WSP* CRLF WSP+) | (CRLF WSP+) | obs_FWS;
22
- ALPHA = [a-zA-Z];
23
- DIGIT = [0-9];
24
- DQUOTE = '"';
25
- obs_qtext = obs_NO_WS_CTL;
26
- atext = ALPHA | DIGIT | "!" | "#" | "$" | "%" | "&" |
27
- "'" | "*" | "+" | "-" | "/" | "=" | "?" | "^" |
28
- "_" | "`" | "{" | "|" | "}" | "~";
29
- qtext = 0x21 | 0x23..0x5b | 0x5d..0x7e | obs_qtext;
30
- obs_dtext = obs_NO_WS_CTL | quoted_pair;
31
- qcontent = qtext | quoted_pair;
32
-
33
- # Handle recursive comments
34
- ccontent = ctext | quoted_pair | "(" @comment_begin;
35
- comment_tail := ((FWS? ccontent)* >comment_s) FWS? ")" @comment_exit;
36
- comment = "(" @comment_begin %comment_e;
37
- CFWS = ((FWS? comment)+ FWS?) | FWS;
38
-
39
- quoted_string = CFWS?
40
- (DQUOTE
41
- (((FWS? qcontent)* FWS?) >qstr_s %qstr_e)
42
- DQUOTE)
43
- CFWS?;
44
-
45
- atom = CFWS? atext+ CFWS?;
46
- word = atom | quoted_string;
47
-
48
- # phrase_lists
49
- obs_phrase = (word | "." | "@")+;
50
- phrase = (obs_phrase | word+) >phrase_s %phrase_e;
51
- phrase_lists = phrase ("," FWS* phrase)*;
52
-
53
- # address_lists
54
-
55
- # local_part:
56
- domain_text = (DQUOTE (FWS? qcontent)+ FWS? DQUOTE) | atext+;
57
- local_dot_atom_text = ("."* domain_text "."*)+;
58
- local_dot_atom = CFWS?
59
- (local_dot_atom_text >local_dot_atom_s %local_dot_atom_pre_comment_e)
60
- CFWS?;
61
- obs_local_part = word ("." word)*;
62
- local_part = (local_dot_atom >local_dot_atom_s %local_dot_atom_e |
63
- (quoted_string %local_quoted_string_e) |
64
- obs_local_part);
65
-
66
- # Treetop parser behavior was to ignore addresses missing '@' inside of angle
67
- # brackets. This construction preserves that behavior.
68
- local_part_no_capture = (local_dot_atom | quoted_string | obs_local_part);
69
-
70
- # domain:
71
- dot_atom_text = "."* domain_text ("."* domain_text)*;
72
- dtext = 0x21..0x5a | 0x5e..0x7e | obs_dtext;
73
- dot_atom = CFWS? dot_atom_text (CFWS? >(comment_after_address,1));
74
- domain_literal = CFWS? "[" (FWS? dtext)* FWS? "]" CFWS?;
75
- obs_domain = atom ("." atom)*;
76
- domain = (dot_atom | domain_literal | obs_domain) >domain_s %domain_e;
77
-
78
- # addr_spec:
79
-
80
- # The %(end_addr,N) priority resolves uncertainty when whitespace
81
- # after an addr_spec could cause it to be interpreted as a
82
- # display name: "bar@example.com ,..."
83
-
84
- addr_spec_in_angle_brackets =
85
- (local_part "@" domain) %(end_addr,1) |
86
- local_part_no_capture %(end_addr,0);
87
-
88
- addr_spec_no_angle_brackets =
89
- (local_part "@" domain) %(end_addr,1) |
90
- local_part %(end_addr,0);
91
-
92
- # angle_addr:
93
- obs_domain_list = (CFWS | ",")* "@" domain ("," CFWS? ("@" domain)?)*;
94
- obs_route = (obs_domain_list ":") >obs_domain_list_s %obs_domain_list_e;
95
- obs_angle_addr = CFWS? "<" obs_route? addr_spec_in_angle_brackets ">" CFWS?;
96
-
97
- angle_addr = CFWS? ("<" >angle_addr_s) addr_spec_in_angle_brackets ">" CFWS? |
98
- obs_angle_addr;
99
-
100
- # Address
101
- display_name = phrase;
102
- name_addr = display_name? %(end_addr,2) angle_addr;
103
- mailbox = (name_addr | addr_spec_no_angle_brackets) >address_s %address_e;
104
- obs_mbox_list = (CFWS? ",")* mailbox ("," (mailbox | CFWS)?)*;
105
- mailbox_list = (mailbox (("," | ";") mailbox)*) | obs_mbox_list;
106
- obs_group_list = (CFWS? ",")+ CFWS?;
107
- group_list = mailbox_list | CFWS | obs_group_list;
108
- group = (display_name >group_name_s %group_name_e) ":"
109
- (group_list?) ";" CFWS?;
110
- address = group | mailbox;
111
- #obs_addr_list = (CFWS? ",")* address ("," (address | CFWS)?)*;
112
- address_lists = address? %(comment_after_address,0)
113
- (FWS* ("," | ";") FWS* address?)*;
114
-
115
- # message_ids
116
- obs_id_left = local_part;
117
- id_left = dot_atom_text | obs_id_left;
118
- # id_right modifications to support multiple '@' in msg_id.
119
- msg_id_atext = ALPHA | DIGIT | "!" | "#" | "$" | "%" | "&" | "'" | "*" |
120
- "+" | "-" | "/" | "=" | "?" | "^" | "_" | "`" | "{" | "|" |
121
- "}" | "~" | "@";
122
- msg_id_dot_atom_text = (msg_id_atext+ "."?)+;
123
- obs_id_right = domain;
124
- no_fold_literal = "[" (dtext)* "]";
125
- id_right = msg_id_dot_atom_text | no_fold_literal | obs_id_right;
126
- msg_id = (CFWS)?
127
- (("<" id_left "@" id_right ">") >msg_id_s %msg_id_e)
128
- (CFWS)?;
129
- message_ids = msg_id (CFWS? msg_id)*;
130
-
131
- include date_time "date_time.rl";
132
- date_time = (day_of_week ",")?
133
- (date >date_s %date_e) <: (time >time_s %time_e) CFWS?;
134
-
135
- # Added CFWS? to increase robustness
136
- # (qmail likes to include a comment style string...?)
137
- received_token = word | angle_addr | addr_spec_no_angle_brackets | domain;
138
- received = ((CFWS? received_token*) >received_tokens_s %received_tokens_e)
139
- ";" date_time;
140
-
141
- # RFC2045: mime_version, content_type, content_transfer_encoding
142
- mime_version = CFWS?
143
- (DIGIT+ >major_digits_s %major_digits_e)
144
- comment? "." comment?
145
- (DIGIT+ >minor_digits_s %minor_digits_e)
146
- CFWS?;
147
-
148
- token = 0x21..0x27 | 0x2a..0x2b | 0x2c..0x2e |
149
- 0x30..0x39 | 0x41..0x5a | 0x5e..0x7e;
150
- value = (quoted_string | (token -- '"' | 0x3d)+) >param_val_s %param_val_e;
151
- attribute = (token+) >param_attr_s %param_attr_e;
152
- parameter = CFWS? attribute "=" value CFWS?;
153
-
154
- ietf_token = token+;
155
- custom_x_token = 'x'i "-" token+;
156
- extension_token = ietf_token | custom_x_token;
157
- discrete_type = 'text'i | 'image'i | 'audio'i | 'video'i |
158
- 'application'i | extension_token;
159
- composite_type = 'message'i | 'multipart'i | extension_token;
160
- iana_token = token+;
161
- main_type = (discrete_type | composite_type) >main_type_s %main_type_e;
162
- sub_type = (extension_token | iana_token) >sub_type_s %sub_type_e;
163
- content_type = main_type "/" sub_type (((CFWS? ";"+) | CFWS) parameter CFWS?)*;
164
-
165
- encoding = ('7bits' | '8bits' | '7bit' | '8bit' | 'binary' |
166
- 'quoted-printable' | 'base64' | ietf_token |
167
- custom_x_token) >encoding_s %encoding_e;
168
- content_transfer_encoding = CFWS? encoding CFWS? ";"? CFWS?;
169
-
170
- # RFC2183: content_disposition
171
- # TODO: recognize filename, size, creation date, etc.
172
- disposition_type = 'inline'i | 'attachment'i | extension_token | '';
173
- content_disposition = (disposition_type >disp_type_s %disp_type_e)
174
- (CFWS? ";" parameter CFWS?)*;
175
-
176
- # Envelope From
177
- ctime_date = day_name " "+ month " "+ day " " time_of_day " " year;
178
- envelope_from = (addr_spec_no_angle_brackets) >address_s %address_e " "
179
- (ctime_date >ctime_date_s %ctime_date_e);
180
-
181
- # content_location
182
- location = quoted_string | ((token | 0x3d)+ >token_string_s %token_string_e);
183
- content_location = CFWS? location CFWS?;
184
- }%%
@@ -1,61 +0,0 @@
1
- module Mail
2
- module Parsers
3
- module Ragel
4
- ACTIONS = [
5
- :addr_spec,
6
- :address_e,
7
- :address_s,
8
- :angle_addr_s,
9
- :comment_e,
10
- :comment_s,
11
- :ctime_date_e,
12
- :ctime_date_s,
13
- :date_e,
14
- :date_s,
15
- :disp_type_e,
16
- :disp_type_s,
17
- :domain_e,
18
- :domain_s,
19
- :encoding_e,
20
- :encoding_s,
21
- :group_name_e,
22
- :group_name_s,
23
- :local_dot_atom_e,
24
- :local_dot_atom_pre_comment_e,
25
- :local_dot_atom_s,
26
- :local_quoted_string_e,
27
- :main_type_e,
28
- :main_type_s,
29
- :major_digits_e,
30
- :major_digits_s,
31
- :minor_digits_e,
32
- :minor_digits_s,
33
- :msg_id_e,
34
- :msg_id_s,
35
- :obs_domain_list_e,
36
- :obs_domain_list_s,
37
- :param_attr_e,
38
- :param_attr_s,
39
- :param_val_e,
40
- :param_val_s,
41
- :phrase_e,
42
- :phrase_s,
43
- :qstr_e,
44
- :qstr_s,
45
- :received_tokens_e,
46
- :received_tokens_s,
47
- :sub_type_e,
48
- :sub_type_s,
49
- :time_e,
50
- :time_s,
51
- :token_string_e,
52
- :token_string_s
53
- ]
54
-
55
- FIELD_PARSERS = %w[ address_lists phrase_lists
56
- date_time received message_ids envelope_from
57
- mime_version content_type content_disposition
58
- content_transfer_encoding content_location ]
59
- end
60
- end
61
- end