mail 2.6.1 → 2.8.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 (188) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +150 -107
  4. data/lib/mail/attachments_list.rb +13 -10
  5. data/lib/mail/body.rb +104 -90
  6. data/lib/mail/check_delivery_params.rb +55 -10
  7. data/lib/mail/configuration.rb +3 -0
  8. data/lib/mail/constants.rb +79 -0
  9. data/lib/mail/elements/address.rb +96 -108
  10. data/lib/mail/elements/address_list.rb +13 -30
  11. data/lib/mail/elements/content_disposition_element.rb +10 -16
  12. data/lib/mail/elements/content_location_element.rb +9 -13
  13. data/lib/mail/elements/content_transfer_encoding_element.rb +7 -11
  14. data/lib/mail/elements/content_type_element.rb +17 -23
  15. data/lib/mail/elements/date_time_element.rb +8 -15
  16. data/lib/mail/elements/envelope_from_element.rb +23 -23
  17. data/lib/mail/elements/message_ids_element.rb +22 -15
  18. data/lib/mail/elements/mime_version_element.rb +8 -15
  19. data/lib/mail/elements/phrase_list.rb +13 -10
  20. data/lib/mail/elements/received_element.rb +28 -19
  21. data/lib/mail/elements.rb +1 -0
  22. data/lib/mail/encodings/7bit.rb +10 -14
  23. data/lib/mail/encodings/8bit.rb +5 -18
  24. data/lib/mail/encodings/base64.rb +15 -10
  25. data/lib/mail/encodings/binary.rb +4 -22
  26. data/lib/mail/encodings/identity.rb +24 -0
  27. data/lib/mail/encodings/quoted_printable.rb +13 -7
  28. data/lib/mail/encodings/transfer_encoding.rb +47 -28
  29. data/lib/mail/encodings/unix_to_unix.rb +20 -0
  30. data/lib/mail/encodings.rb +102 -92
  31. data/lib/mail/envelope.rb +12 -14
  32. data/lib/mail/field.rb +121 -85
  33. data/lib/mail/field_list.rb +62 -8
  34. data/lib/mail/fields/bcc_field.rb +42 -48
  35. data/lib/mail/fields/cc_field.rb +29 -50
  36. data/lib/mail/fields/comments_field.rb +28 -37
  37. data/lib/mail/fields/common_address_field.rb +170 -0
  38. data/lib/mail/fields/common_date_field.rb +58 -0
  39. data/lib/mail/fields/common_field.rb +77 -0
  40. data/lib/mail/fields/common_message_id_field.rb +42 -0
  41. data/lib/mail/fields/content_description_field.rb +8 -14
  42. data/lib/mail/fields/content_disposition_field.rb +20 -44
  43. data/lib/mail/fields/content_id_field.rb +25 -51
  44. data/lib/mail/fields/content_location_field.rb +12 -25
  45. data/lib/mail/fields/content_transfer_encoding_field.rb +32 -31
  46. data/lib/mail/fields/content_type_field.rb +51 -80
  47. data/lib/mail/fields/date_field.rb +24 -52
  48. data/lib/mail/fields/from_field.rb +29 -50
  49. data/lib/mail/fields/in_reply_to_field.rb +39 -49
  50. data/lib/mail/fields/keywords_field.rb +19 -32
  51. data/lib/mail/fields/message_id_field.rb +26 -71
  52. data/lib/mail/fields/mime_version_field.rb +20 -30
  53. data/lib/mail/fields/named_structured_field.rb +11 -0
  54. data/lib/mail/fields/named_unstructured_field.rb +11 -0
  55. data/lib/mail/fields/optional_field.rb +10 -7
  56. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +16 -13
  57. data/lib/mail/fields/received_field.rb +44 -57
  58. data/lib/mail/fields/references_field.rb +36 -49
  59. data/lib/mail/fields/reply_to_field.rb +29 -50
  60. data/lib/mail/fields/resent_bcc_field.rb +29 -50
  61. data/lib/mail/fields/resent_cc_field.rb +29 -50
  62. data/lib/mail/fields/resent_date_field.rb +6 -30
  63. data/lib/mail/fields/resent_from_field.rb +29 -50
  64. data/lib/mail/fields/resent_message_id_field.rb +6 -29
  65. data/lib/mail/fields/resent_sender_field.rb +28 -57
  66. data/lib/mail/fields/resent_to_field.rb +29 -50
  67. data/lib/mail/fields/return_path_field.rb +51 -55
  68. data/lib/mail/fields/sender_field.rb +35 -56
  69. data/lib/mail/fields/structured_field.rb +4 -30
  70. data/lib/mail/fields/subject_field.rb +10 -11
  71. data/lib/mail/fields/to_field.rb +29 -50
  72. data/lib/mail/fields/unstructured_field.rb +36 -50
  73. data/lib/mail/fields.rb +1 -0
  74. data/lib/mail/header.rb +73 -110
  75. data/lib/mail/indifferent_hash.rb +1 -0
  76. data/lib/mail/mail.rb +6 -11
  77. data/lib/mail/matchers/attachment_matchers.rb +44 -0
  78. data/lib/mail/matchers/has_sent_mail.rb +53 -9
  79. data/lib/mail/message.rb +132 -136
  80. data/lib/mail/multibyte/chars.rb +24 -180
  81. data/lib/mail/multibyte/unicode.rb +31 -26
  82. data/lib/mail/multibyte/utils.rb +27 -43
  83. data/lib/mail/multibyte.rb +56 -16
  84. data/lib/mail/network/delivery_methods/exim.rb +9 -11
  85. data/lib/mail/network/delivery_methods/file_delivery.rb +14 -16
  86. data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  87. data/lib/mail/network/delivery_methods/sendmail.rb +68 -24
  88. data/lib/mail/network/delivery_methods/smtp.rb +77 -54
  89. data/lib/mail/network/delivery_methods/smtp_connection.rb +5 -9
  90. data/lib/mail/network/delivery_methods/test_mailer.rb +9 -9
  91. data/lib/mail/network/retriever_methods/base.rb +9 -8
  92. data/lib/mail/network/retriever_methods/imap.rb +21 -7
  93. data/lib/mail/network/retriever_methods/pop3.rb +6 -3
  94. data/lib/mail/network/retriever_methods/test_retriever.rb +4 -2
  95. data/lib/mail/network.rb +2 -0
  96. data/lib/mail/parser_tools.rb +15 -0
  97. data/lib/mail/parsers/address_lists_parser.rb +33226 -116
  98. data/lib/mail/parsers/address_lists_parser.rl +179 -0
  99. data/lib/mail/parsers/content_disposition_parser.rb +883 -49
  100. data/lib/mail/parsers/content_disposition_parser.rl +89 -0
  101. data/lib/mail/parsers/content_location_parser.rb +810 -23
  102. data/lib/mail/parsers/content_location_parser.rl +78 -0
  103. data/lib/mail/parsers/content_transfer_encoding_parser.rb +510 -21
  104. data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
  105. data/lib/mail/parsers/content_type_parser.rb +1031 -47
  106. data/lib/mail/parsers/content_type_parser.rl +90 -0
  107. data/lib/mail/parsers/date_time_parser.rb +879 -24
  108. data/lib/mail/parsers/date_time_parser.rl +69 -0
  109. data/lib/mail/parsers/envelope_from_parser.rb +3670 -40
  110. data/lib/mail/parsers/envelope_from_parser.rl +89 -0
  111. data/lib/mail/parsers/message_ids_parser.rb +5147 -25
  112. data/lib/mail/parsers/message_ids_parser.rl +93 -0
  113. data/lib/mail/parsers/mime_version_parser.rb +498 -26
  114. data/lib/mail/parsers/mime_version_parser.rl +68 -0
  115. data/lib/mail/parsers/phrase_lists_parser.rb +872 -21
  116. data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
  117. data/lib/mail/parsers/received_parser.rb +8777 -42
  118. data/lib/mail/parsers/received_parser.rl +91 -0
  119. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  120. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  121. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  122. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  123. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  124. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  125. data/lib/mail/parsers/rfc5322.rl +74 -0
  126. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  127. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
  128. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  129. data/lib/mail/parsers.rb +12 -25
  130. data/lib/mail/part.rb +11 -12
  131. data/lib/mail/parts_list.rb +88 -14
  132. data/lib/mail/smtp_envelope.rb +57 -0
  133. data/lib/mail/utilities.rb +377 -40
  134. data/lib/mail/values/unicode_tables.dat +0 -0
  135. data/lib/mail/version.rb +8 -15
  136. data/lib/mail/yaml.rb +30 -0
  137. data/lib/mail.rb +9 -32
  138. metadata +138 -94
  139. data/CHANGELOG.rdoc +0 -752
  140. data/CONTRIBUTING.md +0 -60
  141. data/Dependencies.txt +0 -2
  142. data/Gemfile +0 -15
  143. data/Rakefile +0 -29
  144. data/TODO.rdoc +0 -9
  145. data/VERSION +0 -4
  146. data/lib/mail/core_extensions/nil.rb +0 -19
  147. data/lib/mail/core_extensions/object.rb +0 -13
  148. data/lib/mail/core_extensions/smtp.rb +0 -24
  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/core_extensions/string.rb +0 -43
  152. data/lib/mail/fields/common/address_container.rb +0 -16
  153. data/lib/mail/fields/common/common_address.rb +0 -135
  154. data/lib/mail/fields/common/common_date.rb +0 -35
  155. data/lib/mail/fields/common/common_field.rb +0 -57
  156. data/lib/mail/fields/common/common_message_id.rb +0 -48
  157. data/lib/mail/multibyte/exceptions.rb +0 -8
  158. data/lib/mail/parsers/ragel/common.rl +0 -184
  159. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  160. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  161. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  162. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  163. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  164. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  165. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  166. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  167. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  168. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  169. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  170. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  171. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  172. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2129
  173. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  174. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  175. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  176. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  177. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  178. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  179. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  180. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  181. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  182. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  183. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  184. data/lib/mail/parsers/ragel/ruby.rb +0 -39
  185. data/lib/mail/parsers/ragel.rb +0 -17
  186. data/lib/mail/patterns.rb +0 -37
  187. data/lib/mail/version_specific/ruby_1_8.rb +0 -119
  188. data/lib/mail/version_specific/ruby_1_9.rb +0 -159
