mail 2.6.3 → 2.7.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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +91 -79
  4. data/lib/mail/attachments_list.rb +11 -5
  5. data/lib/mail/body.rb +46 -39
  6. data/lib/mail/check_delivery_params.rb +50 -10
  7. data/lib/mail/configuration.rb +3 -0
  8. data/lib/mail/constants.rb +4 -2
  9. data/lib/mail/core_extensions/smtp.rb +20 -16
  10. data/lib/mail/core_extensions/string.rb +1 -30
  11. data/lib/mail/elements/address.rb +43 -32
  12. data/lib/mail/elements/address_list.rb +11 -18
  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 +3 -1
  32. data/lib/mail/encodings.rb +114 -60
  33. data/lib/mail/envelope.rb +2 -1
  34. data/lib/mail/field.rb +112 -62
  35. data/lib/mail/field_list.rb +1 -0
  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 +5 -11
  43. data/lib/mail/fields/common/common_message_id.rb +3 -2
  44. data/lib/mail/fields/common/parameter_hash.rb +2 -1
  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 +6 -10
  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 +25 -7
  74. data/lib/mail/fields.rb +1 -0
  75. data/lib/mail/header.rb +15 -12
  76. data/lib/mail/indifferent_hash.rb +1 -0
  77. data/lib/mail/mail.rb +3 -10
  78. data/lib/mail/matchers/attachment_matchers.rb +29 -0
  79. data/lib/mail/matchers/has_sent_mail.rb +51 -7
  80. data/lib/mail/message.rb +91 -85
  81. data/lib/mail/multibyte/chars.rb +32 -30
  82. data/lib/mail/multibyte/unicode.rb +21 -16
  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 +33187 -112
  99. data/lib/mail/parsers/address_lists_parser.rl +172 -0
  100. data/lib/mail/parsers/content_disposition_parser.rb +889 -55
  101. data/lib/mail/parsers/content_disposition_parser.rl +82 -0
  102. data/lib/mail/parsers/content_location_parser.rb +801 -23
  103. data/lib/mail/parsers/content_location_parser.rl +71 -0
  104. data/lib/mail/parsers/content_transfer_encoding_parser.rb +511 -22
  105. data/lib/mail/parsers/content_transfer_encoding_parser.rl +64 -0
  106. data/lib/mail/parsers/content_type_parser.rb +1033 -54
  107. data/lib/mail/parsers/content_type_parser.rl +83 -0
  108. data/lib/mail/parsers/date_time_parser.rb +875 -25
  109. data/lib/mail/parsers/date_time_parser.rl +62 -0
  110. data/lib/mail/parsers/envelope_from_parser.rb +3565 -36
  111. data/lib/mail/parsers/envelope_from_parser.rl +82 -0
  112. data/lib/mail/parsers/message_ids_parser.rb +2844 -25
  113. data/lib/mail/parsers/message_ids_parser.rl +82 -0
  114. data/lib/mail/parsers/mime_version_parser.rb +494 -26
  115. data/lib/mail/parsers/mime_version_parser.rl +61 -0
  116. data/lib/mail/parsers/phrase_lists_parser.rb +876 -18
  117. data/lib/mail/parsers/phrase_lists_parser.rl +83 -0
  118. data/lib/mail/parsers/received_parser.rb +8744 -37
  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 +6 -3
  132. data/lib/mail/parts_list.rb +31 -14
  133. data/lib/mail/utilities.rb +107 -8
  134. data/lib/mail/values/unicode_tables.dat +0 -0
  135. data/lib/mail/version.rb +3 -2
  136. data/lib/mail/version_specific/ruby_1_8.rb +50 -6
  137. data/lib/mail/version_specific/ruby_1_9.rb +103 -18
  138. data/lib/mail.rb +5 -12
  139. metadata +33 -57
  140. data/CHANGELOG.rdoc +0 -759
  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/lib/mail/core_extensions/nil.rb +0 -19
  147. data/lib/mail/core_extensions/object.rb +0 -13
  148. data/lib/mail/core_extensions/string/access.rb +0 -145
  149. data/lib/mail/core_extensions/string/multibyte.rb +0 -78
  150. data/lib/mail/multibyte/exceptions.rb +0 -8
  151. data/lib/mail/parsers/ragel/common.rl +0 -185
  152. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  153. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  154. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  155. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  156. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  157. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  158. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  159. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  160. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  161. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  162. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  163. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  164. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  165. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  166. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  167. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  168. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  169. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  170. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  171. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  172. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  173. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  174. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  175. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  176. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  177. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  178. data/lib/mail/parsers/ragel.rb +0 -17
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  require 'mail/fields/common/parameter_hash'
3
4
 
