mail 2.4.4 → 2.5.5

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 (82) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +140 -1
  3. data/CONTRIBUTING.md +4 -4
  4. data/Gemfile +14 -8
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +24 -23
  7. data/Rakefile +3 -22
  8. data/lib/VERSION +2 -2
  9. data/lib/load_parsers.rb +35 -0
  10. data/lib/mail/attachments_list.rb +2 -2
  11. data/lib/mail/body.rb +5 -5
  12. data/lib/mail/check_delivery_params.rb +57 -0
  13. data/lib/mail/configuration.rb +1 -1
  14. data/lib/mail/core_extensions/nil.rb +4 -2
  15. data/lib/mail/core_extensions/object.rb +8 -8
  16. data/lib/mail/core_extensions/smtp.rb +12 -13
  17. data/lib/mail/core_extensions/string.rb +4 -4
  18. data/lib/mail/elements/address.rb +13 -5
  19. data/lib/mail/elements/envelope_from_element.rb +15 -2
  20. data/lib/mail/elements.rb +12 -12
  21. data/lib/mail/encodings/quoted_printable.rb +4 -3
  22. data/lib/mail/encodings.rb +66 -35
  23. data/lib/mail/field.rb +76 -99
  24. data/lib/mail/fields/bcc_field.rb +2 -2
  25. data/lib/mail/fields/cc_field.rb +2 -2
  26. data/lib/mail/fields/comments_field.rb +1 -1
  27. data/lib/mail/fields/common/common_address.rb +19 -4
  28. data/lib/mail/fields/common/common_field.rb +8 -2
  29. data/lib/mail/fields/common/common_message_id.rb +9 -5
  30. data/lib/mail/fields/content_disposition_field.rb +1 -0
  31. data/lib/mail/fields/content_id_field.rb +1 -2
  32. data/lib/mail/fields/content_transfer_encoding_field.rb +2 -2
  33. data/lib/mail/fields/content_type_field.rb +5 -2
  34. data/lib/mail/fields/date_field.rb +14 -14
  35. data/lib/mail/fields/from_field.rb +2 -2
  36. data/lib/mail/fields/in_reply_to_field.rb +2 -1
  37. data/lib/mail/fields/keywords_field.rb +1 -1
  38. data/lib/mail/fields/message_id_field.rb +2 -3
  39. data/lib/mail/fields/references_field.rb +2 -1
  40. data/lib/mail/fields/reply_to_field.rb +2 -2
  41. data/lib/mail/fields/resent_bcc_field.rb +2 -2
  42. data/lib/mail/fields/resent_cc_field.rb +2 -2
  43. data/lib/mail/fields/resent_from_field.rb +2 -2
  44. data/lib/mail/fields/resent_sender_field.rb +2 -2
  45. data/lib/mail/fields/resent_to_field.rb +2 -2
  46. data/lib/mail/fields/sender_field.rb +7 -7
  47. data/lib/mail/fields/to_field.rb +2 -2
  48. data/lib/mail/fields/unstructured_field.rb +34 -27
  49. data/lib/mail/fields.rb +32 -32
  50. data/lib/mail/header.rb +37 -14
  51. data/lib/mail/message.rb +140 -45
  52. data/lib/mail/multibyte/chars.rb +4 -4
  53. data/lib/mail/multibyte/unicode.rb +8 -0
  54. data/lib/mail/network/delivery_methods/exim.rb +6 -11
  55. data/lib/mail/network/delivery_methods/file_delivery.rb +7 -6
  56. data/lib/mail/network/delivery_methods/sendmail.rb +40 -11
  57. data/lib/mail/network/delivery_methods/smtp.rb +33 -47
  58. data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -24
  59. data/lib/mail/network/delivery_methods/test_mailer.rb +9 -8
  60. data/lib/mail/network/retriever_methods/imap.rb +14 -6
  61. data/lib/mail/network/retriever_methods/pop3.rb +2 -2
  62. data/lib/mail/network/retriever_methods/test_retriever.rb +11 -15
  63. data/lib/mail/network.rb +9 -9
  64. data/lib/mail/parsers/content_transfer_encoding.rb +81 -42
  65. data/lib/mail/parsers/content_transfer_encoding.treetop +4 -6
  66. data/lib/mail/parsers/content_type.rb +16 -12
  67. data/lib/mail/parsers/content_type.treetop +2 -2
  68. data/lib/mail/parsers/rfc2045.rb +12 -55
  69. data/lib/mail/parsers/rfc2045.treetop +1 -2
  70. data/lib/mail/parsers/rfc2822.rb +127 -71
  71. data/lib/mail/parsers/rfc2822.treetop +22 -24
  72. data/lib/mail/part.rb +6 -2
  73. data/lib/mail/parts_list.rb +1 -1
  74. data/lib/mail/patterns.rb +1 -1
  75. data/lib/mail/utilities.rb +25 -17
  76. data/lib/mail/values/unicode_tables.dat +0 -0
  77. data/lib/mail/version_specific/ruby_1_8.rb +23 -2
  78. data/lib/mail/version_specific/ruby_1_9.rb +55 -21
  79. data/lib/mail.rb +18 -18
  80. metadata +89 -37
  81. data/Gemfile.lock +0 -36
  82. data/lib/mail/core_extensions/shell_escape.rb +0 -56
