mail 2.5.2 → 2.6.4
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 +124 -0
- data/CONTRIBUTING.md +21 -6
- data/Dependencies.txt +0 -1
- data/Gemfile +7 -22
- data/MIT-LICENSE +20 -0
- data/README.md +86 -31
- data/Rakefile +11 -22
- data/lib/mail/attachments_list.rb +4 -2
- data/lib/mail/body.rb +36 -11
- data/lib/mail/check_delivery_params.rb +13 -22
- data/lib/mail/configuration.rb +1 -0
- data/lib/mail/{patterns.rb → constants.rb} +29 -6
- data/lib/mail/core_extensions/smtp.rb +13 -13
- data/lib/mail/core_extensions/string/access.rb +1 -0
- data/lib/mail/core_extensions/string/multibyte.rb +1 -0
- data/lib/mail/core_extensions/string.rb +5 -17
- data/lib/mail/elements/address.rb +86 -145
- data/lib/mail/elements/address_list.rb +10 -42
- data/lib/mail/elements/content_disposition_element.rb +4 -7
- data/lib/mail/elements/content_location_element.rb +8 -11
- data/lib/mail/elements/content_transfer_encoding_element.rb +4 -10
- data/lib/mail/elements/content_type_element.rb +5 -8
- data/lib/mail/elements/date_time_element.rb +4 -7
- data/lib/mail/elements/envelope_from_element.rb +19 -13
- data/lib/mail/elements/message_ids_element.rb +8 -11
- data/lib/mail/elements/mime_version_element.rb +4 -7
- data/lib/mail/elements/phrase_list.rb +3 -7
- data/lib/mail/elements/received_element.rb +4 -7
- data/lib/mail/elements.rb +1 -0
- data/lib/mail/encodings/7bit.rb +1 -0
- data/lib/mail/encodings/8bit.rb +8 -2
- data/lib/mail/encodings/base64.rb +7 -1
- data/lib/mail/encodings/binary.rb +1 -0
- data/lib/mail/encodings/quoted_printable.rb +11 -4
- data/lib/mail/encodings/transfer_encoding.rb +27 -17
- data/lib/mail/encodings/unix_to_unix.rb +18 -0
- data/lib/mail/encodings.rb +54 -39
- data/lib/mail/envelope.rb +1 -5
- data/lib/mail/field.rb +81 -31
- data/lib/mail/field_list.rb +19 -18
- data/lib/mail/fields/bcc_field.rb +17 -5
- data/lib/mail/fields/cc_field.rb +3 -3
- data/lib/mail/fields/comments_field.rb +2 -1
- data/lib/mail/fields/common/address_container.rb +1 -0
- data/lib/mail/fields/common/common_address.rb +34 -28
- data/lib/mail/fields/common/common_date.rb +2 -8
- data/lib/mail/fields/common/common_field.rb +9 -5
- data/lib/mail/fields/common/common_message_id.rb +3 -2
- data/lib/mail/fields/common/parameter_hash.rb +4 -3
- data/lib/mail/fields/content_description_field.rb +1 -0
- data/lib/mail/fields/content_disposition_field.rb +13 -12
- data/lib/mail/fields/content_id_field.rb +4 -4
- data/lib/mail/fields/content_location_field.rb +2 -1
- data/lib/mail/fields/content_transfer_encoding_field.rb +4 -9
- data/lib/mail/fields/content_type_field.rb +4 -3
- data/lib/mail/fields/date_field.rb +16 -15
- data/lib/mail/fields/from_field.rb +3 -3
- data/lib/mail/fields/in_reply_to_field.rb +3 -1
- data/lib/mail/fields/keywords_field.rb +2 -2
- data/lib/mail/fields/message_id_field.rb +4 -4
- data/lib/mail/fields/mime_version_field.rb +3 -2
- data/lib/mail/fields/optional_field.rb +1 -0
- data/lib/mail/fields/received_field.rb +4 -3
- data/lib/mail/fields/references_field.rb +3 -1
- data/lib/mail/fields/reply_to_field.rb +3 -3
- data/lib/mail/fields/resent_bcc_field.rb +3 -3
- data/lib/mail/fields/resent_cc_field.rb +3 -3
- data/lib/mail/fields/resent_date_field.rb +2 -1
- data/lib/mail/fields/resent_from_field.rb +3 -3
- data/lib/mail/fields/resent_message_id_field.rb +1 -0
- data/lib/mail/fields/resent_sender_field.rb +4 -4
- data/lib/mail/fields/resent_to_field.rb +3 -3
- data/lib/mail/fields/return_path_field.rb +1 -1
- data/lib/mail/fields/sender_field.rb +9 -9
- data/lib/mail/fields/structured_field.rb +1 -0
- data/lib/mail/fields/subject_field.rb +1 -0
- data/lib/mail/fields/to_field.rb +3 -3
- data/lib/mail/fields/unstructured_field.rb +15 -8
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +21 -29
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +16 -1
- data/lib/mail/matchers/attachment_matchers.rb +29 -0
- data/lib/mail/matchers/has_sent_mail.rb +61 -4
- data/lib/mail/message.rb +175 -72
- data/lib/mail/multibyte/chars.rb +3 -2
- data/lib/mail/multibyte/exceptions.rb +1 -0
- data/lib/mail/multibyte/unicode.rb +22 -15
- data/lib/mail/multibyte/utils.rb +1 -0
- data/lib/mail/multibyte.rb +1 -0
- data/lib/mail/network/delivery_methods/exim.rb +3 -7
- data/lib/mail/network/delivery_methods/file_delivery.rb +2 -1
- data/lib/mail/network/delivery_methods/sendmail.rb +33 -10
- data/lib/mail/network/delivery_methods/smtp.rb +32 -34
- data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -6
- data/lib/mail/network/delivery_methods/test_mailer.rb +3 -2
- data/lib/mail/network/retriever_methods/base.rb +1 -0
- data/lib/mail/network/retriever_methods/imap.rb +19 -13
- data/lib/mail/network/retriever_methods/pop3.rb +1 -0
- data/lib/mail/network/retriever_methods/test_retriever.rb +1 -0
- data/lib/mail/network.rb +1 -0
- data/lib/mail/parsers/address_lists_parser.rb +133 -0
- data/lib/mail/parsers/content_disposition_parser.rb +68 -0
- data/lib/mail/parsers/content_location_parser.rb +36 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +34 -0
- data/lib/mail/parsers/content_type_parser.rb +67 -0
- data/lib/mail/parsers/date_time_parser.rb +39 -0
- data/lib/mail/parsers/envelope_from_parser.rb +46 -0
- data/lib/mail/parsers/message_ids_parser.rb +40 -0
- data/lib/mail/parsers/mime_version_parser.rb +42 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +36 -0
- data/lib/mail/parsers/ragel/common.rl +185 -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 +2149 -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 +40 -0
- data/lib/mail/parsers/ragel.rb +18 -0
- data/lib/mail/parsers/received_parser.rb +49 -0
- data/lib/mail/parsers.rb +27 -0
- data/lib/mail/part.rb +11 -4
- data/lib/mail/parts_list.rb +30 -10
- data/lib/mail/utilities.rb +127 -63
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +8 -15
- data/lib/mail/version_specific/ruby_1_8.rb +18 -7
- data/lib/mail/version_specific/ruby_1_9.rb +136 -32
- data/lib/mail.rb +12 -6
- metadata +115 -77
- data/lib/VERSION +0 -4
- data/lib/load_parsers.rb +0 -41
- data/lib/mail/core_extensions/nil.rb +0 -19
- data/lib/mail/core_extensions/object.rb +0 -13
- data/lib/mail/core_extensions/shell_escape.rb +0 -56
- 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 -162
- data/lib/mail/parsers/content_transfer_encoding.treetop +0 -20
- data/lib/mail/parsers/content_type.rb +0 -967
- 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 -464
- data/lib/mail/parsers/rfc2045.treetop +0 -36
- data/lib/mail/parsers/rfc2822.rb +0 -5397
- data/lib/mail/parsers/rfc2822.treetop +0 -410
- 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,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mail/check_delivery_params'
|
|
2
3
|
|
|
3
4
|
module Mail
|
|
@@ -89,57 +90,54 @@ module Mail
|
|
|
89
90
|
:tls => nil
|
|
90
91
|
}.merge!(values)
|
|
91
92
|
end
|
|
92
|
-
|
|
93
|
+
|
|
93
94
|
attr_accessor :settings
|
|
94
|
-
|
|
95
|
+
|
|
95
96
|
# Send the message via SMTP.
|
|
96
97
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
|
97
98
|
def deliver!(mail)
|
|
98
|
-
|
|
99
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
|
99
100
|
|
|
100
101
|
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
|
101
102
|
if settings[:tls] || settings[:ssl]
|
|
102
103
|
if smtp.respond_to?(:enable_tls)
|
|
103
|
-
|
|
104
|
-
smtp.enable_tls
|
|
105
|
-
else
|
|
106
|
-
openssl_verify_mode = settings[:openssl_verify_mode]
|
|
107
|
-
if openssl_verify_mode.kind_of?(String)
|
|
108
|
-
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
|
109
|
-
end
|
|
110
|
-
context = Net::SMTP.default_ssl_context
|
|
111
|
-
context.verify_mode = openssl_verify_mode
|
|
112
|
-
smtp.enable_tls(context)
|
|
113
|
-
end
|
|
104
|
+
smtp.enable_tls(ssl_context)
|
|
114
105
|
end
|
|
115
106
|
elsif settings[:enable_starttls_auto]
|
|
116
|
-
if smtp.respond_to?(:enable_starttls_auto)
|
|
117
|
-
|
|
118
|
-
smtp.enable_starttls_auto
|
|
119
|
-
else
|
|
120
|
-
openssl_verify_mode = settings[:openssl_verify_mode]
|
|
121
|
-
if openssl_verify_mode.kind_of?(String)
|
|
122
|
-
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
|
123
|
-
end
|
|
124
|
-
if RUBY_VERSION >= '1.9.0'
|
|
125
|
-
context = Net::SMTP.default_ssl_context
|
|
126
|
-
context.verify_mode = openssl_verify_mode
|
|
127
|
-
smtp.enable_tls(context)
|
|
128
|
-
else
|
|
129
|
-
smtp.enable_tls(openssl_verify_mode)
|
|
130
|
-
end
|
|
131
|
-
end
|
|
107
|
+
if smtp.respond_to?(:enable_starttls_auto)
|
|
108
|
+
smtp.enable_starttls_auto(ssl_context)
|
|
132
109
|
end
|
|
133
110
|
end
|
|
134
|
-
|
|
111
|
+
|
|
135
112
|
response = nil
|
|
136
113
|
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp_obj|
|
|
137
|
-
response = smtp_obj.sendmail(message,
|
|
114
|
+
response = smtp_obj.sendmail(message, smtp_from, smtp_to)
|
|
138
115
|
end
|
|
139
116
|
|
|
140
|
-
|
|
117
|
+
if settings[:return_response]
|
|
118
|
+
response
|
|
119
|
+
else
|
|
120
|
+
self
|
|
121
|
+
end
|
|
141
122
|
end
|
|
142
123
|
|
|
143
|
-
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
# Allow SSL context to be configured via settings, for Ruby >= 1.9
|
|
128
|
+
# Just returns openssl verify mode for Ruby 1.8.x
|
|
129
|
+
def ssl_context
|
|
130
|
+
openssl_verify_mode = settings[:openssl_verify_mode]
|
|
131
|
+
|
|
132
|
+
if openssl_verify_mode.kind_of?(String)
|
|
133
|
+
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
context = Net::SMTP.default_ssl_context
|
|
137
|
+
context.verify_mode = openssl_verify_mode
|
|
138
|
+
context.ca_path = settings[:ca_path] if settings[:ca_path]
|
|
139
|
+
context.ca_file = settings[:ca_file] if settings[:ca_file]
|
|
140
|
+
context
|
|
141
|
+
end
|
|
144
142
|
end
|
|
145
143
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mail/check_delivery_params'
|
|
2
3
|
|
|
3
4
|
module Mail
|
|
@@ -44,18 +45,18 @@ module Mail
|
|
|
44
45
|
self.smtp = values[:connection]
|
|
45
46
|
self.settings = values
|
|
46
47
|
end
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
attr_accessor :smtp
|
|
49
50
|
attr_accessor :settings
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
# Send the message via SMTP.
|
|
52
53
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
|
53
54
|
def deliver!(mail)
|
|
54
|
-
|
|
55
|
-
response = smtp.sendmail(message,
|
|
55
|
+
smtp_from, smtp_to, message = check_delivery_params(mail)
|
|
56
|
+
response = smtp.sendmail(message, smtp_from, smtp_to)
|
|
56
57
|
|
|
57
|
-
settings[:return_response] ? response : self
|
|
58
|
+
settings[:return_response] ? response : self
|
|
58
59
|
end
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
end
|
|
61
62
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mail/check_delivery_params'
|
|
2
3
|
|
|
3
4
|
module Mail
|
|
@@ -30,13 +31,13 @@ module Mail
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
def initialize(values)
|
|
33
|
-
@settings =
|
|
34
|
+
@settings = values.dup
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
attr_accessor :settings
|
|
37
38
|
|
|
38
39
|
def deliver!(mail)
|
|
39
|
-
|
|
40
|
+
check_delivery_params(mail)
|
|
40
41
|
Mail::TestMailer.deliveries << mail
|
|
41
42
|
end
|
|
42
43
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Mail
|
|
4
5
|
# The IMAP retriever allows to get the last, first or all emails from a IMAP server.
|
|
@@ -73,31 +74,35 @@ module Mail
|
|
|
73
74
|
start do |imap|
|
|
74
75
|
options[:read_only] ? imap.examine(options[:mailbox]) : imap.select(options[:mailbox])
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
uids = imap.uid_search(options[:keys])
|
|
78
|
+
uids.reverse! if options[:what].to_sym == :last
|
|
79
|
+
uids = uids.first(options[:count]) if options[:count].is_a?(Integer)
|
|
80
|
+
uids.reverse! if (options[:what].to_sym == :last && options[:order].to_sym == :asc) ||
|
|
80
81
|
(options[:what].to_sym != :last && options[:order].to_sym == :desc)
|
|
81
82
|
|
|
82
83
|
if block_given?
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
uids.each do |uid|
|
|
85
|
+
uid = options[:uid].to_i unless options[:uid].nil?
|
|
86
|
+
fetchdata = imap.uid_fetch(uid, ['RFC822'])[0]
|
|
85
87
|
new_message = Mail.new(fetchdata.attr['RFC822'])
|
|
86
88
|
new_message.mark_for_delete = true if options[:delete_after_find]
|
|
87
89
|
if block.arity == 3
|
|
88
|
-
yield new_message, imap,
|
|
90
|
+
yield new_message, imap, uid
|
|
89
91
|
else
|
|
90
92
|
yield new_message
|
|
91
93
|
end
|
|
92
|
-
imap.uid_store(
|
|
94
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find] && new_message.is_marked_for_delete?
|
|
95
|
+
break unless options[:uid].nil?
|
|
93
96
|
end
|
|
94
97
|
imap.expunge if options[:delete_after_find]
|
|
95
98
|
else
|
|
96
99
|
emails = []
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
uids.each do |uid|
|
|
101
|
+
uid = options[:uid].to_i unless options[:uid].nil?
|
|
102
|
+
fetchdata = imap.uid_fetch(uid, ['RFC822'])[0]
|
|
99
103
|
emails << Mail.new(fetchdata.attr['RFC822'])
|
|
100
|
-
imap.uid_store(
|
|
104
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find]
|
|
105
|
+
break unless options[:uid].nil?
|
|
101
106
|
end
|
|
102
107
|
imap.expunge if options[:delete_after_find]
|
|
103
108
|
emails.size == 1 && options[:count] == 1 ? emails.first : emails
|
|
@@ -111,8 +116,8 @@ module Mail
|
|
|
111
116
|
mailbox = Net::IMAP.encode_utf7(mailbox)
|
|
112
117
|
|
|
113
118
|
start do |imap|
|
|
114
|
-
imap.uid_search(['ALL']).each do |
|
|
115
|
-
imap.uid_store(
|
|
119
|
+
imap.uid_search(['ALL']).each do |uid|
|
|
120
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED])
|
|
116
121
|
end
|
|
117
122
|
imap.expunge
|
|
118
123
|
end
|
|
@@ -137,6 +142,7 @@ module Mail
|
|
|
137
142
|
options[:order] ||= :asc
|
|
138
143
|
options[:what] ||= :first
|
|
139
144
|
options[:keys] ||= 'ALL'
|
|
145
|
+
options[:uid] ||= nil
|
|
140
146
|
options[:delete_after_find] ||= false
|
|
141
147
|
options[:mailbox] = Net::IMAP.encode_utf7(options[:mailbox])
|
|
142
148
|
options[:read_only] ||= false
|
data/lib/mail/network.rb
CHANGED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class AddressListsParser
|
|
4
|
+
include Mail::Utilities
|
|
5
|
+
|
|
6
|
+
def parse(s)
|
|
7
|
+
address_list = AddressListStruct.new([],[])
|
|
8
|
+
|
|
9
|
+
if Mail::Utilities.blank?(s)
|
|
10
|
+
return address_list
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
actions, error = Ragel.parse(:address_lists, s)
|
|
14
|
+
if error
|
|
15
|
+
raise Mail::Field::ParseError.new(Mail::AddressList, s, error)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
phrase_s = phrase_e = qstr_s = qstr = comment_s = nil
|
|
20
|
+
group_name_s = domain_s = group_name = nil
|
|
21
|
+
local_dot_atom_s = local_dot_atom_e = nil
|
|
22
|
+
local_dot_atom_pre_comment_e = nil
|
|
23
|
+
obs_domain_list_s = nil
|
|
24
|
+
|
|
25
|
+
address_s = 0
|
|
26
|
+
address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
|
|
27
|
+
actions.each_slice(2) do |action_id, p|
|
|
28
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
29
|
+
case action
|
|
30
|
+
|
|
31
|
+
# Phrase
|
|
32
|
+
when :phrase_s then phrase_s = p
|
|
33
|
+
when :phrase_e then phrase_e = 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
|
+
# Comment
|
|
40
|
+
when :comment_s
|
|
41
|
+
comment_s = p unless comment_s
|
|
42
|
+
when :comment_e
|
|
43
|
+
if address
|
|
44
|
+
address.comments << s[comment_s..(p-2)]
|
|
45
|
+
end
|
|
46
|
+
comment_s = nil
|
|
47
|
+
|
|
48
|
+
# Group Name
|
|
49
|
+
when :group_name_s then group_name_s = p
|
|
50
|
+
when :group_name_e
|
|
51
|
+
if qstr
|
|
52
|
+
group = qstr
|
|
53
|
+
qstr = nil
|
|
54
|
+
else
|
|
55
|
+
group = s[group_name_s..(p-1)]
|
|
56
|
+
group_name_s = nil
|
|
57
|
+
end
|
|
58
|
+
address_list.group_names << group
|
|
59
|
+
group_name = group
|
|
60
|
+
|
|
61
|
+
# Start next address
|
|
62
|
+
address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
|
|
63
|
+
address_s = p
|
|
64
|
+
address.group = group_name
|
|
65
|
+
|
|
66
|
+
# Address
|
|
67
|
+
when :address_s
|
|
68
|
+
address_s = p
|
|
69
|
+
when :address_e
|
|
70
|
+
# Ignore address end events if they don't have
|
|
71
|
+
# a matching address start event.
|
|
72
|
+
next if address_s.nil?
|
|
73
|
+
if address.local.nil? && local_dot_atom_pre_comment_e && local_dot_atom_s && local_dot_atom_e
|
|
74
|
+
if address.domain
|
|
75
|
+
address.local = s[local_dot_atom_s..local_dot_atom_e] if address
|
|
76
|
+
else
|
|
77
|
+
address.local = s[local_dot_atom_s..local_dot_atom_pre_comment_e] if address
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
address.raw = s[address_s..(p-1)]
|
|
81
|
+
address_list.addresses << address if address
|
|
82
|
+
|
|
83
|
+
# Start next address
|
|
84
|
+
address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
|
|
85
|
+
address.group = group_name
|
|
86
|
+
address_s = nil
|
|
87
|
+
|
|
88
|
+
# Don't set the display name until the
|
|
89
|
+
# address has actually started. This allows
|
|
90
|
+
# us to choose quoted_s version if it
|
|
91
|
+
# exists and always use the 'full' phrase
|
|
92
|
+
# version.
|
|
93
|
+
when :angle_addr_s
|
|
94
|
+
if qstr
|
|
95
|
+
address.display_name = qstr
|
|
96
|
+
qstr = nil
|
|
97
|
+
elsif phrase_e
|
|
98
|
+
address.display_name = s[phrase_s..phrase_e].strip
|
|
99
|
+
phrase_e = phrase_s = nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Domain
|
|
103
|
+
when :domain_s
|
|
104
|
+
domain_s = p
|
|
105
|
+
when :domain_e
|
|
106
|
+
address.domain = s[domain_s..(p-1)].rstrip if address
|
|
107
|
+
|
|
108
|
+
# Local
|
|
109
|
+
when :local_dot_atom_s then local_dot_atom_s = p
|
|
110
|
+
when :local_dot_atom_e then local_dot_atom_e = p-1
|
|
111
|
+
when :local_dot_atom_pre_comment_e
|
|
112
|
+
local_dot_atom_pre_comment_e = p-1
|
|
113
|
+
when :local_quoted_string_e
|
|
114
|
+
address.local = '"' + qstr + '"' if address
|
|
115
|
+
|
|
116
|
+
# obs_domain_list
|
|
117
|
+
when :obs_domain_list_s then obs_domain_list_s = p
|
|
118
|
+
when :obs_domain_list_e
|
|
119
|
+
address.obs_domain_list = s[obs_domain_list_s..(p-1)]
|
|
120
|
+
|
|
121
|
+
else
|
|
122
|
+
raise Mail::Field::ParseError.new(Mail::AddressList, s, "Failed to process unknown action: #{action}")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if address_list.addresses.empty? && address_list.group_names.empty?
|
|
127
|
+
raise Mail::Field::ParseError.new(Mail::AddressList, s, "Didn't find any addresses or groups")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
address_list
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class ContentDispositionParser
|
|
4
|
+
include Mail::Utilities
|
|
5
|
+
|
|
6
|
+
def parse(s)
|
|
7
|
+
content_disposition = ContentDispositionStruct.new("", nil)
|
|
8
|
+
if Mail::Utilities.blank?(s)
|
|
9
|
+
return content_disposition
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
actions, error = Ragel.parse(:content_disposition, s)
|
|
13
|
+
if error
|
|
14
|
+
raise Mail::Field::ParseError.new(Mail::ContentDispositionElement, s, error)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
content_disposition.parameters = []
|
|
18
|
+
|
|
19
|
+
disp_type_s = param_attr_s = param_attr = qstr_s = qstr = param_val_s = nil
|
|
20
|
+
actions.each_slice(2) do |action_id, p|
|
|
21
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
22
|
+
case action
|
|
23
|
+
|
|
24
|
+
# Disposition Type
|
|
25
|
+
when :disp_type_s then disp_type_s = p
|
|
26
|
+
when :disp_type_e
|
|
27
|
+
content_disposition.disposition_type = s[disp_type_s..(p-1)].downcase
|
|
28
|
+
|
|
29
|
+
# Parameter Attribute
|
|
30
|
+
when :param_attr_s then param_attr_s = p
|
|
31
|
+
when :param_attr_e then param_attr = s[param_attr_s..(p-1)]
|
|
32
|
+
|
|
33
|
+
# Quoted String.
|
|
34
|
+
when :qstr_s then qstr_s = p
|
|
35
|
+
when :qstr_e then qstr = s[qstr_s..(p-1)]
|
|
36
|
+
|
|
37
|
+
# Parameter Value
|
|
38
|
+
when :param_val_s then param_val_s = p
|
|
39
|
+
when :param_val_e
|
|
40
|
+
if param_attr.nil?
|
|
41
|
+
raise Mail::Field::ParseError.new(Mail::ContentDispositionElement, s, "no attribute for value")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Use quoted string value if one exists, otherwise use parameter value
|
|
45
|
+
if qstr
|
|
46
|
+
value = qstr
|
|
47
|
+
else
|
|
48
|
+
value = s[param_val_s..(p-1)]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
content_disposition.parameters << { param_attr => value }
|
|
52
|
+
param_attr = nil
|
|
53
|
+
qstr = nil
|
|
54
|
+
|
|
55
|
+
else
|
|
56
|
+
raise Mail::Field::ParseError.new(Mail::ContentDispositionElement, s, "Failed to process unknown action: #{action}")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
content_disposition
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
def cleaned(string)
|
|
65
|
+
string =~ /(.+);\s*$/ ? $1 : string
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class ContentLocationParser
|
|
4
|
+
def parse(s)
|
|
5
|
+
content_location = ContentLocationStruct.new(nil)
|
|
6
|
+
if Mail::Utilities.blank?(s)
|
|
7
|
+
return content_location
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
actions, error = Ragel.parse(:content_location, s)
|
|
11
|
+
if error
|
|
12
|
+
raise Mail::Field::ParseError.new(Mail::ContentLocationElement, s, error)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
qstr_s = token_string_s = nil
|
|
16
|
+
actions.each_slice(2) do |action_id, p|
|
|
17
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
18
|
+
case action
|
|
19
|
+
|
|
20
|
+
# Quoted String.
|
|
21
|
+
when :qstr_s then qstr_s = p
|
|
22
|
+
when :qstr_e then content_location.location = s[qstr_s..(p-1)]
|
|
23
|
+
|
|
24
|
+
# Token String
|
|
25
|
+
when :token_string_s then token_string_s = p
|
|
26
|
+
when :token_string_e
|
|
27
|
+
content_location.location = s[token_string_s..(p-1)]
|
|
28
|
+
|
|
29
|
+
else
|
|
30
|
+
raise Mail::Field::ParseError.new(Mail::ContentLocationElement, s, "Failed to process unknown action: #{action}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
content_location
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class ContentTransferEncodingParser
|
|
4
|
+
|
|
5
|
+
def parse(s)
|
|
6
|
+
content_transfer_encoding = ContentTransferEncodingStruct.new("")
|
|
7
|
+
if Mail::Utilities.blank?(s)
|
|
8
|
+
return content_transfer_encoding
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
actions, error = Ragel.parse(:content_transfer_encoding, s)
|
|
12
|
+
if error
|
|
13
|
+
raise Mail::Field::ParseError.new(Mail::ContentTransferEncodingElement, s, error)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
encoding_s = nil
|
|
17
|
+
actions.each_slice(2) do |action_id, p|
|
|
18
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
19
|
+
case action
|
|
20
|
+
|
|
21
|
+
# Encoding
|
|
22
|
+
when :encoding_s then encoding_s = p
|
|
23
|
+
when :encoding_e
|
|
24
|
+
content_transfer_encoding.encoding = s[encoding_s..(p-1)].downcase
|
|
25
|
+
|
|
26
|
+
else
|
|
27
|
+
raise Mail::Field::ParseError.new(Mail::ContentTransferEncodingElement, s, "Failed to process unknown action: #{action}")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
content_transfer_encoding
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class ContentTypeParser
|
|
4
|
+
include Mail::Utilities
|
|
5
|
+
|
|
6
|
+
def parse(s)
|
|
7
|
+
actions, error = Ragel.parse(:content_type, s)
|
|
8
|
+
if error
|
|
9
|
+
raise Mail::Field::ParseError.new(Mail::ContentTypeElement, s, error)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
content_type = ContentTypeStruct.new(nil,nil,[])
|
|
13
|
+
|
|
14
|
+
content_type.parameters = []
|
|
15
|
+
|
|
16
|
+
main_type_s = sub_type_s = param_attr_s = param_attr = nil
|
|
17
|
+
qstr_s = qstr = param_val_s = nil
|
|
18
|
+
actions.each_slice(2) do |action_id, p|
|
|
19
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
20
|
+
case action
|
|
21
|
+
|
|
22
|
+
# Main Type
|
|
23
|
+
when :main_type_s then main_type_s = p
|
|
24
|
+
when :main_type_e then
|
|
25
|
+
content_type.main_type = s[main_type_s..(p-1)]
|
|
26
|
+
content_type.main_type.downcase!
|
|
27
|
+
|
|
28
|
+
# Sub Type
|
|
29
|
+
when :sub_type_s then sub_type_s = p
|
|
30
|
+
when :sub_type_e
|
|
31
|
+
content_type.sub_type = s[sub_type_s..(p-1)]
|
|
32
|
+
content_type.sub_type.downcase!
|
|
33
|
+
|
|
34
|
+
# Parameter Attribute
|
|
35
|
+
when :param_attr_s then param_attr_s = p
|
|
36
|
+
when :param_attr_e then param_attr = s[param_attr_s..(p-1)]
|
|
37
|
+
|
|
38
|
+
# Quoted String.
|
|
39
|
+
when :qstr_s then qstr_s = p
|
|
40
|
+
when :qstr_e then qstr = s[qstr_s..(p-1)]
|
|
41
|
+
|
|
42
|
+
# Parameter Value
|
|
43
|
+
when :param_val_s then param_val_s = p
|
|
44
|
+
when :param_val_e
|
|
45
|
+
if param_attr.nil?
|
|
46
|
+
raise Mail::Field::ParseError.new(Mail::ContentTypeElement, s, "no attribute for value")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Use quoted s value if one exists, otherwise use parameter value
|
|
50
|
+
if qstr
|
|
51
|
+
value = qstr
|
|
52
|
+
else
|
|
53
|
+
value = s[param_val_s..(p-1)]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
content_type.parameters << { param_attr => value }
|
|
57
|
+
param_attr = nil
|
|
58
|
+
qstr = nil
|
|
59
|
+
|
|
60
|
+
else
|
|
61
|
+
raise Mail::Field::ParseError.new(Mail::ContentTypeElement, s, "Failed to process unknown action: #{action}")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
content_type
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class DateTimeParser
|
|
4
|
+
include Mail::Utilities
|
|
5
|
+
|
|
6
|
+
def parse(s)
|
|
7
|
+
raise Mail::Field::ParseError.new(Mail::DateTimeElement, s, "nil is an invalid DateTime") if s.nil?
|
|
8
|
+
|
|
9
|
+
date_time = DateTimeStruct.new([])
|
|
10
|
+
|
|
11
|
+
actions, error = Ragel.parse(:date_time, s)
|
|
12
|
+
if error
|
|
13
|
+
raise Mail::Field::ParseError.new(Mail::DateTimeElement, s, error)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
date_s = time_s = nil
|
|
17
|
+
actions.each_slice(2) do |action_id, p|
|
|
18
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
19
|
+
case action
|
|
20
|
+
|
|
21
|
+
# Date
|
|
22
|
+
when :date_s then date_s = p
|
|
23
|
+
when :date_e
|
|
24
|
+
date_time.date_string = s[date_s..(p-1)]
|
|
25
|
+
|
|
26
|
+
# Time
|
|
27
|
+
when :time_s then time_s = p
|
|
28
|
+
when :time_e
|
|
29
|
+
date_time.time_string = s[time_s..(p-1)]
|
|
30
|
+
|
|
31
|
+
else
|
|
32
|
+
raise Mail::Field::ParseError.new(Mail::DateTimeElement, s, "Failed to process unknown action: #{action}")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
date_time
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mail::Parsers
|
|
3
|
+
class EnvelopeFromParser
|
|
4
|
+
def parse(s)
|
|
5
|
+
envelope_from = EnvelopeFromStruct.new
|
|
6
|
+
if Mail::Utilities.blank?(s)
|
|
7
|
+
return envelope_from
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
actions, error = Ragel.parse(:envelope_from, s)
|
|
11
|
+
if error
|
|
12
|
+
raise Mail::Field::ParseError.new(Mail::EnvelopeFromElement, s, error)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
address_s = ctime_date_s = nil
|
|
16
|
+
envelope_from = EnvelopeFromStruct.new
|
|
17
|
+
actions.each_slice(2) do |action_id, p|
|
|
18
|
+
action = Mail::Parsers::Ragel::ACTIONS[action_id]
|
|
19
|
+
case action
|
|
20
|
+
|
|
21
|
+
# Address
|
|
22
|
+
when :address_s then address_s = p
|
|
23
|
+
when :address_e
|
|
24
|
+
envelope_from.address = s[address_s..(p-1)].rstrip
|
|
25
|
+
|
|
26
|
+
# ctime_date
|
|
27
|
+
when :ctime_date_s then ctime_date_s = p
|
|
28
|
+
when :ctime_date_e
|
|
29
|
+
envelope_from.ctime_date = s[ctime_date_s..(p-1)]
|
|
30
|
+
|
|
31
|
+
# ignored actions
|
|
32
|
+
when :angle_addr_s, :comment_e, :comment_s,
|
|
33
|
+
:domain_e, :domain_s, :local_dot_atom_e,
|
|
34
|
+
:local_dot_atom_pre_comment_e,
|
|
35
|
+
:local_dot_atom_pre_comment_s,
|
|
36
|
+
:local_dot_atom_s, :qstr_e, :qstr_s
|
|
37
|
+
nil
|
|
38
|
+
|
|
39
|
+
else
|
|
40
|
+
raise Mail::Field::ParseError.new(Mail::EnvelopeFromElement, s, "Failed to process unknown action: #{action}")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
envelope_from
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|