mail 1.1.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mail might be problematic. Click here for more details.

Files changed (50) hide show
  1. data/CHANGELOG.rdoc +14 -1
  2. data/README.rdoc +37 -13
  3. data/lib/mail/configuration.rb +4 -0
  4. data/lib/mail/elements/address.rb +11 -0
  5. data/lib/mail/encodings/base64.rb +1 -0
  6. data/lib/mail/encodings/encodings.rb +133 -6
  7. data/lib/mail/encodings/quoted_printable.rb +1 -1
  8. data/lib/mail/field.rb +34 -34
  9. data/lib/mail/fields/bcc_field.rb +10 -1
  10. data/lib/mail/fields/cc_field.rb +10 -1
  11. data/lib/mail/fields/comments_field.rb +2 -1
  12. data/lib/mail/fields/common/common_address.rb +25 -1
  13. data/lib/mail/fields/common/common_date.rb +8 -5
  14. data/lib/mail/fields/common/common_field.rb +2 -74
  15. data/lib/mail/fields/common/common_message_id.rb +10 -0
  16. data/lib/mail/fields/common/parameter_hash.rb +10 -0
  17. data/lib/mail/fields/content_description_field.rb +3 -2
  18. data/lib/mail/fields/content_disposition_field.rb +12 -2
  19. data/lib/mail/fields/content_id_field.rb +12 -2
  20. data/lib/mail/fields/content_location_field.rb +12 -2
  21. data/lib/mail/fields/content_transfer_encoding_field.rb +12 -2
  22. data/lib/mail/fields/content_type_field.rb +26 -5
  23. data/lib/mail/fields/date_field.rb +11 -2
  24. data/lib/mail/fields/from_field.rb +10 -1
  25. data/lib/mail/fields/in_reply_to_field.rb +10 -1
  26. data/lib/mail/fields/keywords_field.rb +10 -1
  27. data/lib/mail/fields/message_id_field.rb +11 -2
  28. data/lib/mail/fields/mime_version_field.rb +11 -2
  29. data/lib/mail/fields/received_field.rb +10 -1
  30. data/lib/mail/fields/references_field.rb +10 -1
  31. data/lib/mail/fields/reply_to_field.rb +10 -1
  32. data/lib/mail/fields/resent_bcc_field.rb +10 -1
  33. data/lib/mail/fields/resent_cc_field.rb +10 -1
  34. data/lib/mail/fields/resent_date_field.rb +10 -1
  35. data/lib/mail/fields/resent_from_field.rb +10 -1
  36. data/lib/mail/fields/resent_message_id_field.rb +10 -1
  37. data/lib/mail/fields/resent_sender_field.rb +10 -1
  38. data/lib/mail/fields/resent_to_field.rb +10 -1
  39. data/lib/mail/fields/return_path_field.rb +10 -1
  40. data/lib/mail/fields/sender_field.rb +10 -1
  41. data/lib/mail/fields/subject_field.rb +2 -1
  42. data/lib/mail/fields/to_field.rb +10 -1
  43. data/lib/mail/fields/unstructured_field.rb +82 -0
  44. data/lib/mail/header.rb +2 -2
  45. data/lib/mail/message.rb +25 -9
  46. data/lib/mail/utilities.rb +7 -1
  47. data/lib/mail/version.rb +2 -2
  48. data/lib/mail/version_specific/ruby_1_8.rb +30 -10
  49. data/lib/mail/version_specific/ruby_1_9.rb +30 -8
  50. metadata +1 -1
@@ -31,10 +31,19 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'from'
34
+ CAPITALIZED_FIELD = 'From'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
37
38
  end
38
39
 
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
46
+ end
47
+
39
48
  end
40
49
  end
@@ -33,9 +33,18 @@ module Mail
33
33
  include Mail::CommonMessageId
34
34
 
35
35
  FIELD_NAME = 'in-reply-to'
36
+ CAPITALIZED_FIELD = 'In-Reply-To'
36
37
 
37
38
  def initialize(*args)