4
5
  module Mail
@@ -17,16 +18,16 @@ module Mail
17
18
  @main_type = nil
18
19
  @sub_type = nil
19
20
  @parameters = nil
20
- value = strip_field(FIELD_NAME, value)
21
+ value = value.to_s
21
22
  end
22
- ensure_filename_quoted(value)
23
+ value = ensure_filename_quoted(value)
23
24
  super(CAPITALIZED_FIELD, value, charset)
24
25
  self.parse
25
26
  self
26
27
  end
27
28
 
28
29
  def parse(val = value)
29
- unless val.blank?
30
+ unless Utilities.blank?(val)
30
31
  self.value = val
31
32
  @element = nil
32
33
  element
@@ -144,9 +145,7 @@ module Mail
144
145
  # TODO: check if there are cases where whitespace is not a separator
145
146
  val = val.
146
147
  gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
147
- tr(' ',';').
148
- squeeze(';').
149
- gsub(';', '; '). #use '; ' as a separator (or EOL)
148
+ gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL)
150
149
  gsub(/;\s*$/,'') #remove trailing to keep examples below
151
150
 
152
151
  if val =~ /(boundary=(\S*))/i
@@ -156,9 +155,6 @@ module Mail
156
155
  end
157
156
 
158
157
  case
159
- when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;;+(.*)$/i
160
- # Handles 'text/plain;; format="flowed"' (double semi colon)
161
- "#{$1}/#{$2}; #{$3}"
162
158
  when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
163
159
  # Microsoft helper:
164
160
  # Handles 'type/subtype;ISO-8559-1'
@@ -185,7 +181,7 @@ module Mail
185
181
  when val =~ /^\s*$/
186
182
  'text/plain'
187
183
  else
188
- ''
184
+ val
189
185
  end
190
186
  end
191
187
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Date Field
4
5
  #
@@ -33,12 +34,11 @@ module Mail
33
34
 
34
35
  def initialize(value = nil, charset = 'utf-8')
35
36
  self.charset = charset
36
- if value.blank?
37
+ if Utilities.blank?(value)
37
38
  value = ::DateTime.now.strftime('%a, %d %b %Y %H:%M:%S %z')
38
39
  else
39
- value = strip_field(FIELD_NAME, value)
40
- value.to_s.gsub!(/\(.*?\)/, '')
41
- value = ::DateTime.parse(value.to_s.squeeze(" ")).strftime('%a, %d %b %Y %H:%M:%S %z')
40
+ value = value.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
41
+ value = ::DateTime.parse(value).strftime('%a, %d %b %Y %H:%M:%S %z')
42
42
  end
43
43
  super(CAPITALIZED_FIELD, value, charset)
44
44
  rescue ArgumentError => e
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = From Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = In-Reply-To Field
4
5
  #
@@ -39,7 +40,7 @@ module Mail
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
42
  value = value.join("\r\n\s") if value.is_a?(Array)
42
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
43
+ super(CAPITALIZED_FIELD, value, charset)
43
44
  self.parse
44
45
  self
45
46
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # keywords = "Keywords:" phrase *("," phrase) CRLF
4
5
  module Mail
@@ -9,13 +10,12 @@ module Mail
9
10
 
10
11
  def initialize(value = nil, charset = 'utf-8')
11
12
  self.charset = charset
12
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
13
- self.parse
13
+ super(CAPITALIZED_FIELD, value, charset)
14
14
  self
15
15
  end
16
16
 
17
17
  def parse(val = value)
18
- unless val.blank?
18
+ unless Utilities.blank?(val)
19
19
  @phrase_list ||= PhraseList.new(value)
20
20
  end
21
21
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Message-ID Field
4
5
  #
@@ -41,11 +42,11 @@ module Mail
41
42
  def initialize(value = nil, charset = 'utf-8')
42
43
  self.charset = charset
43
44
  @uniq = 1
44
- if value.blank?
45
+ if Utilities.blank?(value)
45
46
  self.name = CAPITALIZED_FIELD
46
47
  self.value = generate_message_id
47
48
  else
48
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
49
+ super(CAPITALIZED_FIELD, value, charset)
49
50
  end
50
51
  self.parse