data/lib/mail/body.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  module Mail
3
4
 
4
5
  # = Body
@@ -31,24 +32,29 @@ module Mail
31
32
  @preamble = nil
32
33
  @epilogue = nil
33
34
  @charset = nil
34
- @part_sort_order = [ "text/plain", "text/enriched", "text/html" ]
35
+ @part_sort_order = [ "text/plain", "text/enriched", "text/html", "multipart/alternative" ]
35
36
  @parts = Mail::PartsList.new
36
- if string.blank?
37
+ if Utilities.blank?(string)
37
38
  @raw_source = ''
38
39
  else
39
40
  # Do join first incase we have been given an Array in Ruby 1.9
40
41
  if string.respond_to?(:join)
41
- @raw_source = string.join('')
42
+ @raw_source = ::Mail::Utilities.to_crlf(string.join(''))
42
43
  elsif string.respond_to?(:to_s)
43
- @raw_source = string.to_s
44
+ @raw_source = ::Mail::Utilities.to_crlf(string.to_s)
44
45
  else
45
46
  raise "You can only assign a string or an object that responds_to? :join or :to_s to a body."
46
47
  end
47
48
  end
48
- @encoding = (only_us_ascii? ? '7bit' : '8bit')
49
+ @encoding = default_encoding
49
50
  set_charset