38
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
39
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
40
+ end
41
+
42
+ def encoded
43
+ do_encode(CAPITALIZED_FIELD)
44
+ end
45
+
46
+ def decoded
47
+ do_decode
39
48
  end
40
49
 
41
50
  end
@@ -5,9 +5,10 @@ module Mail
5
5
  class KeywordsField < StructuredField
6
6
 
7
7
  FIELD_NAME = 'keywords'
8
+ CAPITALIZED_FIELD = 'Keywords'
8
9
 
9
10
  def initialize(*args)
10
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
11
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
11
12
  end
12
13
 
13
14
  def phrase_list
@@ -18,5 +19,13 @@ module Mail
18
19
  phrase_list.phrases
19
20
  end
20
21
 
22
+ def encoded
23
+ "#{CAPITALIZED_FIELD}: #{keywords.join(', ')}\r\n"
24
+ end
25
+
26
+ def decoded
27
+ keywords.join(', ')
28
+ end
29
+
21
30
  end
22
31
  end
@@ -35,15 +35,16 @@ module Mail
35
35
  include Mail::CommonMessageId
36
36
 
37
37
  FIELD_NAME = 'message-id'
38
+ CAPITALIZED_FIELD = 'Message-ID'
38
39
 
39
40
  def initialize(*args)
40
41
  @uniq = 1
41
42
  if args.last.blank?
42
- self.name = FIELD_NAME
43
+ self.name = CAPITALIZED_FIELD
43
44
  self.value = generate_message_id
44
45
  self
45
46
  else
46
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
47
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
47
48
  end
48
49
  end
49
50
 
@@ -59,6 +60,14 @@ module Mail
59
60
  "<#{message_id}>"
60
61
  end
61
62
 
63
+ def encoded
64
+ do_encode(CAPITALIZED_FIELD)
65
+ end
66
+
67
+ def decoded
68
+ do_decode
69
+ end
70
+
62
71
  private
63
72
 
64
73
  def generate_message_id
@@ -6,14 +6,15 @@ module Mail
6
6
  class MimeVersionField < StructuredField
7
7
 
8
8
  FIELD_NAME = 'mime-version'
9
+ CAPITALIZED_FIELD = 'Mime-Version'
9
10
 
10
11
  def initialize(*args)
11
12
  if args.last.blank?
12
- self.name = FIELD_NAME
13
+ self.name = CAPITALIZED_FIELD
13
14
  self.value = '1.0'
14
15
  self
15
16
  else
16
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
17
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
17
18
  end
18
19
  end
19
20
 
@@ -38,5 +39,13 @@ module Mail
38
39
  element.minor.to_i
39
40
  end
40
41
 
42
+ def encoded
43
+ "#{CAPITALIZED_FIELD}: #{value}\r\n"
44
+ end
45
+
46
+ def decoded
47
+ value
48
+ end
49
+
41
50
  end
42
51
  end
@@ -23,9 +23,10 @@ module Mail
23
23
  class ReceivedField < StructuredField
24
24
 
25
25
  FIELD_NAME = 'received'
26
+ CAPITALIZED_FIELD = 'Received'
26
27
 
27
28
  def initialize(*args)
28
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
29
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
29
30
  end
30
31
 
31
32
  def tree
@@ -45,5 +46,13 @@ module Mail
45
46
  element.info
46
47
  end
47
48
 
49
+ def encoded
50
+ "#{CAPITALIZED_FIELD}: #{value}"
51
+ end
52
+
53
+ def decoded
54
+ value
55
+ end
56
+
48
57
  end
49
58
  end
@@ -33,9 +33,18 @@ module Mail
33
33
  include CommonMessageId
34
34
 
35
35
  FIELD_NAME = 'references'
36
+ CAPITALIZED_FIELD = 'References'
36
37
 
37
38
  def initialize(*args)
38
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
39
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
40
+ end
41
+
42
+ def encoded
43
+ do_encode(CAPITALIZED_FIELD)
44
+ end
45
+
46
+ def decoded
47
+ do_decode
39
48
  end
