mail 2.5.5 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|