50
51
  end
51
-
52
+
53
+ def init_with(coder)
54
+ coder.map.each { |k, v| instance_variable_set(:"@#{k}", v) }
55
+ @parts = Mail::PartsList.new(coder['parts'])
56
+ end
57
+
52
58
  # Matches this body with another body. Also matches the decoded value of this
53
59
  # body with a string.
54
60
  #
@@ -114,8 +120,8 @@ module Mail
114
120
  end
115
121
 
116
122
  # Allows you to set the sort order of the parts, overriding the default sort order.
117
- # Defaults to 'text/plain', then 'text/enriched', then 'text/html' with any other content
118
- # type coming after.
123
+ # Defaults to 'text/plain', then 'text/enriched', then 'text/html', then 'multipart/alternative'
124
+ # with any other content type coming after.
119
125
  def set_sort_order(order)
120
126
  @part_sort_order = order
121
127
  end
@@ -132,46 +138,44 @@ module Mail
132
138
  @parts.sort!(@part_sort_order)
133
139
  end
134
140
 
135
- # Returns the raw source that the body was initialized with, without
136
- # any tampering
137
- def raw_source
138
- @raw_source
141
+ def negotiate_best_encoding(message_encoding, allowed_encodings = nil)
142
+ Mail::Encodings::TransferEncoding.negotiate(message_encoding, encoding, raw_source, allowed_encodings)
139
143
  end