@@ -22,7 +22,7 @@ module Mail
22
22
  end
23
23
 
24
24
  def to_s
25
- decoded
25
+ decoded.to_s
26
26
  end
27
27
 
28
28
  def default
@@ -34,7 +34,7 @@ module Mail
34
34
  end
35
35
 
36
36
  def responsible_for?( val )
37
- name.to_s.downcase == val.to_s.downcase
37
+ name.to_s.casecmp(val.to_s) == 0
38
38
  end
39
39
 
40
40
  private
@@ -47,5 +47,11 @@ module Mail
47
47
  end
48
48
  end
49
49
 
50
+ FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
51
+ def ensure_filename_quoted(value)
52
+ if value.is_a?(String)
53
+ value.sub! FILENAME_RE, '\1="\2"'
54
+ end
55
+ end
50
56
  end
51
57
  end
@@ -31,14 +31,18 @@ module Mail
31
31
  end
32
32
 
33
33
  private
34
-
34
+
35
35
  def do_encode(field_name)
36
- %Q{#{field_name}: #{do_decode}\r\n}
36
+ %Q{#{field_name}: #{formated_message_ids("\r\n ")}\r\n}
37
37
  end
38
-
38
+
39
39
  def do_decode
40
- "#{message_ids.map { |m| "<#{m}>" }.join(' ')}" if message_ids
40
+ formated_message_ids(' ')
41
41
  end
42
-
42
+
43
+ def formated_message_ids(join)
44
+ message_ids.map{ |m| "<#{m}>" }.join(join) if message_ids
45
+ end
46
+
43
47
  end
44
48
  end
@@ -9,6 +9,7 @@ module Mail
9
9
 
10
10
  def initialize(value = nil, charset = 'utf-8')
11
11
  self.charset = charset
12
+ ensure_filename_quoted(value)
12
13
  super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
13
14
  self.parse
14
15
  self
@@ -55,8 +55,7 @@ module Mail
55
55
  private
56
56
 
57
57
  def generate_content_id
58
- fqdn = ::Socket.gethostname
59
- "<#{Mail.random_tag}@#{fqdn}.mail>"
58
+ "<#{Mail.random_tag}@#{::Socket.gethostname}.mail>"
60
59
  end
61
60
 
62
61
  end
@@ -10,8 +10,8 @@ module Mail
10
10
 
11
11
  def initialize(value = nil, charset = 'utf-8')
12
12
  self.charset = charset
13
- value = '7bit' if value.to_s =~ /7-bit/i
14
- value = '8bit' if value.to_s =~ /8-bit/i
13
+ value = '7bit' if value.to_s =~ /7-?bits?/i
14
+ value = '8bit' if value.to_s =~ /8-?bits?/i
15
15
  super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
16
16
  self.parse
17
17
  self
@@ -19,6 +19,7 @@ module Mail
19
19
  @parameters = nil
20
20
  value = strip_field(FIELD_NAME, value)
21
21
  end
22
+ ensure_filename_quoted(value)
22
23
  super(CAPITALIZED_FIELD, value, charset)
23
24
  self.parse
24
25
  self
@@ -141,7 +142,9 @@ module Mail
141
142
  def sanatize( val )
142
143
 
143
144
  # TODO: check if there are cases where whitespace is not a separator
144
- val = val.tr(' ',';').
145
+ val = val.
146
+ gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
147
+ tr(' ',';').
145
148
  squeeze(';').
146
149
  gsub(';', '; '). #use '; ' as a separator (or EOL)
147
150
  gsub(/;\s*$/,'') #remove trailing to keep examples below
@@ -177,7 +180,7 @@ module Mail
177
180
  params = $2.to_s.split(/\s+/)
178
181
  params = params.map { |i| i.to_s.chomp.strip }
179
182
  params = params.map { |i| i.split(/\s*\=\s*/) }
180
- params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s)}" }.join('; ')
183
+ params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
181
184
  "#{type}; #{params}"
