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
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_structured_field'
4
+ require 'mail/utilities'
5
+
6
+ module Mail
7
+ class CommonMessageIdField < NamedStructuredField #:nodoc:
8
+ def element
9
+ @element ||= Mail::MessageIdsElement.new(value)
10
+ end
11
+
12
+ def message_id
13
+ element.message_id
14
+ end
15
+
16
+ def message_ids
17
+ element.message_ids
18
+ end
19
+
20
+ def default
21
+ ids = message_ids
22
+ ids.one? ? ids.first : ids
23
+ end
24
+
25
+ def to_s
26
+ decoded.to_s
27
+ end
28
+
29
+ private
30
+ def do_encode
31
+ %Q{#{name}: #{formatted_message_ids("\r\n ")}\r\n}
32
+ end
33
+
34
+ def do_decode
35
+ formatted_message_ids
36
+ end
37
+
38
+ def formatted_message_ids(join = ' ')
39
+ message_ids.map { |m| "<#{m}>" }.join(join) if message_ids.any?
40
+ end
41
+ end
42
+ end
@@ -1,19 +1,13 @@
1
1
  # encoding: utf-8
2
- #
3
- #
4
- #
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_unstructured_field'
4
+
5
5
  module Mail
6
- class ContentDescriptionField < UnstructuredField
7
-
8
- FIELD_NAME = 'content-description'
9
- CAPITALIZED_FIELD = 'Content-Description'
10
-
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
14
- self.parse
15
- self
6
+ class ContentDescriptionField < NamedUnstructuredField #:nodoc:
7
+ NAME = 'Content-Description'
8
+
9
+ def self.singular?
10
+ true
16
11
  end
17
-
18
12
  end
19
13
  end
@@ -1,26 +1,20 @@
1
1
  # encoding: utf-8
2
- require 'mail/fields/common/parameter_hash'
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_structured_field'
4
+ require 'mail/fields/parameter_hash'
3
5
 
4
6
  module Mail
5
- class ContentDispositionField < StructuredField
6
-
7
- FIELD_NAME = 'content-disposition'
8
- CAPITALIZED_FIELD = 'Content-Disposition'
9
-
10
- def initialize(value = nil, charset = 'utf-8')
11
- self.charset = charset
12
- ensure_filename_quoted(value)
13
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
14
- self.parse
15
- self
7
+ class ContentDispositionField < NamedStructuredField #:nodoc:
8
+ NAME = 'Content-Disposition'
9
+
10
+ def self.singular?
11
+ true
16
12
  end
17
-
18
- def parse(val = value)
19
- unless val.blank?
20
- @element = Mail::ContentDispositionElement.new(val)
21
- end
13
+
14
+ def initialize(value = nil, charset = nil)
15
+ super ensure_filename_quoted(value), charset
22
16
  end
23
-
17
+
24
18
  def element
25
19
  @element ||= Mail::ContentDispositionElement.new(value)
26
20
  end
@@ -28,43 +22,25 @@ module Mail
28
22
  def disposition_type
29
23
  element.disposition_type
30
24
  end
31
-
25
+
32
26
  def parameters
33
27
  @parameters = ParameterHash.new
34
- element.parameters.each { |p| @parameters.merge!(p) }
28
+ element.parameters.each { |p| @parameters.merge!(p) } unless element.parameters.nil?
35
29
  @parameters
36
30
  end
37
31
 
38
32
  def filename
39
- case
40
- when !parameters['filename'].blank?
41
- @filename = parameters['filename']
42
- when !parameters['name'].blank?
43
- @filename = parameters['name']
44
- else
45
- @filename = nil
46
- end
47
- @filename
33
+ @filename ||= parameters['filename'] || parameters['name']
48
34
  end
49
35
 
50
- # TODO: Fix this up
51
36
  def encoded
52
- if parameters.length > 0
53
- p = ";\r\n\s#{parameters.encoded}\r\n"
54
- else
55
- p = "\r\n"
56
- end
57
- "#{CAPITALIZED_FIELD}: #{disposition_type}" + p
37
+ p = ";\r\n\s#{parameters.encoded}" if parameters.length > 0
38
+ "#{name}: #{disposition_type}#{p}\r\n"
58
39
  end
59
-
40
+
60
41
  def decoded
61
- if parameters.length > 0
62
- p = "; #{parameters.decoded}"
63
- else
64
- p = ""
65
- end
66
- "#{disposition_type}" + p
42
+ p = "; #{parameters.decoded}" if parameters.length > 0
43
+ "#{disposition_type}#{p}"
67
44
  end
68
-
69
45
  end
70
46
  end
@@ -1,62 +1,36 @@
1
1
  # encoding: utf-8
2
- #
3
- #
4
- #
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_structured_field'
4
+ require 'mail/utilities'
5
+
5
6
  module Mail
6
- class ContentIdField < StructuredField
7
-
8
- FIELD_NAME = 'content-id'
9
- CAPITALIZED_FIELD = "Content-ID"
10
-
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- @uniq = 1
14
- if value.blank?
15
- value = generate_content_id
16
- else
17
- value = strip_field(FIELD_NAME, value)
18
- end
19
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
20
- self.parse
21
- self
22
- end
23
-
24
- def parse(val = value)
25
- unless val.blank?
26
- @element = Mail::MessageIdsElement.new(val)
27
- end
28
- end
29
-
7
+ class ContentIdField < NamedStructuredField #:nodoc:
8
+ NAME = 'Content-ID'
9
+
10
+ def self.singular?
11
+ true
12
+ end
13
+
14
+ def initialize(value = nil, charset = nil)
15
+ value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
16
+ super value, charset
17
+ end
18
+
30
19
  def element
31
20
  @element ||= Mail::MessageIdsElement.new(value)
32
21
  end
33
-
34
- def name
35
- 'Content-ID'
36
- end
37
-
22
+
38
23
  def content_id
39
24
  element.message_id
40
25
  end
41
-
42
- def to_s
43
- "<#{content_id}>"
44
- end
45
-
46
- # TODO: Fix this up
47
- def encoded
48
- "#{CAPITALIZED_FIELD}: #{to_s}\r\n"
49
- end
50
-
51
- def decoded
52
- "#{to_s}"
53
- end
54
-
26
+
55
27
  private
56
-
57
- def generate_content_id
58
- "<#{Mail.random_tag}@#{::Socket.gethostname}.mail>"
59
- end
60
-
28
+ def do_decode
29
+ "<#{content_id}>"
30
+ end
31
+
32
+ def do_encode
33
+ "#{name}: #{do_decode}\r\n"
34
+ end
61
35
  end
62
36
  end
@@ -1,26 +1,15 @@
1
1
  # encoding: utf-8
2
- #
3
- #
4
- #
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_structured_field'
4
+
5
5
  module Mail
6
- class ContentLocationField < StructuredField
7
-
8
- FIELD_NAME = 'content-location'
9
- CAPITALIZED_FIELD = 'Content-Location'
10
-
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
14
- self.parse
15
- self
16
- end
17
-
18
- def parse(val = value)
19
- unless val.blank?
20
- @element = Mail::ContentLocationElement.new(val)
21
- end
6
+ class ContentLocationField < NamedStructuredField #:nodoc:
7
+ NAME = 'Content-Location'
8
+
9
+ def self.singular?
10
+ true
22
11
  end
23
-
12
+
24
13
  def element
25
14
  @element ||= Mail::ContentLocationElement.new(value)
26
15
  end
@@ -29,14 +18,12 @@ module Mail
29
18
  element.location
30
19
  end
31
20
 
32
- # TODO: Fix this up
33
21
  def encoded
34
- "#{CAPITALIZED_FIELD}: #{location}\r\n"
22
+ "#{name}: #{location}\r\n"
35
23
  end
36
-
24
+
37
25
  def decoded
38
- location
26
+ location
39
27
  end
40
-
41
28
  end
42
29
  end
@@ -1,44 +1,45 @@
1
1
  # encoding: utf-8
2
- #
3
- #
4
- #
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_structured_field'
4
+
5
5
  module Mail
6
- class ContentTransferEncodingField < StructuredField
7
-
8
- FIELD_NAME = 'content-transfer-encoding'
9
- CAPITALIZED_FIELD = 'Content-Transfer-Encoding'
10
-
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- value = '7bit' if value.to_s =~ /7-?bits?/i
14
- value = '8bit' if value.to_s =~ /8-?bits?/i
15
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
16
- self.parse
17
- self
6
+ class ContentTransferEncodingField < NamedStructuredField #:nodoc:
7
+ NAME = 'Content-Transfer-Encoding'
8
+
9
+ def self.singular?
10
+ true
18
11
  end
19
-
20
- def parse(val = value)
21
- unless val.blank?
22
- @element = Mail::ContentTransferEncodingElement.new(val)
12
+
13
+ def self.normalize_content_transfer_encoding(value)
14
+ case value
15
+ when /7-?bits?/i
16
+ '7bit'
17
+ when /8-?bits?/i
18
+ '8bit'
19
+ else
20
+ value
23
21
  end
24
22
  end
25
-
23
+
24
+ def initialize(value = nil, charset = nil)
25
+ super self.class.normalize_content_transfer_encoding(value), charset
26
+ end
27
+
26
28
  def element
27
29
  @element ||= Mail::ContentTransferEncodingElement.new(value)
28
30
  end
29
-
31
+
30
32
  def encoding
31
33
  element.encoding
32
34
  end
33
-
34
- # TODO: Fix this up
35
- def encoded
36
- "#{CAPITALIZED_FIELD}: #{encoding}\r\n"
37
- end
38
-
39
- def decoded
40
- encoding
41
- end
42
-
35
+
36
+ private
37
+ def do_encode
38
+ "#{name}: #{encoding}\r\n"
39
+ end
40
+
41
+ def do_decode
42
+ encoding
43
+ end
43
44
  end
44
45
  end
@@ -1,52 +1,55 @@
1
1
  # encoding: utf-8
2
- require 'mail/fields/common/parameter_hash'
2
+ # frozen_string_literal: true
3
+ require 'mail/fields/named_structured_field'
4
+ require 'mail/fields/parameter_hash'
3
5
 
4
6
  module Mail
5
- class ContentTypeField < StructuredField
7
+ class ContentTypeField < NamedStructuredField #:nodoc:
8
+ NAME = 'Content-Type'
6
9
 
7
- FIELD_NAME = 'content-type'
8
- CAPITALIZED_FIELD = 'Content-Type'
10
+ class << self
11
+ def singular?
12
+ true
13
+ end
14
+
15
+ def with_boundary(type)
16
+ new "#{type}; boundary=#{generate_boundary}"
17
+ end
18
+
19
+ def generate_boundary
20
+ "--==_mimepart_#{Mail.random_tag}"
21
+ end
22
+ end
9
23
 
10
- def initialize(value = nil, charset = 'utf-8')
11
- self.charset = charset
12
- if value.class == Array
24
+ def initialize(value = nil, charset = nil)
25
+ if value.is_a? Array
13
26
  @main_type = value[0]
14
27
  @sub_type = value[1]
15
28
  @parameters = ParameterHash.new.merge!(value.last)
16
29
  else
17
30
  @main_type = nil
18
31
  @sub_type = nil
19
- @parameters = nil
20
- value = strip_field(FIELD_NAME, value)
32
+ value = value.to_s
21
33
  end
22
- ensure_filename_quoted(value)
23
- super(CAPITALIZED_FIELD, value, charset)
24
- self.parse
25
- self
26
- end
27
34
 
28
- def parse(val = value)
29
- unless val.blank?
30
- self.value = val
31
- @element = nil
32
- element
33
- end
35
+ super ensure_filename_quoted(value), charset
34
36
  end
35
37
 
36
38
  def element
37
- begin
38
- @element ||= Mail::ContentTypeElement.new(value)
39
- rescue
40
- attempt_to_clean
41
- end
39
+ @element ||=
40
+ begin
41
+ Mail::ContentTypeElement.new(value)
42
+ rescue Mail::Field::ParseError
43
+ attempt_to_clean
44
+ end
42
45
  end
43
46
 
44
47
  def attempt_to_clean
45
48
  # Sanitize the value, handle special cases
46
- @element ||= Mail::ContentTypeElement.new(sanatize(value))
47
- rescue
49
+ Mail::ContentTypeElement.new(sanitize(value))
50
+ rescue Mail::Field::ParseError
48
51
  # All else fails, just get the MIME media type
49
- @element ||= Mail::ContentTypeElement.new(get_mime_type(value))
52
+ Mail::ContentTypeElement.new(get_mime_type(value))
50
53
  end
51
54
 
52
55
  def main_type
@@ -60,31 +63,22 @@ module Mail
60
63
  def string
61
64
  "#{main_type}/#{sub_type}"
62
65
  end
66
+ alias_method :content_type, :string
63
67
 
64
68
  def default
65
69
  decoded
66
70
  end
67
71
 
68
- alias :content_type :string
69
-
70
72
  def parameters
71
- unless @parameters
73
+ unless defined? @parameters
72
74
  @parameters = ParameterHash.new
73
75
  element.parameters.each { |p| @parameters.merge!(p) }
74
76
  end
75
77
  @parameters
76
78
  end
77
79
 
78
- def ContentTypeField.with_boundary(type)
79
- new("#{type}; boundary=#{generate_boundary}")
80
- end
81
-
82
- def ContentTypeField.generate_boundary
83
- "--==_mimepart_#{Mail.random_tag}"
84
- end
85
-
86
80
  def value
87
- if @value.class == Array
81
+ if @value.is_a? Array
88
82
  "#{@main_type}/#{@sub_type}; #{stringify(parameters)}"
89
83
  else
90
84
  @value
@@ -96,34 +90,17 @@ module Mail
96
90
  end
97
91
 
98
92
  def filename
99
- case
100
- when parameters['filename']
101
- @filename = parameters['filename']
102
- when parameters['name']
103
- @filename = parameters['name']
104
- else
105
- @filename = nil
106
- end
107
- @filename
93
+ @filename ||= parameters['filename'] || parameters['name']
108
94
  end
109
95
 
110
- # TODO: Fix this up
111
96
  def encoded
112
- if parameters.length > 0
113
- p = ";\r\n\s#{parameters.encoded}"
114
- else
115
- p = ""
116
- end
117
- "#{CAPITALIZED_FIELD}: #{content_type}#{p}\r\n"
97
+ p = ";\r\n\s#{parameters.encoded}" if parameters && parameters.length > 0
98
+ "#{name}: #{content_type}#{p}\r\n"
118
99
  end
119
100
 
120
101
  def decoded
121
- if parameters.length > 0
122
- p = "; #{parameters.decoded}"
123
- else
124
- p = ""
125
- end
126
- "#{content_type}" + p
102
+ p = "; #{parameters.decoded}" if parameters && parameters.length > 0
103
+ "#{content_type}#{p}"
127
104
  end
128
105
 
129
106
  private
@@ -139,30 +116,24 @@ module Mail
139
116
 
140
117
  # Various special cases from random emails found that I am not going to change
141
118
  # the parser for
142
- def sanatize( val )
143
-
119
+ def sanitize(val)
144
120
  # TODO: check if there are cases where whitespace is not a separator
145
121
  val = val.
146
122
  gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
147
- tr(' ',';').
148
- squeeze(';').
149
- gsub(';', '; '). #use '; ' as a separator (or EOL)
123
+ gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL)
150
124
  gsub(/;\s*$/,'') #remove trailing to keep examples below