140
-
141
- def get_best_encoding(target)
142
- target_encoding = Mail::Encodings.get_encoding(target)
143
- target_encoding.get_best_compatible(encoding, raw_source)
144
- end
145
-
144
+
146
145
  # Returns a body encoded using transfer_encoding. Multipart always uses an
147
146
  # identiy encoding (i.e. no encoding).
148
147
  # Calling this directly is not a good idea, but supported for compatibility
149
148
  # TODO: Validate that preamble and epilogue are valid for requested encoding
150
- def encoded(transfer_encoding = '8bit')
149
+ def encoded(transfer_encoding = nil)
151
150
  if multipart?
152
151
  self.sort_parts!
153
152
  encoded_parts = parts.map { |p| p.encoded }
154
153
  ([preamble] + encoded_parts).join(crlf_boundary) + end_boundary + epilogue.to_s
155
154
  else
156
- be = get_best_encoding(transfer_encoding)
157
- dec = Mail::Encodings::get_encoding(encoding)
158
- enc = Mail::Encodings::get_encoding(be)
159
- if transfer_encoding == encoding and dec.nil?
160
- # Cannot decode, so skip normalization
161
- raw_source
155
+ dec = Mail::Encodings.get_encoding(encoding)
156
+ enc =
157
+ if Utilities.blank?(transfer_encoding)
158
+ dec
159
+ else
160
+ negotiate_best_encoding(transfer_encoding)
161
+ end
162
+
163
+ if dec.nil?
164
+ # Cannot decode, so skip normalization
165
+ raw_source
162
166
  else
163
- # Decode then encode to normalize and allow transforming
164
- # from base64 to Q-P and vice versa
165
- decoded = dec.decode(raw_source)
166
- if defined?(Encoding) && charset && charset != "US-ASCII"
167
- decoded.encode!(charset)
168
- decoded.force_encoding('BINARY') unless Encoding.find(charset).ascii_compatible?
169
- end
170
- enc.encode(decoded)
167
+ # Decode then encode to normalize and allow transforming
168
+ # from base64 to Q-P and vice versa
169
+ decoded = dec.decode(raw_source)
170
+ if defined?(Encoding) && charset && charset != "US-ASCII"
171
+ decoded = decoded.encode(charset)
172
+ decoded.force_encoding('BINARY') unless Encoding.find(charset).ascii_compatible?
173
+ end
174
+ enc.encode(decoded)
171
175
  end
172
176
  end
173
177
  end
174
-
178
+
175
179
  def decoded
176
180
  if !Encodings.defined?(encoding)
177
181
  raise UnknownEncodingType, "Don't know how to decode #{encoding}, please call #encoded and decode it yourself."
@@ -183,14 +187,6 @@ module Mail
183
187
  def to_s
184
188
  decoded
185
189
  end
186
-
187
- def charset
188
- @charset
189
- end
190
-
191
- def charset=( val )
192
- @charset = val
193
- end
194
190
 