182
185
  when val =~ /^\s*$/
183
186
  'text/plain'
@@ -1,18 +1,18 @@
1
1
  # encoding: utf-8
2
- #
2
+ #
3
3
  # = Date Field
4
- #
4
+ #
5
5
  # The Date field inherits from StructuredField and handles the Date: header
6
6
  # field in the email.
7
- #
7
+ #
8
8
  # Sending date to a mail message will instantiate a Mail::Field object that
9
- # has a DateField as it's field type. This includes all Mail::CommonAddress
9
+ # has a DateField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance methods.
11
- #
11
+ #
12
12
  # There must be excatly one Date field in an RFC2822 email.
13
- #
13
+ #
14
14
  # == Examples:
15
- #
15
+ #
16
16
  # mail = Mail.new
17
17
  # mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
18
18
  # mail.date #=> #<DateTime: 211747170121/86400,-1/3,2299161>
@@ -20,17 +20,17 @@
20
20
  # mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
21
21
  # mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
22
22
  # mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
23
- #
23
+ #
24
24
  require 'mail/fields/common/common_date'
25
25
 
26
26
  module Mail
27
27
  class DateField < StructuredField
28
-
28
+
29
29
  include Mail::CommonDate
30
-
30
+
31
31
  FIELD_NAME = 'date'
32
32
  CAPITALIZED_FIELD = "Date"
33
-
33
+
34
34
  def initialize(value = nil, charset = 'utf-8')
35
35
  self.charset = charset
36
36
  if value.blank?
@@ -44,14 +44,14 @@ module Mail
44
44
  rescue ArgumentError => e
45
45
  raise e unless "invalid date"==e.message
46
46
  end
47
-
47
+
48
48
  def encoded
49
49
  do_encode(CAPITALIZED_FIELD)
50
50
  end
51
-
51
+
52
52
  def decoded
53
53
  do_decode
54
54
  end
55
-
55
+
56
56
  end
57
57
  end
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending from to a mail message will instantiate a Mail::Field object that
9
- # has a FromField as it's field type. This includes all Mail::CommonAddress
9
+ # has a FromField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one From field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.from #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
21
21
  # mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
22
22
  # mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # In-Reply-To: header field in the email.
7
7
  #
8
8
  # Sending in_reply_to to a mail message will instantiate a Mail::Field object that
9
- # has a InReplyToField as it's field type. This includes all Mail::CommonMessageId
9
+ # has a InReplyToField as its field type. This includes all Mail::CommonMessageId
10
10
  # module instance metods.
11
11
  #
12
12
  # Note that, the #message_ids method will return an array of message IDs without the
@@ -38,6 +38,7 @@ module Mail
38
38
 
39
39
  def initialize(value = nil, charset = 'utf-8')
40
40
  self.charset = charset
41
+ value = value.join("\r\n\s") if value.is_a?(Array)
41
42
  super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
43
  self.parse
43
44
  self
@@ -29,7 +29,7 @@ module Mail
29
29
  end
30
30
 
31
31
  def encoded
32
- "#{CAPITALIZED_FIELD}: #{keywords.join(', ')}\r\n"
32
+ "#{CAPITALIZED_FIELD}: #{keywords.join(",\r\n ")}\r\n"
33
33
  end
34
34
 
35
35
  def decoded
@@ -6,7 +6,7 @@
6
6
  # Message-ID: header field in the email.
7
7
  #
8
8
  # Sending message_id to a mail message will instantiate a Mail::Field object that
9
- # has a MessageIdField as it's field type. This includes all Mail::CommonMessageId
9
+ # has a MessageIdField as its field type. This includes all Mail::CommonMessageId
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one MessageId field can appear in a header, and syntactically it can only have
@@ -75,8 +75,7 @@ module Mail
75
75
  private
76
76
 
77
77
  def generate_message_id
78
- fqdn = ::Socket.gethostname
79
- "<#{Mail.random_tag}@#{fqdn}.mail>"
78
+ "<#{Mail.random_tag}@#{::Socket.gethostname}.mail>"
80
79
  end
81
80
 
82
81
  end
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending references to a mail message will instantiate a Mail::Field object that
9
- # has a ReferencesField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ReferencesField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Note that, the #message_ids method will return an array of message IDs without the
@@ -38,6 +38,7 @@ module Mail
38
38
 
