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.
- data/CHANGELOG.rdoc +14 -1
- data/README.rdoc +37 -13
- data/lib/mail/configuration.rb +4 -0
- data/lib/mail/elements/address.rb +11 -0
- data/lib/mail/encodings/base64.rb +1 -0
- data/lib/mail/encodings/encodings.rb +133 -6
- data/lib/mail/encodings/quoted_printable.rb +1 -1
- data/lib/mail/field.rb +34 -34
- data/lib/mail/fields/bcc_field.rb +10 -1
- data/lib/mail/fields/cc_field.rb +10 -1
- data/lib/mail/fields/comments_field.rb +2 -1
- data/lib/mail/fields/common/common_address.rb +25 -1
- data/lib/mail/fields/common/common_date.rb +8 -5
- data/lib/mail/fields/common/common_field.rb +2 -74
- data/lib/mail/fields/common/common_message_id.rb +10 -0
- data/lib/mail/fields/common/parameter_hash.rb +10 -0
- data/lib/mail/fields/content_description_field.rb +3 -2
- data/lib/mail/fields/content_disposition_field.rb +12 -2
- data/lib/mail/fields/content_id_field.rb +12 -2
- data/lib/mail/fields/content_location_field.rb +12 -2
- data/lib/mail/fields/content_transfer_encoding_field.rb +12 -2
- data/lib/mail/fields/content_type_field.rb +26 -5
- data/lib/mail/fields/date_field.rb +11 -2
- data/lib/mail/fields/from_field.rb +10 -1
- data/lib/mail/fields/in_reply_to_field.rb +10 -1
- data/lib/mail/fields/keywords_field.rb +10 -1
- data/lib/mail/fields/message_id_field.rb +11 -2
- data/lib/mail/fields/mime_version_field.rb +11 -2
- data/lib/mail/fields/received_field.rb +10 -1
- data/lib/mail/fields/references_field.rb +10 -1
- data/lib/mail/fields/reply_to_field.rb +10 -1
- data/lib/mail/fields/resent_bcc_field.rb +10 -1
- data/lib/mail/fields/resent_cc_field.rb +10 -1
- data/lib/mail/fields/resent_date_field.rb +10 -1
- data/lib/mail/fields/resent_from_field.rb +10 -1
- data/lib/mail/fields/resent_message_id_field.rb +10 -1
- data/lib/mail/fields/resent_sender_field.rb +10 -1
- data/lib/mail/fields/resent_to_field.rb +10 -1
- data/lib/mail/fields/return_path_field.rb +10 -1
- data/lib/mail/fields/sender_field.rb +10 -1
- data/lib/mail/fields/subject_field.rb +2 -1
- data/lib/mail/fields/to_field.rb +10 -1
- data/lib/mail/fields/unstructured_field.rb +82 -0
- data/lib/mail/header.rb +2 -2
- data/lib/mail/message.rb +25 -9
- data/lib/mail/utilities.rb +7 -1
- data/lib/mail/version.rb +2 -2
- data/lib/mail/version_specific/ruby_1_8.rb +30 -10
- data/lib/mail/version_specific/ruby_1_9.rb +30 -8
- 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(
|
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(
|
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(
|
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 =
|
43
|
+
self.name = CAPITALIZED_FIELD
|
43
44
|
self.value = generate_message_id
|
44
45
|
self
|
45
46
|
else
|
46
|
-
super(
|
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 =
|
13
|
+
self.name = CAPITALIZED_FIELD
|
13
14
|
self.value = '1.0'
|
14
15
|
self
|
15
16
|
else
|
16
|
-
super(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
11
|
+
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, args.last))
|
11
12
|
end
|
12
13
|
|
13
14
|
end
|
data/lib/mail/fields/to_field.rb
CHANGED
@@ -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(
|
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
|