mail 2.5.4 → 2.6.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.
- checksums.yaml +7 -0
- data/CHANGELOG.rdoc +7 -2
- data/CONTRIBUTING.md +13 -0
- data/Dependencies.txt +0 -1
- data/Gemfile +9 -7
- data/README.md +41 -21
- data/Rakefile +10 -2
- data/VERSION +4 -0
- data/lib/mail/body.rb +2 -2
- data/lib/mail/core_extensions/string.rb +12 -2
- data/lib/mail/elements/address.rb +38 -82
- data/lib/mail/elements/address_list.rb +19 -42
- data/lib/mail/elements/content_disposition_element.rb +3 -7
- data/lib/mail/elements/content_location_element.rb +2 -6
- data/lib/mail/elements/content_transfer_encoding_element.rb +3 -10
- data/lib/mail/elements/content_type_element.rb +4 -8
- data/lib/mail/elements/date_time_element.rb +3 -7
- data/lib/mail/elements/envelope_from_element.rb +3 -11
- data/lib/mail/elements/message_ids_element.rb +1 -6
- data/lib/mail/elements/mime_version_element.rb +3 -7
- data/lib/mail/elements/phrase_list.rb +2 -7
- data/lib/mail/elements/received_element.rb +3 -7
- data/lib/mail/encodings.rb +0 -1
- data/lib/mail/envelope.rb +0 -5
- data/lib/mail/field.rb +53 -17
- data/lib/mail/field_list.rb +18 -18
- data/lib/mail/fields/common/common_address.rb +15 -20
- data/lib/mail/fields/common/common_date.rb +0 -7
- data/lib/mail/fields/common/common_field.rb +1 -1
- data/lib/mail/fields/content_transfer_encoding_field.rb +0 -6
- data/lib/mail/fields/resent_sender_field.rb +1 -1
- data/lib/mail/fields/sender_field.rb +1 -1
- data/lib/mail/fields/unstructured_field.rb +7 -1
- data/lib/mail/header.rb +8 -22
- data/lib/mail/mail.rb +12 -0
- data/lib/mail/matchers/has_sent_mail.rb +34 -1
- data/lib/mail/message.rb +18 -11
- data/lib/mail/multibyte/unicode.rb +1 -1
- data/lib/mail/network/delivery_methods/sendmail.rb +1 -1
- data/lib/mail/network/delivery_methods/smtp.rb +5 -9
- data/lib/mail/network/retriever_methods/imap.rb +18 -13
- data/lib/mail/parsers/address_lists_parser.rb +132 -0
- data/lib/mail/parsers/content_disposition_parser.rb +67 -0
- data/lib/mail/parsers/content_location_parser.rb +35 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +33 -0
- data/lib/mail/parsers/content_type_parser.rb +64 -0
- data/lib/mail/parsers/date_time_parser.rb +36 -0
- data/lib/mail/parsers/envelope_from_parser.rb +45 -0
- data/lib/mail/parsers/message_ids_parser.rb +39 -0
- data/lib/mail/parsers/mime_version_parser.rb +41 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +33 -0
- data/lib/mail/parsers/ragel/common.rl +184 -0
- data/lib/mail/parsers/ragel/date_time.rl +30 -0
- data/lib/mail/parsers/ragel/parser_info.rb +61 -0
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +14864 -0
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +751 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +614 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +447 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +825 -0
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +817 -0
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +2129 -0
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +1570 -0
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +440 -0
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +564 -0
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +51 -0
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +5144 -0
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +37 -0
- data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +37 -0
- data/lib/mail/parsers/ragel/ruby.rb +29 -0
- data/lib/mail/parsers/ragel.rb +17 -0
- data/lib/mail/parsers/received_parser.rb +47 -0
- data/lib/mail/parsers.rb +26 -0
- data/lib/mail/parts_list.rb +5 -3
- data/lib/mail/patterns.rb +3 -1
- data/lib/mail/utilities.rb +3 -1
- data/lib/mail/version.rb +1 -1
- data/lib/mail/version_specific/ruby_1_8.rb +1 -1
- data/lib/mail/version_specific/ruby_1_9.rb +16 -1
- data/lib/mail.rb +1 -1
- metadata +77 -87
- data/lib/VERSION +0 -4
- data/lib/load_parsers.rb +0 -35
- data/lib/mail/parsers/address_lists.rb +0 -64
- data/lib/mail/parsers/address_lists.treetop +0 -19
- data/lib/mail/parsers/content_disposition.rb +0 -535
- data/lib/mail/parsers/content_disposition.treetop +0 -46
- data/lib/mail/parsers/content_location.rb +0 -139
- data/lib/mail/parsers/content_location.treetop +0 -20
- data/lib/mail/parsers/content_transfer_encoding.rb +0 -201
- data/lib/mail/parsers/content_transfer_encoding.treetop +0 -18
- data/lib/mail/parsers/content_type.rb +0 -971
- data/lib/mail/parsers/content_type.treetop +0 -68
- data/lib/mail/parsers/date_time.rb +0 -114
- data/lib/mail/parsers/date_time.treetop +0 -11
- data/lib/mail/parsers/envelope_from.rb +0 -194
- data/lib/mail/parsers/envelope_from.treetop +0 -32
- data/lib/mail/parsers/message_ids.rb +0 -45
- data/lib/mail/parsers/message_ids.treetop +0 -15
- data/lib/mail/parsers/mime_version.rb +0 -144
- data/lib/mail/parsers/mime_version.treetop +0 -19
- data/lib/mail/parsers/phrase_lists.rb +0 -45
- data/lib/mail/parsers/phrase_lists.treetop +0 -15
- data/lib/mail/parsers/received.rb +0 -71
- data/lib/mail/parsers/received.treetop +0 -11
- data/lib/mail/parsers/rfc2045.rb +0 -421
- data/lib/mail/parsers/rfc2045.treetop +0 -35
- data/lib/mail/parsers/rfc2822.rb +0 -5397
- data/lib/mail/parsers/rfc2822.treetop +0 -408
- data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
- data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
- data/lib/tasks/corpus.rake +0 -125
- data/lib/tasks/treetop.rake +0 -10
data/lib/mail/message.rb
CHANGED
|
@@ -240,7 +240,7 @@ module Mail
|
|
|
240
240
|
# This method bypasses checking perform_deliveries and raise_delivery_errors,
|
|
241
241
|
# so use with caution.
|
|
242
242
|
#
|
|
243
|
-
# It still however fires off the
|
|
243
|
+
# It still however fires off the interceptors and calls the observers callbacks if they are defined.
|
|
244
244
|
#
|
|
245
245
|
# Returns self
|
|
246
246
|
def deliver!
|
|
@@ -353,17 +353,23 @@ module Mail
|
|
|
353
353
|
return false unless other.respond_to?(:encoded)
|
|
354
354
|
|
|
355
355
|
if self.message_id && other.message_id
|
|
356
|
-
|
|
356
|
+
self.encoded == other.encoded
|
|
357
357
|
else
|
|
358
358
|
self_message_id, other_message_id = self.message_id, other.message_id
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
359
|
+
begin
|
|
360
|
+
self.message_id, other.message_id = '<temp@test>', '<temp@test>'
|
|
361
|
+
self.encoded == other.encoded
|
|
362
|
+
ensure
|
|
363
|
+
self.message_id, other.message_id = self_message_id, other_message_id
|
|
364
|
+
end
|
|
364
365
|
end
|
|
365
366
|
end
|
|
366
367
|
|
|
368
|
+
def initialize_copy(original)
|
|
369
|
+
super
|
|
370
|
+
@header = @header.dup
|
|
371
|
+
end
|
|
372
|
+
|
|
367
373
|
# Provides access to the raw source of the message as it was when it
|
|
368
374
|
# was instantiated. This is set at initialization and so is untouched
|
|
369
375
|
# by the parsers or decoder / encoders
|
|
@@ -1388,7 +1394,7 @@ module Mail
|
|
|
1388
1394
|
header.has_date?
|
|
1389
1395
|
end
|
|
1390
1396
|
|
|
1391
|
-
# Returns true if the message has a
|
|
1397
|
+
# Returns true if the message has a Mime-Version field, the field may or may
|
|
1392
1398
|
# not have a value, but the field exists or not.
|
|
1393
1399
|
def has_mime_version?
|
|
1394
1400
|
header.has_mime_version?
|
|
@@ -1594,7 +1600,7 @@ module Mail
|
|
|
1594
1600
|
end
|
|
1595
1601
|
|
|
1596
1602
|
# Returns an AttachmentsList object, which holds all of the attachments in
|
|
1597
|
-
# the receiver object (either the
|
|
1603
|
+
# the receiver object (either the entire email or a part within) and all
|
|
1598
1604
|
# of its descendants.
|
|
1599
1605
|
#
|
|
1600
1606
|
# It also allows you to add attachments to the mail object directly, like so:
|
|
@@ -1974,8 +1980,9 @@ module Mail
|
|
|
1974
1980
|
end
|
|
1975
1981
|
|
|
1976
1982
|
def raw_source=(value)
|
|
1977
|
-
value.force_encoding("binary") if RUBY_VERSION >= "1.9.1"
|
|
1978
1983
|
@raw_source = value.to_crlf
|
|
1984
|
+
@raw_source.force_encoding("binary") if RUBY_VERSION >= "1.9.1"
|
|
1985
|
+
@raw_source
|
|
1979
1986
|
end
|
|
1980
1987
|
|
|
1981
1988
|
# see comments to body=. We take data and process it lazily
|
|
@@ -2128,7 +2135,7 @@ module Mail
|
|
|
2128
2135
|
if perform_deliveries
|
|
2129
2136
|
delivery_method.deliver!(self)
|
|
2130
2137
|
end
|
|
2131
|
-
rescue
|
|
2138
|
+
rescue => e # Net::SMTP errors or sendmail pipe errors
|
|
2132
2139
|
raise e if raise_delivery_errors
|
|
2133
2140
|
end
|
|
2134
2141
|
end
|
|
@@ -341,7 +341,7 @@ module Mail
|
|
|
341
341
|
def load
|
|
342
342
|
begin
|
|
343
343
|
@codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, 'rb') { |f| Marshal.load f.read }
|
|
344
|
-
rescue
|
|
344
|
+
rescue => e
|
|
345
345
|
raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), Mail::Multibyte is unusable")
|
|
346
346
|
end
|
|
347
347
|
|
|
@@ -50,7 +50,7 @@ module Mail
|
|
|
50
50
|
smtp_from, smtp_to, message = check_delivery_params(mail)
|
|
51
51
|
|
|
52
52
|
from = "-f #{self.class.shellquote(smtp_from)}"
|
|
53
|
-
to = smtp_to.map { |
|
|
53
|
+
to = smtp_to.map { |_to| self.class.shellquote(_to) }.join(' ')
|
|
54
54
|
|
|
55
55
|
arguments = "#{settings[:arguments]} #{from} --"
|
|
56
56
|
self.class.call(settings[:location], arguments, to, message)
|
|
@@ -132,15 +132,11 @@ module Mail
|
|
|
132
132
|
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
context.ca_path = settings[:ca_path] if settings[:ca_path]
|
|
141
|
-
context.ca_file = settings[:ca_file] if settings[:ca_file]
|
|
142
|
-
context
|
|
143
|
-
end
|
|
135
|
+
context = Net::SMTP.default_ssl_context
|
|
136
|
+
context.verify_mode = openssl_verify_mode
|
|
137
|
+
context.ca_path = settings[:ca_path] if settings[:ca_path]
|
|
138
|
+
context.ca_file = settings[:ca_file] if settings[:ca_file]
|
|
139
|
+
context
|
|
144
140
|
end
|
|
145
141
|
end
|
|
146
142
|
end
|
|
@@ -73,31 +73,35 @@ module Mail
|
|
|
73
73
|
start do |imap|
|
|
74
74
|
options[:read_only] ? imap.examine(options[:mailbox]) : imap.select(options[:mailbox])
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
uids = imap.uid_search(options[:keys])
|
|
77
|
+
uids.reverse! if options[:what].to_sym == :last
|
|
78
|
+
uids = uids.first(options[:count]) if options[:count].is_a?(Integer)
|
|
79
|
+
uids.reverse! if (options[:what].to_sym == :last && options[:order].to_sym == :asc) ||
|
|
80
80
|
(options[:what].to_sym != :last && options[:order].to_sym == :desc)
|
|
81
81
|
|
|
82
82
|
if block_given?
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
uids.each do |uid|
|
|
84
|
+
uid = options[:uid].to_i unless options[:uid].nil?
|
|
85
|
+
fetchdata = imap.uid_fetch(uid, ['RFC822'])[0]
|
|
85
86
|
new_message = Mail.new(fetchdata.attr['RFC822'])
|
|
86
87
|
new_message.mark_for_delete = true if options[:delete_after_find]
|
|
87
88
|
if block.arity == 3
|
|
88
|
-
yield new_message, imap,
|
|
89
|
+
yield new_message, imap, uid
|
|
89
90
|
else
|
|
90
91
|
yield new_message
|
|
91
92
|
end
|
|
92
|
-
imap.uid_store(
|
|
93
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find] && new_message.is_marked_for_delete?
|
|
94
|
+
break unless options[:uid].nil?
|
|
93
95
|
end
|
|
94
96
|
imap.expunge if options[:delete_after_find]
|
|
95
97
|
else
|
|
96
98
|
emails = []
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
uids.each do |uid|
|
|
100
|
+
uid = options[:uid].to_i unless options[:uid].nil?
|
|
101
|
+
fetchdata = imap.uid_fetch(uid, ['RFC822'])[0]
|
|
99
102
|
emails << Mail.new(fetchdata.attr['RFC822'])
|
|
100
|
-
imap.uid_store(
|
|
103
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find]
|
|
104
|
+
break unless options[:uid].nil?
|
|
101
105
|
end
|
|
102
106
|
imap.expunge if options[:delete_after_find]
|
|
103
107
|
emails.size == 1 && options[:count] == 1 ? emails.first : emails
|
|
@@ -111,8 +115,8 @@ module Mail
|
|
|
111
115
|
mailbox = Net::IMAP.encode_utf7(mailbox)
|
|
112
116
|
|
|
113
117
|
start do |imap|
|
|
114
|
-
imap.uid_search(['ALL']).each do |
|
|
115
|
-
imap.uid_store(
|
|
118
|
+
imap.uid_search(['ALL']).each do |uid|
|
|
119
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED])
|
|
116
120
|
end
|
|
117
121
|
imap.expunge
|
|
118
122
|
end
|
|
@@ -137,6 +141,7 @@ module Mail
|
|
|
137
141
|
options[:order] ||= :asc
|
|
138
142
|
options[:what] ||= :first
|
|
139
143
|
options[:keys] ||= 'ALL'
|
|
144
|
+
options[:uid] ||= nil
|
|
140
145
|
options[:delete_after_find] ||= false
|
|
141
146
|
options[:mailbox] = Net::IMAP.encode_utf7(options[:mailbox])
|
|
142
147
|
options[:read_only] ||= false
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class AddressListsParser
|
|
3
|
+
include Mail::Utilities
|
|
4
|
+
|
|
5
|
+
def parse(s)
|
|
6
|
+
address_list = AddressListStruct.new([],[])
|
|
7
|
+
|
|
8
|
+
if s.blank?
|
|
9
|
+
return address_list
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
actions, error = Ragel.parse(:address_lists, s)
|
|
13
|
+
if error
|
|
14
|
+
raise Mail::Field::ParseError.new(Mail::AddressList, s, error)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
phrase_s = phrase_e = qstr_s = qstr = comment_s = nil
|
|
19
|
+
group_name_s = domain_s = group_name = nil
|
|
20
|
+
local_dot_atom_s = local_dot_atom_e = nil
|
|
21
|
+
local_dot_atom_pre_comment_e = nil
|
|
22
|
+
obs_domain_list_s = nil
|
|
23
|
+
|
|
24
|
+
address_s = 0
|
|
25
|
+
address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
|
|
26
|
+
actions.each_slice(2) do |action_id, p|
|
|
27
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
28
|
+
case action
|
|
29
|
+
|
|
30
|
+
# Phrase
|
|
31
|
+
when :phrase_s then phrase_s = p
|
|
32
|
+
when :phrase_e then phrase_e = p-1
|
|
33
|
+
|
|
34
|
+
# Quoted String.
|
|
35
|
+
when :qstr_s then qstr_s = p
|
|
36
|
+
when :qstr_e then qstr = s[qstr_s..(p-1)]
|
|
37
|
+
|
|
38
|
+
# Comment
|
|
39
|
+
when :comment_s
|
|
40
|
+
comment_s = p unless comment_s
|
|
41
|
+
when :comment_e
|
|
42
|
+
if address
|
|
43
|
+
address.comments << s[comment_s..(p-2)]
|
|
44
|
+
end
|
|
45
|
+
comment_s = nil
|
|
46
|
+
|
|
47
|
+
# Group Name
|
|
48
|
+
when :group_name_s then group_name_s = p
|
|
49
|
+
when :group_name_e
|
|
50
|
+
if qstr
|
|
51
|
+
group = qstr
|
|
52
|
+
qstr = nil
|
|
53
|
+
else
|
|
54
|
+
group = s[group_name_s..(p-1)]
|
|
55
|
+
group_name_s = nil
|
|
56
|
+
end
|
|
57
|
+
address_list.group_names << group
|
|
58
|
+
group_name = group
|
|
59
|
+
|
|
60
|
+
# Start next address
|
|
61
|
+
address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
|
|
62
|
+
address_s = p
|
|
63
|
+
address.group = group_name
|
|
64
|
+
|
|
65
|
+
# Address
|
|
66
|
+
when :address_s
|
|
67
|
+
address_s = p
|
|
68
|
+
when :address_e
|
|
69
|
+
# Ignore address end events if they don't have
|
|
70
|
+
# a matching address start event.
|
|
71
|
+
next if address_s.nil?
|
|
72
|
+
if address.local.nil? && local_dot_atom_pre_comment_e && local_dot_atom_s && local_dot_atom_e
|
|
73
|
+
if address.domain
|
|
74
|
+
address.local = s[local_dot_atom_s..local_dot_atom_e] if address
|
|
75
|
+
else
|
|
76
|
+
address.local = s[local_dot_atom_s..local_dot_atom_pre_comment_e] if address
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
address.raw = s[address_s..(p-1)]
|
|
80
|
+
address_list.addresses << address if address
|
|
81
|
+
|
|
82
|
+
# Start next address
|
|
83
|
+
address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
|
|
84
|
+
address.group = group_name
|
|
85
|
+
address_s = nil
|
|
86
|
+
|
|
87
|
+
# Don't set the display name until the
|
|
88
|
+
# address has actually started. This allows
|
|
89
|
+
# us to choose quoted_s version if it
|
|
90
|
+
# exists and always use the 'full' phrase
|
|
91
|
+
# version.
|
|
92
|
+
when :angle_addr_s
|
|
93
|
+
if qstr
|
|
94
|
+
address.display_name = qstr
|
|
95
|
+
qstr = nil
|
|
96
|
+
elsif phrase_e
|
|
97
|
+
address.display_name = s[phrase_s..phrase_e].strip
|
|
98
|
+
phrase_e = phrase_s = nil
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Domain
|
|
102
|
+
when :domain_s
|
|
103
|
+
domain_s = p
|
|
104
|
+
when :domain_e
|
|
105
|
+
address.domain = s[domain_s..(p-1)].rstrip if address
|
|
106
|
+
|
|
107
|
+
# Local
|
|
108
|
+
when :local_dot_atom_s then local_dot_atom_s = p
|
|
109
|
+
when :local_dot_atom_e then local_dot_atom_e = p-1
|
|
110
|
+
when :local_dot_atom_pre_comment_e
|
|
111
|
+
local_dot_atom_pre_comment_e = p-1
|
|
112
|
+
when :local_quoted_string_e
|
|
113
|
+
address.local = '"' + qstr + '"' if address
|
|
114
|
+
|
|
115
|
+
# obs_domain_list
|
|
116
|
+
when :obs_domain_list_s then obs_domain_list_s = p
|
|
117
|
+
when :obs_domain_list_e
|
|
118
|
+
address.obs_domain_list = s[obs_domain_list_s..(p-1)]
|
|
119
|
+
|
|
120
|
+
else
|
|
121
|
+
raise Mail::Field::ParseError.new(Mail::AddressList, s, "Failed to process unknown action: #{action}")
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
if address_list.addresses.empty? && address_list.group_names.empty?
|
|
126
|
+
raise Mail::Field::ParseError.new(Mail::AddressList, s, "Didn't find any addresses or groups")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
address_list
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class ContentDispositionParser
|
|
3
|
+
include Mail::Utilities
|
|
4
|
+
|
|
5
|
+
def parse(s)
|
|
6
|
+
content_disposition = ContentDispositionStruct.new("", nil)
|
|
7
|
+
if s.blank?
|
|
8
|
+
return content_disposition
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
actions, error = Ragel.parse(:content_disposition, s)
|
|
12
|
+
if error
|
|
13
|
+
raise Mail::Field::ParseError.new(Mail::ContentDispositionElement, s, error)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
content_disposition.parameters = []
|
|
17
|
+
|
|
18
|
+
disp_type_s = param_attr_s = param_attr = qstr_s = qstr = param_val_s = nil
|
|
19
|
+
actions.each_slice(2) do |action_id, p|
|
|
20
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
21
|
+
case action
|
|
22
|
+
|
|
23
|
+
# Disposition Type
|
|
24
|
+
when :disp_type_s then disp_type_s = p
|
|
25
|
+
when :disp_type_e
|
|
26
|
+
content_disposition.disposition_type = s[disp_type_s..(p-1)].downcase
|
|
27
|
+
|
|
28
|
+
# Parameter Attribute
|
|
29
|
+
when :param_attr_s then param_attr_s = p
|
|
30
|
+
when :param_attr_e then param_attr = s[param_attr_s..(p-1)]
|
|
31
|
+
|
|
32
|
+
# Quoted String.
|
|
33
|
+
when :qstr_s then qstr_s = p
|
|
34
|
+
when :qstr_e then qstr = s[qstr_s..(p-1)]
|
|
35
|
+
|
|
36
|
+
# Parameter Value
|
|
37
|
+
when :param_val_s then param_val_s = p
|
|
38
|
+
when :param_val_e
|
|
39
|
+
if param_attr.nil?
|
|
40
|
+
raise Mail::Field::ParseError.new(Mail::ContentDispositionElement, s, "no attribute for value")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Use quoted string value if one exists, otherwise use parameter value
|
|
44
|
+
if qstr
|
|
45
|
+
value = qstr
|
|
46
|
+
else
|
|
47
|
+
value = s[param_val_s..(p-1)]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
content_disposition.parameters << { param_attr => value }
|
|
51
|
+
param_attr = nil
|
|
52
|
+
qstr = nil
|
|
53
|
+
|
|
54
|
+
else
|
|
55
|
+
raise Mail::Field::ParseError.new(Mail::ContentDispositionElement, s, "Failed to process unknown action: #{action}")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
content_disposition
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
def cleaned(string)
|
|
64
|
+
string =~ /(.+);\s*$/ ? $1 : string
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class ContentLocationParser
|
|
3
|
+
def parse(s)
|
|
4
|
+
content_location = ContentLocationStruct.new(nil)
|
|
5
|
+
if s.blank?
|
|
6
|
+
return content_location
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
actions, error = Ragel.parse(:content_location, s)
|
|
10
|
+
if error
|
|
11
|
+
raise Mail::Field::ParseError.new(Mail::ContentLocationElement, s, error)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
qstr_s = token_string_s = nil
|
|
15
|
+
actions.each_slice(2) do |action_id, p|
|
|
16
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
17
|
+
case action
|
|
18
|
+
|
|
19
|
+
# Quoted String.
|
|
20
|
+
when :qstr_s then qstr_s = p
|
|
21
|
+
when :qstr_e then content_location.location = s[qstr_s..(p-1)]
|
|
22
|
+
|
|
23
|
+
# Token String
|
|
24
|
+
when :token_string_s then token_string_s = p
|
|
25
|
+
when :token_string_e
|
|
26
|
+
content_location.location = s[token_string_s..(p-1)]
|
|
27
|
+
|
|
28
|
+
else
|
|
29
|
+
raise Mail::Field::ParseError.new(Mail::ContentLocationElement, s, "Failed to process unknown action: #{action}")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
content_location
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class ContentTransferEncodingParser
|
|
3
|
+
|
|
4
|
+
def parse(s)
|
|
5
|
+
content_transfer_encoding = ContentTransferEncodingStruct.new("")
|
|
6
|
+
if s.blank?
|
|
7
|
+
return content_transfer_encoding
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
actions, error = Ragel.parse(:content_transfer_encoding, s)
|
|
11
|
+
if error
|
|
12
|
+
raise Mail::Field::ParseError.new(Mail::ContentTransferEncodingElement, s, error)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
encoding_s = nil
|
|
16
|
+
actions.each_slice(2) do |action_id, p|
|
|
17
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
18
|
+
case action
|
|
19
|
+
|
|
20
|
+
# Encoding
|
|
21
|
+
when :encoding_s then encoding_s = p
|
|
22
|
+
when :encoding_e
|
|
23
|
+
content_transfer_encoding.encoding = s[encoding_s..(p-1)].downcase
|
|
24
|
+
|
|
25
|
+
else
|
|
26
|
+
raise Mail::Field::ParseError.new(Mail::ContentTransferEncodingElement, s, "Failed to process unknown action: #{action}")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
content_transfer_encoding
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class ContentTypeParser
|
|
3
|
+
include Mail::Utilities
|
|
4
|
+
|
|
5
|
+
def parse(s)
|
|
6
|
+
actions, error = Ragel.parse(:content_type, s)
|
|
7
|
+
if error
|
|
8
|
+
raise Mail::Field::ParseError.new(Mail::ContentTypeElement, s, error)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
content_type = ContentTypeStruct.new(nil,nil,[])
|
|
12
|
+
|
|
13
|
+
content_type.parameters = []
|
|
14
|
+
|
|
15
|
+
main_type_s = sub_type_s = param_attr_s = param_attr = nil
|
|
16
|
+
qstr_s = qstr = param_val_s = nil
|
|
17
|
+
actions.each_slice(2) do |action_id, p|
|
|
18
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
19
|
+
case action
|
|
20
|
+
|
|
21
|
+
# Main Type
|
|
22
|
+
when :main_type_s then main_type_s = p
|
|
23
|
+
when :main_type_e then
|
|
24
|
+
content_type.main_type = s[main_type_s..(p-1)].downcase
|
|
25
|
+
|
|
26
|
+
# Sub Type
|
|
27
|
+
when :sub_type_s then sub_type_s = p
|
|
28
|
+
when :sub_type_e
|
|
29
|
+
content_type.sub_type = s[sub_type_s..(p-1)].downcase
|
|
30
|
+
|
|
31
|
+
# Parameter Attribute
|
|
32
|
+
when :param_attr_s then param_attr_s = p
|
|
33
|
+
when :param_attr_e then param_attr = s[param_attr_s..(p-1)]
|
|
34
|
+
|
|
35
|
+
# Quoted String.
|
|
36
|
+
when :qstr_s then qstr_s = p
|
|
37
|
+
when :qstr_e then qstr = s[qstr_s..(p-1)]
|
|
38
|
+
|
|
39
|
+
# Parameter Value
|
|
40
|
+
when :param_val_s then param_val_s = p
|
|
41
|
+
when :param_val_e
|
|
42
|
+
if param_attr.nil?
|
|
43
|
+
raise Mail::Field::ParseError.new(Mail::ContentTypeElement, s, "no attribute for value")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Use quoted s value if one exists, otherwise use parameter value
|
|
47
|
+
if qstr
|
|
48
|
+
value = qstr
|
|
49
|
+
else
|
|
50
|
+
value = s[param_val_s..(p-1)]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
content_type.parameters << { param_attr => value }
|
|
54
|
+
param_attr = nil
|
|
55
|
+
qstr = nil
|
|
56
|
+
|
|
57
|
+
else
|
|
58
|
+
raise Mail::Field::ParseError.new(Mail::ContentTypeElement, s, "Failed to process unknown action: #{action}")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
content_type
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class DateTimeParser
|
|
3
|
+
include Mail::Utilities
|
|
4
|
+
|
|
5
|
+
def parse(s)
|
|
6
|
+
date_time = DateTimeStruct.new([])
|
|
7
|
+
|
|
8
|
+
actions, error = Ragel.parse(:date_time, s)
|
|
9
|
+
if error
|
|
10
|
+
raise Mail::Field::ParseError.new(Mail::DateTimeElement, s, error)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
date_s = time_s = nil
|
|
14
|
+
actions.each_slice(2) do |action_id, p|
|
|
15
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
16
|
+
case action
|
|
17
|
+
|
|
18
|
+
# Date
|
|
19
|
+
when :date_s then date_s = p
|
|
20
|
+
when :date_e
|
|
21
|
+
date_time.date_string = s[date_s..(p-1)]
|
|
22
|
+
|
|
23
|
+
# Time
|
|
24
|
+
when :time_s then time_s = p
|
|
25
|
+
when :time_e
|
|
26
|
+
date_time.time_string = s[time_s..(p-1)]
|
|
27
|
+
|
|
28
|
+
else
|
|
29
|
+
raise Mail::Field::ParseError.new(Mail::DateTimeElement, s, "Failed to process unknown action: #{action}")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
date_time
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class EnvelopeFromParser
|
|
3
|
+
def parse(s)
|
|
4
|
+
envelope_from = EnvelopeFromStruct.new
|
|
5
|
+
if s.blank?
|
|
6
|
+
return envelope_from
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
actions, error = Ragel.parse(:envelope_from, s)
|
|
10
|
+
if error
|
|
11
|
+
raise Mail::Field::ParseError.new(Mail::EnvelopeFromElement, s, error)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
address_s = ctime_date_s = nil
|
|
15
|
+
envelope_from = EnvelopeFromStruct.new
|
|
16
|
+
actions.each_slice(2) do |action_id, p|
|
|
17
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
18
|
+
case action
|
|
19
|
+
|
|
20
|
+
# Address
|
|
21
|
+
when :address_s then address_s = p
|
|
22
|
+
when :address_e
|
|
23
|
+
envelope_from.address = s[address_s..(p-1)].rstrip
|
|
24
|
+
|
|
25
|
+
# ctime_date
|
|
26
|
+
when :ctime_date_s then ctime_date_s = p
|
|
27
|
+
when :ctime_date_e
|
|
28
|
+
envelope_from.ctime_date = s[ctime_date_s..(p-1)]
|
|
29
|
+
|
|
30
|
+
# ignored actions
|
|
31
|
+
when :angle_addr_s, :comment_e, :comment_s,
|
|
32
|
+
:domain_e, :domain_s, :local_dot_atom_e,
|
|
33
|
+
:local_dot_atom_pre_comment_e,
|
|
34
|
+
:local_dot_atom_pre_comment_s,
|
|
35
|
+
:local_dot_atom_s, :qstr_e, :qstr_s
|
|
36
|
+
nil
|
|
37
|
+
|
|
38
|
+
else
|
|
39
|
+
raise Mail::Field::ParseError.new(Mail::EnvelopeFromElement, s, "Failed to process unknown action: #{action}")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
envelope_from
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class MessageIdsParser
|
|
3
|
+
def parse(s)
|
|
4
|
+
if s.blank?
|
|
5
|
+
return MessageIdsStruct.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
message_ids = MessageIdsStruct.new([])
|
|
9
|
+
|
|
10
|
+
actions, error = Ragel.parse(:message_ids, s)
|
|
11
|
+
if error
|
|
12
|
+
raise Mail::Field::ParseError.new(Mail::MessageIdsElement, s, error)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
msg_id_s = nil
|
|
16
|
+
actions.each_slice(2) do |action_id, p|
|
|
17
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
18
|
+
case action
|
|
19
|
+
|
|
20
|
+
# Message Ids
|
|
21
|
+
when :msg_id_s then msg_id_s = p
|
|
22
|
+
when :msg_id_e
|
|
23
|
+
message_ids.message_ids << s[msg_id_s..(p-1)].rstrip
|
|
24
|
+
|
|
25
|
+
when :domain_e, :domain_s, :local_dot_atom_e,
|
|
26
|
+
:local_dot_atom_pre_comment_e,
|
|
27
|
+
:local_dot_atom_pre_comment_s,
|
|
28
|
+
:local_dot_atom_s
|
|
29
|
+
|
|
30
|
+
# ignored actions
|
|
31
|
+
|
|
32
|
+
else
|
|
33
|
+
raise Mail::Field::ParseError.new(Mail::MessageIdsElement, s, "Failed to process unknown action: #{action}")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
message_ids
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Mail::Parsers
|
|
2
|
+
class MimeVersionParser
|
|
3
|
+
include Mail::Utilities
|
|
4
|
+
|
|
5
|
+
def parse(s)
|
|
6
|
+
if s.blank?
|
|
7
|
+
return MimeVersionStruct.new("", nil)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
mime_version = MimeVersionStruct.new
|
|
11
|
+
|
|
12
|
+
actions, error = Ragel.parse(:mime_version, s)
|
|
13
|
+
if error
|
|
14
|
+
raise Mail::Field::ParseError.new(Mail::MimeVersionElement, s, error)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
major_digits_s = minor_digits_s = nil
|
|
18
|
+
actions.each_slice(2) do |action_id, p|
|
|
19
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
20
|
+
case action
|
|
21
|
+
|
|
22
|
+
# Major Digits
|
|
23
|
+
when :major_digits_s then major_digits_s = p
|
|
24
|
+
when :major_digits_e
|
|
25
|
+
mime_version.major = s[major_digits_s..(p-1)]
|
|
26
|
+
|
|
27
|
+
# Minor Digits
|
|
28
|
+
when :minor_digits_s then minor_digits_s = p
|
|
29
|
+
when :minor_digits_e
|
|
30
|
+
mime_version.minor = s[minor_digits_s..(p-1)]
|
|
31
|
+
|
|
32
|
+
when :comment_e, :comment_s then nil
|
|
33
|
+
|
|
34
|
+
else
|
|
35
|
+
raise Mail::Field::ParseError.new(Mail::MimeVersionElement, s, "Failed to process unknown action: #{action}")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
mime_version
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|