151
125
 
152
- if val =~ /(boundary=(\S*))/i
153
- val = "#{$`.downcase}boundary=#{$2}#{$'.downcase}"
126
+ if val =~ /((boundary|name|filename)=(\S*))/i
127
+ val = "#{$`.downcase}#{$2}=#{$3}#{$'.downcase}"
154
128
  else
155
129
  val.downcase!
156
130
  end
157
131
 
158
132
  case
159
- when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;;+(.*)$/i
160
- # Handles 'text/plain;; format="flowed"' (double semi colon)
161
- "#{$1}/#{$2}; #{$3}"
162
133
  when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
163
134
  # Microsoft helper:
164
135
  # Handles 'type/subtype;ISO-8559-1'
165
- "#{$1}/#{$2}; charset=#{quote_atom($3)}"
136
+ "#{$1}/#{$2}; charset=#{Utilities.quote_atom($3)}"
166
137
  when val.chomp =~ /^text;?$/i
167
138
  # Handles 'text;' and 'text'
168
139
  "text/plain;"
@@ -171,7 +142,7 @@ module Mail
171
142
  "text/plain; #{$2}"
172
143
  when val =~ /([\w\-]+\/[\w\-]+);\scharset="charset="(\w+)""/i
173
144
  # Handles text/html; charset="charset="GB2312""