195
191
  def encoding(val = nil)
196
192
  if val
@@ -199,54 +195,41 @@ module Mail
199
195
  @encoding
200
196
  end
201
197
  end
202
-
198
+
203
199
  def encoding=( val )
204
- @encoding = if val == "text" || val.blank?
205
- (only_us_ascii? ? '7bit' : '8bit')
206
- else
200
+ @encoding =
201
+ if val == "text" || Utilities.blank?(val)
202
+ default_encoding
203
+ else
207
204
  val
208
- end
205
+ end
209
206
  end
210
207
 
211
- # Returns the preamble (any text that is before the first MIME boundary)
212
- def preamble
213
- @preamble
214
- end
208
+ # Returns the raw source that the body was initialized with, without
209
+ # any tampering
210
+ attr_reader :raw_source
211
+
212
+ # Returns parts of the body
213
+ attr_reader :parts
214
+
215
+ # Returns and sets the original character encoding
216
+ attr_accessor :charset
217
+
218
+ # Returns and sets the preamble as a string (any text that is before the first MIME boundary)
219
+ attr_accessor :preamble
220
+
221
+ # Returns and sets the epilogue as a string (any text that is after the last MIME boundary)
222
+ attr_accessor :epilogue
223
+
224
+ # Returns and sets the boundary used by the body
225
+ # Allows you to change the boundary of this Body object
226
+ attr_accessor :boundary
215
227
 
216
- # Sets the preamble to a string (adds text before the first MIME boundary)
217
- def preamble=( val )
218
- @preamble = val
219
- end
220
-
221
- # Returns the epilogue (any text that is after the last MIME boundary)
222
- def epilogue
223
- @epilogue
224
- end
225
-
226
- # Sets the epilogue to a string (adds text after the last MIME boundary)
227
- def epilogue=( val )
228
- @epilogue = val
229
- end
230
-
231
228
  # Returns true if there are parts defined in the body
232
229
  def multipart?
233
230
  true unless parts.empty?
234
231
  end
235
-
236
- # Returns the boundary used by the body
237
- def boundary
238
- @boundary
239
- end
240
-
241
- # Allows you to change the boundary of this Body object
242
- def boundary=( val )
243
- @boundary = val
244
- end
245
232
 
246
- def parts
247
- @parts
248
- end
249
-
250
233
  def <<( val )
251
234
  if @parts
252
235
  @parts << val
@@ -254,27 +237,58 @@ module Mail
254
237
  @parts = Mail::PartsList.new[val]
255
238
  end
256
239
  end
257
-
240
+
258
241
  def split!(boundary)
259
242
  self.boundary = boundary