39
39
  def initialize(value = nil, charset = 'utf-8')
40
40
  self.charset = charset
41
+ value = value.join("\r\n\s") if value.is_a?(Array)
41
42
  super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
42
43
  self.parse
43
44
  self
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending reply_to to a mail message will instantiate a Mail::Field object that
9
- # has a ReplyToField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ReplyToField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Reply-To field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.reply_to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.reply_to #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.reply_to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
21
21
  # mail['reply-to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
22
22
  # mail['Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # Resent-Bcc: header field in the email.
7
7
  #
8
8
  # Sending resent_bcc to a mail message will instantiate a Mail::Field object that
9
- # has a ResentBccField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentBccField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-Bcc field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_bcc #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
21
21
  # mail['resent-bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
22
22
  # mail['Resent-Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_cc to a mail message will instantiate a Mail::Field object that
9
- # has a ResentCcField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentCcField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-Cc field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_cc #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
21
21
  # mail['resent-cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
22
22
  # mail['Resent-Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_from to a mail message will instantiate a Mail::Field object that
9
- # has a ResentFromField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentFromField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-From field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_from #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
21
21
  # mail['resent-from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
22
22
  # mail['Resent-From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_sender to a mail message will instantiate a Mail::Field object that
9
- # has a ResentSenderField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentSenderField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-Sender field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_sender #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
19
+ # mail.resent_sender #=> ['mikel@test.lindsaar.net']
20
20
  # mail[:resent_sender] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
21
21
  # mail['resent-sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
22
22
  # mail['Resent-Sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_to to a mail message will instantiate a Mail::Field object that
9
- # has a ResentToField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentToField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-To field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_to #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
21
21
  # mail['resent-to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
22
22
  # mail['Resent-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending sender to a mail message will instantiate a Mail::Field object that
9
- # has a SenderField as it's field type. This includes all Mail::CommonAddress
9
+ # has a SenderField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Sender field can appear in a header, though it can have multiple
@@ -15,16 +15,16 @@
15
15
  # == Examples:
16
16
  #
17
17
  # mail = Mail.new
18
- # mail.sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.sender #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
18
+ # mail.sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>'
19
+ # mail.sender #=> 'mikel@test.lindsaar.net'
20
20
  # mail[:sender] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
21
21
  # mail['sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
22
22
  # mail['Sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
23
23
  #
24
- # mail[:sender].encoded #=> 'Sender: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
25
- # mail[:sender].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
26
- # mail[:sender].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
27
- # mail[:sender].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
24
+ # mail[:sender].encoded #=> "Sender: Mikel Lindsaar <mikel@test.lindsaar.net>\r\n"
25
+ # mail[:sender].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>'
26
+ # mail[:sender].addresses #=> ['mikel@test.lindsaar.net']
27
+ # mail[:sender].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>']
28
28
  #
29
29
  require 'mail/fields/common/common_address'
30
30
 
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending to to a mail message will instantiate a Mail::Field object that
9
- # has a ToField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ToField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one To field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.to #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
21
21
  # mail['to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
22
22
  # mail['To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
@@ -6,7 +6,7 @@ module Mail
6
6
  #
7
7
  # ===Per RFC 2822:
8
8
  # 2.2.1. Unstructured Header Field Bodies
9
- #
9
+ #
10
10
  # Some field bodies in this standard are defined simply as
11
11
  # "unstructured" (which is specified below as any US-ASCII characters,
12
12
  # except for CR and LF) with no further restrictions. These are
@@ -15,20 +15,29 @@ module Mail
15
15
  # with no further processing (except for header "folding" and
16
16
  # "unfolding" as described in section 2.2.3).
17
17
  class UnstructuredField
18
-
18
+
19
19
  include Mail::CommonField
20
20
  include Mail::Utilities
21
-
21
+
22
22
  attr_accessor :charset
23
23
  attr_reader :errors
24
-
24
+
25
25
  def initialize(name, value, charset = nil)
26
26
  @errors = []
27
+
28
+ if value.is_a?(Array)
29
+ # Probably has arrived here from a failed parse of an AddressList Field
30
+ value = value.join(', ')
31
+ else
32
+ # Ensure we are dealing with a string
33
+ value = value.to_s
34
+ end
35
+
27
36
  if charset
28
37
  self.charset = charset
29
38
  else
30
- if value.to_s.respond_to?(:encoding)
31
- self.charset = value.to_s.encoding
39
+ if value.respond_to?(:encoding)
40
+ self.charset = value.encoding
32
41
  else