40
49
 
41
50
  end
@@ -31,9 +31,18 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'reply-to'
34
+ CAPITALIZED_FIELD = 'Reply-To'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
38
+ end
39
+
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
37
46
  end
38
47
 
39
48
  end
@@ -31,9 +31,18 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'resent-bcc'
34
+ CAPITALIZED_FIELD = 'Resent-Bcc'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
38
+ end
39
+
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
37
46
  end
38
47
 
39
48
  end
@@ -31,9 +31,18 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'resent-cc'
34
+ CAPITALIZED_FIELD = 'Resent-Cc'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
38
+ end
39
+
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
37
46
  end
38
47
 
39
48
  end
@@ -7,9 +7,18 @@ module Mail
7
7
  include Mail::CommonDate
8
8
 
9
9
  FIELD_NAME = 'resent-date'
10
+ CAPITALIZED_FIELD = 'Resent-Date'
10
11
 
11
12
  def initialize(*args)
12
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
13
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
14
+ end
15
+
16
+ def encoded
17
+ do_encode(CAPITALIZED_FIELD)
18
+ end
19
+
20
+ def decoded
21
+ do_decode
13
22
  end
14
23
 
15
24
  end
@@ -31,9 +31,18 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'resent-from'
34
+ CAPITALIZED_FIELD = 'Resent-From'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
38
+ end
39
+
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
37
46
  end
38
47
 
39
48
  end
@@ -7,14 +7,23 @@ module Mail
7
7
  include CommonMessageId
8
8
 
9
9
  FIELD_NAME = 'resent-message-id'
10
+ CAPITALIZED_FIELD = 'Resent-Message-ID'
10
11
 
11
12
  def initialize(*args)
12
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
13
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
13
14
  end
14
15
 
15
16
  def name
16
17
  'Resent-Message-ID'
17
18
  end
18
19
 
20
+ def encoded
21
+ do_encode(CAPITALIZED_FIELD)
22
+ end
23
+
24
+ def decoded
25
+ do_decode
26
+ end
27
+
19
28
  end
20
29
  end
@@ -31,9 +31,10 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'resent-sender'
34
+ CAPITALIZED_FIELD = 'Resent-Sender'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
37
38
  end
38
39
 
39
40
  def addresses
@@ -44,5 +45,13 @@ module Mail
44
45
  result = tree.addresses.first
45
46
  end
46
47
 
48
+ def encoded
49
+ do_encode(CAPITALIZED_FIELD)
50
+ end
51
+
52
+ def decoded
53
+ do_decode
54
+ end
55
+
47
56
  end
48
57
  end
@@ -31,9 +31,18 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'resent-to'
34
+ CAPITALIZED_FIELD = 'Resent-To'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
38
+ end
39
+
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
37
46
  end
38
47
 
39
48
  end
@@ -25,9 +25,18 @@ module Mail
25
25
  include CommonAddress
26
26
 
27
27
  FIELD_NAME = 'return-path'
28
+ CAPITALIZED_FIELD = 'Return-Path'
28
29
 
29
30
  def initialize(*args)
30
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
31
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
32
+ end
33
+
34
+ def encoded
35
+ do_encode(CAPITALIZED_FIELD)
36
+ end
37
+
38
+ def decoded
39
+ do_decode
31
40
  end
32
41
 
33
42
  end
@@ -31,9 +31,10 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'sender'
34
+ CAPITALIZED_FIELD = 'Sender'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
37
38
  end
38
39
 
39
40
  def addresses
@@ -44,5 +45,13 @@ module Mail
44
45
  result = tree.addresses.first
45
46
  end
46
47
 
48
+ def encoded
49
+ do_encode(CAPITALIZED_FIELD)
50
+ end
51
+
52
+ def decoded
53
+ do_decode
54
+ end
55
+
47
56
  end
48
57
  end
@@ -5,9 +5,10 @@ module Mail
5
5
  class SubjectField < UnstructuredField
6
6
 
7
7
  FIELD_NAME = 'subject'
