mail 2.5.5 → 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 +4 -4
- data/CHANGELOG.rdoc +8 -9
- data/CONTRIBUTING.md +13 -0
- data/Dependencies.txt +0 -1
- data/Gemfile +7 -24
- data/README.md +36 -15
- data/Rakefile +10 -2
- data/VERSION +4 -0
- data/lib/mail.rb +1 -1
- data/lib/mail/body.rb +2 -2
- data/lib/mail/check_delivery_params.rb +10 -47
- 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/exim.rb +10 -6
- data/lib/mail/network/delivery_methods/file_delivery.rb +8 -4
- data/lib/mail/network/delivery_methods/sendmail.rb +7 -9
- data/lib/mail/network/delivery_methods/smtp.rb +5 -2
- data/lib/mail/network/delivery_methods/smtp_connection.rb +6 -2
- data/lib/mail/network/delivery_methods/test_mailer.rb +8 -5
- data/lib/mail/network/retriever_methods/imap.rb +18 -13
- data/lib/mail/parsers.rb +26 -0
- 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.rb +17 -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.rb +29 -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/received_parser.rb +47 -0
- data/lib/mail/parts_list.rb +4 -2
- 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 +13 -1
- metadata +55 -51
- 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
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'mail/check_delivery_params'
|
2
2
|
|
3
3
|
module Mail
|
4
|
+
|
4
5
|
# FileDelivery class delivers emails into multiple files based on the destination
|
5
6
|
# address. Each file is appended to if it already exists.
|
6
7
|
#
|
@@ -12,20 +13,22 @@ module Mail
|
|
12
13
|
# Make sure the path you specify with :location is writable by the Ruby process
|
13
14
|
# running Mail.
|
14
15
|
class FileDelivery
|
16
|
+
include Mail::CheckDeliveryParams
|
17
|
+
|
15
18
|
if RUBY_VERSION >= '1.9.1'
|
16
19
|
require 'fileutils'
|
17
20
|
else
|
18
21
|
require 'ftools'
|
19
22
|
end
|
20
23
|
|
21
|
-
attr_accessor :settings
|
22
|
-
|
23
24
|
def initialize(values)
|
24
25
|
self.settings = { :location => './mails' }.merge!(values)
|
25
26
|
end
|
26
|
-
|
27
|
+
|
28
|
+
attr_accessor :settings
|
29
|
+
|
27
30
|
def deliver!(mail)
|
28
|
-
|
31
|
+
check_delivery_params(mail)
|
29
32
|
|
30
33
|
if ::File.respond_to?(:makedirs)
|
31
34
|
::File.makedirs settings[:location]
|
@@ -37,5 +40,6 @@ module Mail
|
|
37
40
|
::File.open(::File.join(settings[:location], File.basename(to.to_s)), 'a') { |f| "#{f.write(mail.encoded)}\r\n\r\n" }
|
38
41
|
end
|
39
42
|
end
|
43
|
+
|
40
44
|
end
|
41
45
|
end
|
@@ -37,22 +37,20 @@ module Mail
|
|
37
37
|
#
|
38
38
|
# mail.deliver!
|
39
39
|
class Sendmail
|
40
|
-
|
41
|
-
:location => '/usr/sbin/sendmail',
|
42
|
-
:arguments => '-i'
|
43
|
-
}
|
44
|
-
|
45
|
-
attr_accessor :settings
|
40
|
+
include Mail::CheckDeliveryParams
|
46
41
|
|
47
42
|
def initialize(values)
|
48
|
-
self.settings =
|
43
|
+
self.settings = { :location => '/usr/sbin/sendmail',
|
44
|
+
:arguments => '-i' }.merge(values)
|
49
45
|
end
|
50
46
|
|
47
|
+
attr_accessor :settings
|
48
|
+
|
51
49
|
def deliver!(mail)
|
52
|
-
smtp_from, smtp_to, message =
|
50
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
53
51
|
|
54
52
|
from = "-f #{self.class.shellquote(smtp_from)}"
|
55
|
-
to = smtp_to.map { |
|
53
|
+
to = smtp_to.map { |_to| self.class.shellquote(_to) }.join(' ')
|
56
54
|
|
57
55
|
arguments = "#{settings[:arguments]} #{from} --"
|
58
56
|
self.class.call(settings[:location], arguments, to, message)
|
@@ -74,7 +74,7 @@ module Mail
|
|
74
74
|
#
|
75
75
|
# mail.deliver!
|
76
76
|
class SMTP
|
77
|
-
|
77
|
+
include Mail::CheckDeliveryParams
|
78
78
|
|
79
79
|
def initialize(values)
|
80
80
|
self.settings = { :address => "localhost",
|
@@ -90,10 +90,12 @@ module Mail
|
|
90
90
|
}.merge!(values)
|
91
91
|
end
|
92
92
|
|
93
|
+
attr_accessor :settings
|
94
|
+
|
93
95
|
# Send the message via SMTP.
|
94
96
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
95
97
|
def deliver!(mail)
|
96
|
-
smtp_from, smtp_to, message =
|
98
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
97
99
|
|
98
100
|
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
99
101
|
if settings[:tls] || settings[:ssl]
|
@@ -117,6 +119,7 @@ module Mail
|
|
117
119
|
self
|
118
120
|
end
|
119
121
|
end
|
122
|
+
|
120
123
|
|
121
124
|
private
|
122
125
|
|
@@ -37,7 +37,7 @@ module Mail
|
|
37
37
|
#
|
38
38
|
# mail.deliver!
|
39
39
|
class SMTPConnection
|
40
|
-
|
40
|
+
include Mail::CheckDeliveryParams
|
41
41
|
|
42
42
|
def initialize(values)
|
43
43
|
raise ArgumentError.new('A Net::SMTP object is required for this delivery method') if values[:connection].nil?
|
@@ -45,13 +45,17 @@ module Mail
|
|
45
45
|
self.settings = values
|
46
46
|
end
|
47
47
|
|
48
|
+
attr_accessor :smtp
|
49
|
+
attr_accessor :settings
|
50
|
+
|
48
51
|
# Send the message via SMTP.
|
49
52
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
50
53
|
def deliver!(mail)
|
51
|
-
smtp_from, smtp_to, message =
|
54
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
52
55
|
response = smtp.sendmail(message, smtp_from, smtp_to)
|
53
56
|
|
54
57
|
settings[:return_response] ? response : self
|
55
58
|
end
|
59
|
+
|
56
60
|
end
|
57
61
|
end
|
@@ -7,8 +7,10 @@ module Mail
|
|
7
7
|
# It also provides a template of the minimum methods you require to implement
|
8
8
|
# if you want to make a custom mailer for Mail
|
9
9
|
class TestMailer
|
10
|
+
include Mail::CheckDeliveryParams
|
11
|
+
|
10
12
|
# Provides a store of all the emails sent with the TestMailer so you can check them.
|
11
|
-
def
|
13
|
+
def TestMailer.deliveries
|
12
14
|
@@deliveries ||= []
|
13
15
|
end
|
14
16
|
|
@@ -23,19 +25,20 @@ module Mail
|
|
23
25
|
# * length
|
24
26
|
# * size
|
25
27
|
# * and other common Array methods
|
26
|
-
def
|
28
|
+
def TestMailer.deliveries=(val)
|
27
29
|
@@deliveries = val
|
28
30
|
end
|
29
31
|
|
30
|
-
attr_accessor :settings
|
31
|
-
|
32
32
|
def initialize(values)
|
33
33
|
@settings = values.dup
|
34
34
|
end
|
35
|
+
|
36
|
+
attr_accessor :settings
|
35
37
|
|
36
38
|
def deliver!(mail)
|
37
|
-
|
39
|
+
check_delivery_params(mail)
|
38
40
|
Mail::TestMailer.deliveries << mail
|
39
41
|
end
|
42
|
+
|
40
43
|
end
|
41
44
|
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
|
data/lib/mail/parsers.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Mail
|
2
|
+
module Parsers
|
3
|
+
|
4
|
+
# Low-level ragel based parsers
|
5
|
+
require 'mail/parsers/ragel'
|
6
|
+
|
7
|
+
AddressListStruct = Struct.new(:addresses, :group_names, :error)
|
8
|
+
AddressStruct = Struct.new(:raw, :domain, :comments, :local,
|
9
|
+
:obs_domain_list, :display_name, :group, :error)
|
10
|
+
ContentDispositionStruct = Struct.new(:disposition_type, :parameters, :error)
|
11
|
+
ContentLocationStruct = Struct.new(:location, :error)
|
12
|
+
ContentTransferEncodingStruct = Struct.new(:encoding, :error)
|
13
|
+
ContentTypeStruct = Struct.new(:main_type, :sub_type, :parameters, :error)
|
14
|
+
DateTimeStruct = Struct.new(:date_string, :time_string, :error)
|
15
|
+
EnvelopeFromStruct = Struct.new(:address, :ctime_date, :error)
|
16
|
+
MessageIdsStruct = Struct.new(:message_ids, :error)
|
17
|
+
MimeVersionStruct = Struct.new(:major, :minor, :error)
|
18
|
+
PhraseListsStruct = Struct.new(:phrases, :error)
|
19
|
+
ReceivedStruct = Struct.new(:date, :time, :info, :error)
|
20
|
+
|
21
|
+
require 'mail/parsers/ragel/parser_info'
|
22
|
+
Ragel::FIELD_PARSERS.each do |field_parser|
|
23
|
+
require "mail/parsers/#{field_parser}_parser"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -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
|