33
42
  self.charset = $KCODE
34
43
  end
@@ -37,11 +46,11 @@ module Mail
37
46
  self.value = value
38
47
  self
39
48
  end
40
-
49
+
41
50
  def encoded
42
51
  do_encode
43
52
  end
44
-
53
+
45
54
  def decoded
46
55
  do_decode
47
56
  end
@@ -49,25 +58,23 @@ module Mail
49
58
  def default
50
59
  decoded
51
60
  end
52
-
61
+
53
62
  def parse # An unstructured field does not parse
54
63
  self
55
64
  end
56
65
 
57
66
  private
58
-
67
+
59
68
  def do_encode
60
69
  value.nil? ? '' : "#{wrapped_value}\r\n"
61
70
  end
62
-
71
+
63
72
  def do_decode
64
- result = value.blank? ? nil : Encodings.decode_encode(value, :decode)
65
- result.encode!(value.encoding || "UTF-8") if RUBY_VERSION >= '1.9' && !result.blank?
66
- result
73
+ value.blank? ? nil : Encodings.decode_encode(value, :decode)
67
74
  end
68
-
75
+
69
76
  # 2.2.3. Long Header Fields
70
- #
77
+ #
71
78
  # Each header field is logically a single line of characters comprising
72
79
  # the field name, the colon, and the field body. For convenience
73
80
  # however, and to deal with the 998/78 character limitations per line,
@@ -76,14 +83,14 @@ module Mail
76
83
  # that wherever this standard allows for folding white space (not
77
84
  # simply WSP characters), a CRLF may be inserted before any WSP. For
78
85
  # example, the header field:
79
- #
86
+ #
80
87
  # Subject: This is a test
81
- #
88
+ #
82
89
  # can be represented as:
83
- #
90
+ #
84
91
  # Subject: This
85
92
  # is a test
86
- #
93
+ #
87
94
  # Note: Though structured field bodies are defined in such a way that
88
95
  # folding can take place between many of the lexical tokens (and even
89
96
  # within some of the lexical tokens), folding SHOULD be limited to
@@ -95,9 +102,9 @@ module Mail
95
102
  def wrapped_value # :nodoc:
96
103
  wrap_lines(name, fold("#{name}: ".length))
97
104
  end
98
-
105
+
99
106
  # 6.2. Display of 'encoded-word's
100
- #
107
+ #
101
108
  # When displaying a particular header field that contains multiple
102
109
  # 'encoded-word's, any 'linear-white-space' that separates a pair of
103
110
  # adjacent 'encoded-word's is ignored. (This is to allow the use of
@@ -131,7 +138,7 @@ module Mail
131
138
  else
132
139
  words = decoded_string.split(/[ \t]/)
133
140
  end
134
-
141
+
135
142
  folded_lines = []
136
143
  while !words.empty?
137
144
  limit = 78 - prepend
@@ -139,13 +146,13 @@ module Mail
139
146
  line = ""
140
147
  while !words.empty?
141
148
  break unless word = words.first.dup
142
- word.encode!(charset) if defined?(Encoding) && charset
149
+ word.encode!(charset) if charset && word.respond_to?(:encode!)
143
150
  word = encode(word) if should_encode
144
151
  word = encode_crlf(word)
145
152
  # Skip to next line if we're going to go past the limit
146
153
  # Unless this is the first word, in which case we're going to add it anyway
147
154
  # Note: This means that a word that's longer than 998 characters is going to break the spec. Please fix if this is a problem for you.
148
- # (The fix, it seems, would be to use encoded-word encoding on it, because that way you can break it across multiple lines and
155
+ # (The fix, it seems, would be to use encoded-word encoding on it, because that way you can break it across multiple lines and
149
156
  # the linebreak will be ignored)
150
157
  break if !line.empty? && (line.length + word.length + 1 > limit)
151
158
  # Remove the word from the queue ...
@@ -153,7 +160,7 @@ module Mail
153
160
  # Add word separator
154
161
  line << " " unless (line.empty? || should_encode)
155
162
  # ... add it in encoded form to the current line
156
- line << word
163
+ line << word
157
164
  end
158
165
  # Encode the line if necessary
159
166
  line = "=?#{encoding}?Q?#{line}?=" if should_encode
@@ -163,7 +170,7 @@ module Mail
163
170
  end
164
171
  folded_lines
165
172
  end
166
-
173
+
167
174
  def encode(value)
168
175
  value = [value].pack("M").gsub("=\n", '')
169
176
  value.gsub!(/"/, '=22')