260
- parts = raw_source.split(/(?:\A|\r\n)--#{Regexp.escape(boundary || "")}(?=(?:--)?\s*$)/)
243
+ parts = extract_parts
244
+
261
245
  # Make the preamble equal to the preamble (if any)
262
246
  self.preamble = parts[0].to_s.strip
263
247
  # Make the epilogue equal to the epilogue (if any)
264
- self.epilogue = parts[-1].to_s.sub('--', '').strip
248
+ self.epilogue = parts[-1].to_s.strip
265
249
  parts[1...-1].to_a.each { |part| @parts << Mail::Part.new(part) }
266
250
  self
267
251
  end
268
-
269
- def only_us_ascii?
270
- !(raw_source =~ /[^\x01-\x7f]/)
252
+
253
+ def ascii_only?
254
+ unless defined? @ascii_only
255
+ @ascii_only = raw_source.ascii_only?
256
+ end
257
+ @ascii_only
271
258
  end
272
-
259
+
273
260
  def empty?
274
261
  !!raw_source.to_s.empty?
275
262
  end
276
-
263
+
264
+ def default_encoding
265
+ ascii_only? ? '7bit' : '8bit'
266
+ end
267
+
277
268
  private
269
+
270
+ # split parts by boundary, ignore first part if empty, append final part when closing boundary was missing
271
+ def extract_parts
272
+ parts_regex = /
273
+ (?: # non-capturing group
274
+ \A | # start of string OR
275
+ \r\n # line break
276
+ )
277
+ (
278
+ --#{Regexp.escape(boundary || "")} # boundary delimiter
279
+ (?:--)? # with non-capturing optional closing
280
+ )
281
+ (?=\s*$) # lookahead matching zero or more spaces followed by line-ending
282
+ /x
283
+ parts = raw_source.split(parts_regex).each_slice(2).to_a
284
+ parts.each_with_index { |(part, _), index| parts.delete_at(index) if index > 0 && Utilities.blank?(part) }
285
+
286
+ if parts.size > 1
287
+ final_separator = parts[-2][1]
288
+ parts << [""] if final_separator != "--#{boundary}--"
289
+ end
290
+ parts.map(&:first)
291
+ end
278
292
 
279
293
  def crlf_boundary
280
294
  "\r\n--#{boundary}\r\n"
@@ -283,9 +297,9 @@ module Mail
283
297
  def end_boundary
284
298
  "\r\n--#{boundary}--\r\n"
285
299
  end
286
-
300
+
287
301
  def set_charset
288
- only_us_ascii? ? @charset = 'US-ASCII' : @charset = nil
302
+ @charset = ascii_only? ? 'US-ASCII' : nil
289
303
  end
290
304
  end
291
305
  end
@@ -1,20 +1,65 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # This whole class and associated specs is deprecated and will go away in the version 3 release of mail.
1
4
  module 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.')
5
+ module CheckDeliveryParams #:nodoc:
6
+ class << self
7
+
8
+ extend Gem::Deprecate
9
+
10
+ def check(mail)
11
+ envelope = Mail::SmtpEnvelope.new(mail)
12
+ [ envelope.from,
13
+ envelope.to,
14
+ envelope.message ]
15
+ end
16
+ deprecate :check, 'Mail::SmtpEnvelope.new created in commit c106bebea066782a72e4f24dd37b532d95773df7', 2023, 6
17
+
18
+ def check_from(addr)
19
+ mail = Mail.new(from: 'deprecated@example.com', to: 'deprecated@example.com')
20
+ Mail::SmtpEnvelope.new(mail).send(:validate_addr, 'From', addr)
6
21
  end
22
+ deprecate :check_from, :none, 2023, 6
7
23
 
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.')
24
+ def check_to(addrs)
25
+ mail = Mail.new(from: 'deprecated@example.com', to: 'deprecated@example.com')
26
+ Array(addrs).map do |addr|
27
+ Mail::SmtpEnvelope.new(mail).send(:validate_addr, 'To', addr)
28
+ end
10
29
  end
30
+ deprecate :check_to, :none, 2023, 6
11
31
 
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
+ def check_addr(addr_name, addr)
33
+ mail = Mail.new(from: 'deprecated@example.com', to: 'deprecated@example.com')
34
+ Mail::SmtpEnvelope.new(mail).send(:validate_addr, addr_name, addr)
15
35
  end
36
+ deprecate :check_addr, :none, 2023, 6
37
+
38
+ def validate_smtp_addr(addr)
39
+ if addr
40
+ if addr.bytesize > 2048
41
+ yield 'may not exceed 2kB'
42
+ end
43
+
44
+ if /[\r\n]/ =~ addr
45
+ yield 'may not contain CR or LF line breaks'
46
+ end
47
+ end
16
48
 
17
- [mail.smtp_envelope_from, mail.smtp_envelope_to, message]
49
+ addr
50
+ end
51
+ deprecate :validate_smtp_addr, :none, 2023, 6
52
+
53
+ def check_message(message)
54
+ message = message.encoded if message.respond_to?(:encoded)
55
+
56
+ if Utilities.blank?(message)
57
+ raise ArgumentError, 'An encoded message is required to send an email'
58
+ end
59
+
60
+ message
61
+ end
62
+ deprecate :check_message, :none, 2023, 6
18
63
  end
19
64
  end
20
65
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # Thanks to Nicolas Fouché for this wrapper
4
5
  #
@@ -41,6 +42,8 @@ module Mail
41
42
  Mail::SMTPConnection
42
43
  when :test
43
44
  Mail::TestMailer
45
+ when :logger
46
+ Mail::LoggerDelivery
44
47
  else
45
48
  method
46
49
  end
@@ -0,0 +1,79 @@
1
+ # encoding: us-ascii
2
+ # frozen_string_literal: true
3
+ module Mail
4
+ module Constants
5
+ white_space = %Q|\x9\x20|
6
+ text = %Q|\x1-\x8\xB\xC\xE-\x7f|
7
+ field_name = %Q|\x21-\x39\x3b-\x7e|
8
+ qp_safe = %Q|\x20-\x3c\x3e-\x7e|
9
+
10
+ aspecial = %Q|()<>[]:;@\\,."| # RFC5322
11
+ tspecial = %Q|()<>@,;:\\"/[]?=| # RFC2045
12
+ sp = %Q| |
13
+ control = %Q|\x00-\x1f\x7f-\xff|
14
+
15
+ if control.respond_to?(:force_encoding)
16
+ control = control.dup.force_encoding(Encoding::BINARY)
17
+ end
18
+
19
+ LAX_CRLF = /\r?\n/
20
+ WSP = /[#{white_space}]/
21
+ FWS = /#{LAX_CRLF}#{WSP}*/
22
+ UNFOLD_WS = /#{LAX_CRLF}(#{WSP})/m
23
+ TEXT = /[#{text}]/ # + obs-text
24
+ FIELD_NAME = /[#{field_name}]+/
25
+ FIELD_PREFIX = /\A(#{FIELD_NAME})/
26
+ FIELD_BODY = /.+/m
27
+ FIELD_LINE = /^[#{field_name}]+:\s*.+$/
28
+ FIELD_SPLIT = /^(#{FIELD_NAME})\s*:\s*(#{FIELD_BODY})?$/
29
+ HEADER_LINE = /^([#{field_name}]+:\s*.+)$/
30
+ HEADER_SPLIT = /#{LAX_CRLF}(?!#{WSP})/
31
+
32
+ QP_UNSAFE = /[^#{qp_safe}]/
33
+ QP_SAFE = /[#{qp_safe}]/
34
+ CONTROL_CHAR = /[#{control}]/n
35
+ ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{sp}]/n
36
+ PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
37
+ TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{sp}]/n
38
+
39
+ ENCODED_VALUE = %r{
40
+ \=\? # literal =?
41
+ ([^?]+) #
42
+ \? # literal ?
43
+ ([QB]) # either a "Q" or a "B"
44
+ \? # literal ?
45
+ .*? # lazily match all characters
46
+ \?\= # literal ?=
47
+ }mix # m is multi-line, i is case-insensitive, x is free-spacing
48
+
49
+ FULL_ENCODED_VALUE = %r{ # Identical to ENCODED_VALUE but captures the whole rather than components of
50
+ (
51
+ \=\? # literal =?
52
+ [^?]+ #
53
+ \? # literal ?
54
+ [QB] # either a "Q" or a "B"
55
+ \? # literal ?
56
+ .*? # lazily match all characters
57
+ \?\= # literal ?=
58
+ )
59
+ }mix # m is multi-line, i is case-insensitive, x is free-spacing
60
+
61
+ EMPTY = ''
62
+ SPACE = ' '
63
+ UNDERSCORE = '_'
64
+ HYPHEN = '-'
65
+ COLON = ':'
66
+ ASTERISK = '*'
67
+ CRLF = "\r\n"
68
+ CR = "\r"
69
+ LF = "\n"
70
+ CR_ENCODED = "=0D"
71
+ LF_ENCODED = "=0A"
72
+ CAPITAL_M = 'M'
73
+ EQUAL_LF = "=\n"
74
+ NULL_SENDER = '<>'
75
+
76
+ Q_VALUES = ['Q','q']
77
+ B_VALUES = ['B','b']
78
+ end
79
+ end