51
52
  self
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  #
4
5
  #
@@ -10,17 +11,17 @@ module Mail
10
11
 
11
12
  def initialize(value = nil, charset = 'utf-8')
12
13
  self.charset = charset
13
- if value.blank?
14
+ if Utilities.blank?(value)
14
15
  value = '1.0'
15
16
  end
16
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
17
+ super(CAPITALIZED_FIELD, value, charset)
17
18
  self.parse
18
19
  self
19
20
 
20
21
  end
21
22
 
22
23
  def parse(val = value)
23
- unless val.blank?
24
+ unless Utilities.blank?(val)
24
25
  @element = Mail::MimeVersionElement.new(val)
25
26
  end
26
27
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # The field names of any optional-field MUST NOT be identical to any
4
5
  # field name specified elsewhere in this standard.
@@ -8,6 +9,9 @@ require 'mail/fields/unstructured_field'
8
9
 
9
10
  module Mail
10
11
  class OptionalField < UnstructuredField
11
-
12
+ private
13
+ def do_encode
14
+ "#{wrapped_value}\r\n"
15
+ end
12
16
  end
13
17
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # trace = [return]
4
5
  # 1*received
@@ -27,14 +28,14 @@ module Mail
27
28
 
28
29
  def initialize(value = nil, charset = 'utf-8')
29
30
  self.charset = charset
30
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
31
+ super(CAPITALIZED_FIELD, value, charset)
31
32
  self.parse
32
33
  self
33
34
 
34
35
  end
35
36
 
36
37
  def parse(val = value)
37
- unless val.blank?
38
+ unless Utilities.blank?(val)
38
39
  @element = Mail::ReceivedElement.new(val)
39
40
  end
40
41
  end
@@ -56,7 +57,7 @@ module Mail
56
57
  end
57
58
 
58
59
  def encoded
59
- if value.blank?
60
+ if Utilities.blank?(value)
60
61
  "#{CAPITALIZED_FIELD}: \r\n"
61
62
  else
62
63
  "#{CAPITALIZED_FIELD}: #{info}; #{formatted_date}\r\n"
@@ -64,7 +65,7 @@ module Mail
64
65
  end
65
66
 
66
67
  def decoded
67
- if value.blank?
68
+ if Utilities.blank?(value)
68
69
  ""
69
70
  else
70
71
  "#{info}; #{formatted_date}"
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = References Field
4
5
  #
@@ -39,7 +40,7 @@ module Mail
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
42
  value = value.join("\r\n\s") if value.is_a?(Array)
42
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
43
+ super(CAPITALIZED_FIELD, value, charset)
43
44
  self.parse
44
45
  self
45
46
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Reply-To Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Resent-Bcc Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Resent-Cc Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # resent-date = "Resent-Date:" date-time CRLF
4
5
  require 'mail/fields/common/common_date'
@@ -13,10 +14,9 @@ module Mail
13
14
 
14
15
  def initialize(value = nil, charset = 'utf-8')
15
16
  self.charset = charset
16
- if value.blank?
17
+ if Utilities.blank?(value)
17
18
  value = ::DateTime.now.strftime('%a, %d %b %Y %H:%M:%S %z')
18
19
  else
19
- value = strip_field(FIELD_NAME, value)
20
20
  value = ::DateTime.parse(value.to_s).strftime('%a, %d %b %Y %H:%M:%S %z')
21
21
  end
22
22
  super(CAPITALIZED_FIELD, value, charset)
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Resent-From Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # resent-msg-id = "Resent-Message-ID:" msg-id CRLF
4
5
  require 'mail/fields/common/common_message_id'
@@ -13,7 +14,7 @@ module Mail
13
14
 
14
15
  def initialize(value = nil, charset = 'utf-8')
15
16
  self.charset = charset
16
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
17
+ super(CAPITALIZED_FIELD, value, charset)
17
18
  self.parse
18
19
  self
19
20
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Resent-Sender Field
4
5
  #
@@ -37,8 +38,7 @@ module Mail
37
38
 
38
39
  def initialize(value = nil, charset = 'utf-8')
39
40
  self.charset = charset
40
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
41
- self.parse
41
+ super(CAPITALIZED_FIELD, value, charset)
42
42
  self
43
43
  end
44
44
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Resent-To Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # 4.4.3. REPLY-TO / RESENT-REPLY-TO
4
5
  #
@@ -40,8 +41,7 @@ module Mail
40
41
  def initialize(value = nil, charset = 'utf-8')