8
+ CAPITALIZED_FIELD = "Subject"
8
9
 
9
10
  def initialize(*args)
10
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
11
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
11
12
  end
12
13
 
13
14
  end
@@ -31,9 +31,18 @@ module Mail
31
31
  include Mail::CommonAddress
32
32
 
33
33
  FIELD_NAME = 'to'
34
+ CAPITALIZED_FIELD = 'To'
34
35
 
35
36
  def initialize(*args)
36
- super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
38
+ end
39
+
40
+ def encoded
41
+ do_encode(CAPITALIZED_FIELD)
42
+ end
43
+
44
+ def decoded
45
+ do_decode
37
46
  end
38
47
 
39
48
  end
@@ -22,6 +22,88 @@ module Mail
22
22
  self.value = args.last
23
23
  self
24
24
  end
25
+
26
+ def encoded
27
+ do_encode(self.name)
28
+ end
29
+
30
+ def decoded
31
+ do_decode
32
+ end
33
+
34
+ private
35
+
36
+ def do_encode(name)
37
+ value.nil? ? '' : "#{wrapped_value}\r\n"
38
+ end
39
+
40
+ def do_decode
41
+ value.blank? ? nil : value
42
+ end
43
+
44
+ # 2.2.3. Long Header Fields
45
+ #
46
+ # Each header field is logically a single line of characters comprising
47
+ # the field name, the colon, and the field body. For convenience
48
+ # however, and to deal with the 998/78 character limitations per line,
49
+ # the field body portion of a header field can be split into a multiple
50
+ # line representation; this is called "folding". The general rule is
51
+ # that wherever this standard allows for folding white space (not
52
+ # simply WSP characters), a CRLF may be inserted before any WSP. For
53
+ # example, the header field:
54
+ #
55
+ # Subject: This is a test
56
+ #
57
+ # can be represented as:
58
+ #
59
+ # Subject: This
60
+ # is a test
61
+ #
62
+ # Note: Though structured field bodies are defined in such a way that
63
+ # folding can take place between many of the lexical tokens (and even
64
+ # within some of the lexical tokens), folding SHOULD be limited to
65
+ # placing the CRLF at higher-level syntactic breaks. For instance, if
66
+ # a field body is defined as comma-separated values, it is recommended
67
+ # that folding occur after the comma separating the structured items in
68
+ # preference to other places where the field could be folded, even if
69
+ # it is allowed elsewhere.
70
+ def wrapped_value # :nodoc:
71
+ case
72
+ when decoded.to_s.ascii_only? && field_length <= 78
73
+ "#{name}: #{value}"
74
+ when field_length <= 40 # Allow for =?ISO-8859-1?B?=...=
75
+ "#{name}: #{encode(value)}"
76
+ else
77
+ @folded_line = []
78
+ @unfolded_line = value.clone
79
+ fold("#{name}: ".length)
80
+ folded = @folded_line.compact.join("\r\n\t")
81
+ "#{name}: #{folded}"
82
+ end
83
+ end
84
+
85
+ def fold(prepend = 0) # :nodoc:
86
+ # Get the last whitespace character, OR we'll just choose
87
+ # 78 if there is no whitespace
88
+ @unfolded_line.ascii_only? ? (limit = 78 - prepend) : (limit = 40 - prepend)
89
+ wspp = @unfolded_line.slice(0..limit) =~ /[ \t][^ \T]*$/ || limit
90
+ wspp = limit if wspp == 0
91
+ @folded_line << encode(@unfolded_line.slice!(0...wspp))
92
+ if @unfolded_line.length > limit
93
+ fold
94
+ else
95
+ @folded_line << encode(@unfolded_line)
96
+ end
97
+ end
98
+
99
+ def encode(value)
100
+ if value.ascii_only?
101
+ value
102
+ else
103
+ RUBY_VERSION < '1.9' ? encoding = $KCODE : encoding = @value.encoding
104
+ Encodings.b_value_encode(value, encoding)
105
+ end
106
+ end
25
107
 
26
108
  end
27
109
  end