174
- "#{$1}; charset=#{quote_atom($2)}"
145
+ "#{$1}; charset=#{Utilities.quote_atom($2)}"
175
146
  when val =~ /([\w\-]+\/[\w\-]+);\s+(.*)/i
176
147
  type = $1
177
148
  # Handles misquoted param values
@@ -179,19 +150,19 @@ module Mail
179
150
  # and: audio/x-midi;\r\n\sname=Part .exe
180
151
  params = $2.to_s.split(/\s+/)
181
152
  params = params.map { |i| i.to_s.chomp.strip }
182
- params = params.map { |i| i.split(/\s*\=\s*/) }
183
- params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
153
+ params = params.map { |i| i.split(/\s*\=\s*/, 2) }
154
+ params = params.map { |i| "#{i[0]}=#{Utilities.dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
184
155
  "#{type}; #{params}"
185
156
  when val =~ /^\s*$/
186
157
  'text/plain'
187
158
  else
188
- ''
159
+ val
189
160
  end
190
161
  end
191
162
 
192
- def get_mime_type( val )
193
- case
194
- when val =~ /^([\w\-]+)\/([\w\-]+);.+$/i
163
+ def get_mime_type(val)
164
+ case val
165
+ when /^([\w\-]+)\/([\w\-]+);.+$/i
195
166
  "#{$1}/#{$2}"
196
167
  else
197
168
  'text/plain'