41
42
  value = nil if value == '<>'
42
43
  self.charset = charset
43
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
44
- self.parse
44
+ super(CAPITALIZED_FIELD, value, charset)
45
45
  self
46
46
  end
47
47
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = Sender Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  require 'mail/fields/common/common_field'
3
4
 
4
5
  module Mail
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # subject = "Subject:" unstructured CRLF
4
5
  module Mail
@@ -9,7 +10,7 @@ module Mail
9
10
 
10
11
  def initialize(value = nil, charset = 'utf-8')
11
12
  self.charset = charset
12
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
13
+ super(CAPITALIZED_FIELD, value, charset)
13
14
  end
14
15
 
15
16
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # = To Field
4
5
  #
@@ -38,8 +39,7 @@ module Mail
38
39
 
39
40
  def initialize(value = nil, charset = 'utf-8')
40
41
  self.charset = charset
41
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
- self.parse
42
+ super(CAPITALIZED_FIELD, value, charset)
43
43
  self
44
44
  end
45
45
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  require 'mail/fields/common/common_field'
3
4
 
4
5
  module Mail
@@ -31,6 +32,12 @@ module Mail
31
32
  else
32
33
  # Ensure we are dealing with a string
33
34
  value = value.to_s
35
+
36
+ # Mark UTF-8 strings parsed from ASCII-8BIT
37
+ if value.respond_to?(:force_encoding) && value.encoding == Encoding::ASCII_8BIT
38
+ utf8 = value.dup.force_encoding(Encoding::UTF_8)
39
+ value = utf8 if utf8.valid_encoding?
40
+ end
34
41
  end
35
42
 
36
43
  if charset
@@ -66,11 +73,15 @@ module Mail
66
73
  private
67
74
 
68
75
  def do_encode
69
- value.nil? ? '' : "#{wrapped_value}\r\n"
76
+ if value && !value.empty?
77
+ "#{wrapped_value}\r\n"
78
+ else
79
+ ''
80
+ end
70
81
  end
71
82
 
72
83
  def do_decode
73
- value.blank? ? nil : Encodings.decode_encode(value, :decode)
84
+ Utilities.blank?(value) ? nil : Encodings.decode_encode(value, :decode)
74
85
  end
75
86
 
76
87
  # 2.2.3. Long Header Fields
@@ -120,16 +131,16 @@ module Mail
120
131
  def fold(prepend = 0) # :nodoc:
121
132
  encoding = normalized_encoding
122
133
  decoded_string = decoded.to_s
123
- should_encode = decoded_string.not_ascii_only?
134
+ should_encode = !decoded_string.ascii_only?
124
135
  if should_encode
125
136
  first = true
126
137
  words = decoded_string.split(/[ \t]/).map do |word|
127
138
  if first
128
139
  first = !first
129
140
  else
130
- word = " " << word
141
+ word = " #{word}"
131
142
  end
132
- if word.not_ascii_only?
143
+ if !word.ascii_only?
133
144
  word
134
145
  else
135
146
  word.scan(/.{7}|.+$/)
@@ -143,11 +154,18 @@ module Mail
143
154
  while !words.empty?
144
155
  limit = 78 - prepend
145
156
  limit = limit - 7 - encoding.length if should_encode
146
- line = ""
157
+ line = String.new
147
158
  first_word = true
148
159
  while !words.empty?
149
160
  break unless word = words.first.dup
150
- word.encode!(charset) if charset && word.respond_to?(:encode!)
161
+
162
+ # Convert on 1.9+ only since we aren't sure of the current
163
+ # charset encoding on 1.8. We'd need to track internal/external
164
+ # charset on each field.
165
+ if charset && word.respond_to?(:encoding)
166
+ word = Encodings.transcode_charset(word, word.encoding, charset)
167
+ end
168
+
151
169
  word = encode(word) if should_encode
152
170
  word = encode_crlf(word)
153
171
  # Skip to next line if we're going to go past the limit
data/lib/mail/fields.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Mail
2
3
  register_autoload :UnstructuredField, 'mail/fields/unstructured_field'
3
4
  register_autoload :StructuredField, 'mail/fields/structured_field'
data/lib/mail/header.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  module Mail
3
4
 
4
5
  # Provides access to a header object.
@@ -49,13 +50,14 @@ module Mail
49
50
  # me the example so we can fix it.
50
51
  def initialize(header_text = nil, charset = nil)
51
52
  @charset = charset
52
- self.raw_source = header_text.to_crlf.lstrip
53
+ self.raw_source = header_text
53
54
  split_header if header_text
54
55
  end
55
56
 
56
57
  def initialize_copy(original)
57
58
  super
58
59
  @fields = @fields.dup
60
+ @fields.map!(&:dup)
59
61
  end
60
62
 
61
63
  # The preserved raw source of the header as you passed it in, untouched
@@ -91,14 +93,15 @@ module Mail
91
93
  # h.fields = ['From: mikel@me.com', 'To: bob@you.com']
92
94
  def fields=(unfolded_fields)
93
95
  @fields = Mail::FieldList.new
94
- warn "Warning: more than #{self.class.maximum_amount} header fields only using the first #{self.class.maximum_amount}" if unfolded_fields.length > self.class.maximum_amount
96
+ Kernel.warn "WARNING: More than #{self.class.maximum_amount} header fields; only using the first #{self.class.maximum_amount} and ignoring the rest" if unfolded_fields.length > self.class.maximum_amount
95
97
  unfolded_fields[0..(self.class.maximum_amount-1)].each do |field|
96
98
 
97
- field = Field.new(field, nil, charset)
98
- if limited_field?(field.name) && (selected = select_field_for(field.name)) && selected.any?
99
- selected.first.update(field.name, field.value)
100
- else
101
- @fields << field
99
+ if field = Field.parse(field, charset)
100
+ if limited_field?(field.name) && (selected = select_field_for(field.name)) && selected.any?
101
+ selected.first.update(field.name, field.value)
102
+ else
103
+ @fields << field
104
+ end
102
105
  end
103
106
  end
104
107
 
@@ -136,7 +139,7 @@ module Mail
136
139
  case
137
140
  when selected.length > 1
138
141
  selected.map { |f| f }
139
- when !selected.blank?
142
+ when !Utilities.blank?(selected)
140
143
  selected.first
141
144
  else
142
145
  nil
@@ -166,11 +169,11 @@ module Mail
166
169
 
167
170
  case
168
171
  # User wants to delete the field
169
- when !selected.blank? && value == nil
172
+ when !Utilities.blank?(selected) && value == nil
170
173
  fields.delete_if { |f| selected.include?(f) }
171
174
 
172
175
  # User wants to change the field
173
- when !selected.blank? && limited_field?(fn)
176
+ when !Utilities.blank?(selected) && limited_field?(fn)
174
177
  selected.first.update(fn, value)
175
178
 
176
179
  # User wants to create the field
@@ -204,7 +207,7 @@ module Mail
204
207
  content-id content-disposition content-location]
205
208
 
206
209
  def encoded
207
- buffer = ''
210
+ buffer = String.new
208
211
  buffer.force_encoding('us-ascii') if buffer.respond_to?(:force_encoding)
209
212
  fields.each do |field|
210
213
  buffer << field.encoded
@@ -247,7 +250,7 @@ module Mail
247
250
  private
248
251
 
249
252
  def raw_source=(val)
250
- @raw_source = val
253
+ @raw_source = ::Mail::Utilities.to_crlf(val).lstrip
251
254
  end
252
255
 
253
256
  # Splits an unfolded and line break cleaned header into individual field
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  # This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
4
5
  # itself does not depend on ActiveSupport to avoid versioning conflicts
data/lib/mail/mail.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  module Mail
3
4
 
4
5
  # Allows you to create a new Mail::Message object.
@@ -89,19 +90,11 @@ module Mail
89
90
  # Each mail object inherits the default set in Mail.delivery_method, however, on
90
91
  # a per email basis, you can override the method:
91
92
  #
92
- # mail.delivery_method :sendmail
93
+ # mail.delivery_method :smtp
93
94
  #
94
95
  # Or you can override the method and pass in settings:
95
96
  #
96
- # mail.delivery_method :sendmail, { :address => 'some.host' }
97
- #
98
- # You can also just modify the settings:
99
- #
100
- # mail.delivery_settings = { :address => 'some.host' }
101
- #
102
- # The passed in hash is just merged against the defaults with +merge!+ and the result
103
- # assigned the mail object. So the above example will change only the :address value
104
- # of the global smtp_settings to be 'some.host', keeping all other values
97
+ # mail.delivery_method :smtp, :address => 'some.host'
105
98
  def self.defaults(&block)
106
99
  Configuration.instance.instance_eval(&block)
107
100
  end