nano-fast-tool 0.0.1
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/mail-2.9.1/MIT-LICENSE +20 -0
- data/mail-2.9.1/README.md +771 -0
- data/mail-2.9.1/lib/mail/attachments_list.rb +109 -0
- data/mail-2.9.1/lib/mail/body.rb +305 -0
- data/mail-2.9.1/lib/mail/configuration.rb +78 -0
- data/mail-2.9.1/lib/mail/constants.rb +79 -0
- data/mail-2.9.1/lib/mail/elements/address.rb +258 -0
- data/mail-2.9.1/lib/mail/elements/address_list.rb +34 -0
- data/mail-2.9.1/lib/mail/elements/content_disposition_element.rb +20 -0
- data/mail-2.9.1/lib/mail/elements/content_location_element.rb +17 -0
- data/mail-2.9.1/lib/mail/elements/content_transfer_encoding_element.rb +13 -0
- data/mail-2.9.1/lib/mail/elements/content_type_element.rb +25 -0
- data/mail-2.9.1/lib/mail/elements/date_time_element.rb +15 -0
- data/mail-2.9.1/lib/mail/elements/envelope_from_element.rb +39 -0
- data/mail-2.9.1/lib/mail/elements/message_ids_element.rb +31 -0
- data/mail-2.9.1/lib/mail/elements/mime_version_element.rb +15 -0
- data/mail-2.9.1/lib/mail/elements/phrase_list.rb +19 -0
- data/mail-2.9.1/lib/mail/elements/received_element.rb +35 -0
- data/mail-2.9.1/lib/mail/elements.rb +15 -0
- data/mail-2.9.1/lib/mail/encodings/7bit.rb +27 -0
- data/mail-2.9.1/lib/mail/encodings/8bit.rb +18 -0
- data/mail-2.9.1/lib/mail/encodings/base64.rb +38 -0
- data/mail-2.9.1/lib/mail/encodings/binary.rb +13 -0
- data/mail-2.9.1/lib/mail/encodings/identity.rb +24 -0
- data/mail-2.9.1/lib/mail/encodings/quoted_printable.rb +45 -0
- data/mail-2.9.1/lib/mail/encodings/transfer_encoding.rb +77 -0
- data/mail-2.9.1/lib/mail/encodings/unix_to_unix.rb +20 -0
- data/mail-2.9.1/lib/mail/encodings.rb +314 -0
- data/mail-2.9.1/lib/mail/envelope.rb +28 -0
- data/mail-2.9.1/lib/mail/field.rb +313 -0
- data/mail-2.9.1/lib/mail/field_list.rb +87 -0
- data/mail-2.9.1/lib/mail/fields/bcc_field.rb +49 -0
- data/mail-2.9.1/lib/mail/fields/cc_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/comments_field.rb +31 -0
- data/mail-2.9.1/lib/mail/fields/common_address_field.rb +162 -0
- data/mail-2.9.1/lib/mail/fields/common_date_field.rb +56 -0
- data/mail-2.9.1/lib/mail/fields/common_field.rb +77 -0
- data/mail-2.9.1/lib/mail/fields/common_message_id_field.rb +41 -0
- data/mail-2.9.1/lib/mail/fields/content_description_field.rb +12 -0
- data/mail-2.9.1/lib/mail/fields/content_disposition_field.rb +44 -0
- data/mail-2.9.1/lib/mail/fields/content_id_field.rb +35 -0
- data/mail-2.9.1/lib/mail/fields/content_location_field.rb +28 -0
- data/mail-2.9.1/lib/mail/fields/content_transfer_encoding_field.rb +44 -0
- data/mail-2.9.1/lib/mail/fields/content_type_field.rb +171 -0
- data/mail-2.9.1/lib/mail/fields/date_field.rb +28 -0
- data/mail-2.9.1/lib/mail/fields/from_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/in_reply_to_field.rb +45 -0
- data/mail-2.9.1/lib/mail/fields/keywords_field.rb +30 -0
- data/mail-2.9.1/lib/mail/fields/message_id_field.rb +36 -0
- data/mail-2.9.1/lib/mail/fields/mime_version_field.rb +42 -0
- data/mail-2.9.1/lib/mail/fields/named_structured_field.rb +10 -0
- data/mail-2.9.1/lib/mail/fields/named_unstructured_field.rb +10 -0
- data/mail-2.9.1/lib/mail/fields/optional_field.rb +15 -0
- data/mail-2.9.1/lib/mail/fields/parameter_hash.rb +61 -0
- data/mail-2.9.1/lib/mail/fields/received_field.rb +61 -0
- data/mail-2.9.1/lib/mail/fields/references_field.rb +42 -0
- data/mail-2.9.1/lib/mail/fields/reply_to_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/resent_bcc_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/resent_cc_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/resent_date_field.rb +10 -0
- data/mail-2.9.1/lib/mail/fields/resent_from_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/resent_message_id_field.rb +10 -0
- data/mail-2.9.1/lib/mail/fields/resent_sender_field.rb +32 -0
- data/mail-2.9.1/lib/mail/fields/resent_to_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/return_path_field.rb +60 -0
- data/mail-2.9.1/lib/mail/fields/sender_field.rb +45 -0
- data/mail-2.9.1/lib/mail/fields/structured_field.rb +24 -0
- data/mail-2.9.1/lib/mail/fields/subject_field.rb +14 -0
- data/mail-2.9.1/lib/mail/fields/to_field.rb +33 -0
- data/mail-2.9.1/lib/mail/fields/unstructured_field.rb +189 -0
- data/mail-2.9.1/lib/mail/fields.rb +45 -0
- data/mail-2.9.1/lib/mail/header.rb +237 -0
- data/mail-2.9.1/lib/mail/indifferent_hash.rb +147 -0
- data/mail-2.9.1/lib/mail/mail.rb +267 -0
- data/mail-2.9.1/lib/mail/matchers/attachment_matchers.rb +44 -0
- data/mail-2.9.1/lib/mail/matchers/has_sent_mail.rb +201 -0
- data/mail-2.9.1/lib/mail/message.rb +2159 -0
- data/mail-2.9.1/lib/mail/multibyte/chars.rb +318 -0
- data/mail-2.9.1/lib/mail/multibyte/unicode.rb +405 -0
- data/mail-2.9.1/lib/mail/multibyte/utils.rb +44 -0
- data/mail-2.9.1/lib/mail/multibyte.rb +82 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/exim.rb +50 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/file_delivery.rb +43 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/sendmail.rb +87 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/smtp.rb +200 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/smtp_connection.rb +57 -0
- data/mail-2.9.1/lib/mail/network/delivery_methods/test_mailer.rb +44 -0
- data/mail-2.9.1/lib/mail/network/retriever_methods/base.rb +64 -0
- data/mail-2.9.1/lib/mail/network/retriever_methods/imap.rb +190 -0
- data/mail-2.9.1/lib/mail/network/retriever_methods/pop3.rb +143 -0
- data/mail-2.9.1/lib/mail/network/retriever_methods/test_retriever.rb +45 -0
- data/mail-2.9.1/lib/mail/network.rb +16 -0
- data/mail-2.9.1/lib/mail/parser_tools.rb +15 -0
- data/mail-2.9.1/lib/mail/parsers/address_lists_parser.rb +33245 -0
- data/mail-2.9.1/lib/mail/parsers/address_lists_parser.rl +183 -0
- data/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rb +904 -0
- data/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rl +93 -0
- data/mail-2.9.1/lib/mail/parsers/content_location_parser.rb +825 -0
- data/mail-2.9.1/lib/mail/parsers/content_location_parser.rl +82 -0
- data/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rb +525 -0
- data/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
- data/mail-2.9.1/lib/mail/parsers/content_type_parser.rb +1051 -0
- data/mail-2.9.1/lib/mail/parsers/content_type_parser.rl +94 -0
- data/mail-2.9.1/lib/mail/parsers/date_time_parser.rb +894 -0
- data/mail-2.9.1/lib/mail/parsers/date_time_parser.rl +73 -0
- data/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rb +3678 -0
- data/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rl +93 -0
- data/mail-2.9.1/lib/mail/parsers/message_ids_parser.rb +5164 -0
- data/mail-2.9.1/lib/mail/parsers/message_ids_parser.rl +97 -0
- data/mail-2.9.1/lib/mail/parsers/mime_version_parser.rb +516 -0
- data/mail-2.9.1/lib/mail/parsers/mime_version_parser.rl +72 -0
- data/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rb +887 -0
- data/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rl +94 -0
- data/mail-2.9.1/lib/mail/parsers/received_parser.rb +8785 -0
- data/mail-2.9.1/lib/mail/parsers/received_parser.rl +95 -0
- data/mail-2.9.1/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
- data/mail-2.9.1/lib/mail/parsers/rfc2045_content_type.rl +25 -0
- data/mail-2.9.1/lib/mail/parsers/rfc2045_mime.rl +16 -0
- data/mail-2.9.1/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
- data/mail-2.9.1/lib/mail/parsers/rfc3629_utf8.rl +19 -0
- data/mail-2.9.1/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
- data/mail-2.9.1/lib/mail/parsers/rfc5322.rl +74 -0
- data/mail-2.9.1/lib/mail/parsers/rfc5322_address.rl +72 -0
- data/mail-2.9.1/lib/mail/parsers/rfc5322_date_time.rl +37 -0
- data/mail-2.9.1/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
- data/mail-2.9.1/lib/mail/parsers.rb +13 -0
- data/mail-2.9.1/lib/mail/part.rb +119 -0
- data/mail-2.9.1/lib/mail/parts_list.rb +131 -0
- data/mail-2.9.1/lib/mail/smtp_envelope.rb +57 -0
- data/mail-2.9.1/lib/mail/utilities.rb +576 -0
- data/mail-2.9.1/lib/mail/values/unicode_tables.dat +0 -0
- data/mail-2.9.1/lib/mail/version.rb +17 -0
- data/mail-2.9.1/lib/mail/yaml.rb +30 -0
- data/mail-2.9.1/lib/mail.rb +65 -0
- data/nano-fast-tool.gemspec +12 -0
- metadata +177 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'mail/utilities'
|
|
2
|
+
|
|
3
|
+
module Mail
|
|
4
|
+
class CommonDateField < NamedStructuredField #:nodoc:
|
|
5
|
+
def self.singular?
|
|
6
|
+
true
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.normalize_datetime(string)
|
|
10
|
+
if Utilities.blank?(string)
|
|
11
|
+
datetime = ::DateTime.now
|
|
12
|
+
else
|
|
13
|
+
stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
|
|
14
|
+
begin
|
|
15
|
+
datetime = ::DateTime.parse(stripped)
|
|
16
|
+
rescue ArgumentError => e
|
|
17
|
+
raise unless 'invalid date' == e.message
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if datetime
|
|
22
|
+
datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
|
|
23
|
+
else
|
|
24
|
+
string
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(value = nil, charset = nil)
|
|
29
|
+
super self.class.normalize_datetime(value), charset
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Returns a date time object of the parsed date
|
|
33
|
+
def date_time
|
|
34
|
+
::DateTime.parse("#{element.date_string} #{element.time_string}")
|
|
35
|
+
rescue ArgumentError => e
|
|
36
|
+
raise e unless e.message == 'invalid date'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def default
|
|
40
|
+
date_time
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def element
|
|
44
|
+
@element ||= Mail::DateTimeElement.new(value)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
def do_encode
|
|
49
|
+
"#{name}: #{value}\r\n"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def do_decode
|
|
53
|
+
value.to_s
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
require 'mail/constants'
|
|
4
|
+
|
|
5
|
+
module Mail
|
|
6
|
+
class CommonField #:nodoc:
|
|
7
|
+
def self.singular?
|
|
8
|
+
false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.parse(*args)
|
|
12
|
+
new(*args).tap(&:parse)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_accessor :name
|
|
16
|
+
attr_reader :value
|
|
17
|
+
attr_accessor :charset
|
|
18
|
+
attr_reader :errors
|
|
19
|
+
|
|
20
|
+
def initialize(name = nil, value = nil, charset = nil)
|
|
21
|
+
@errors = []
|
|
22
|
+
|
|
23
|
+
self.name = name
|
|
24
|
+
self.value = value
|
|
25
|
+
self.charset = charset || 'utf-8'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def singular?
|
|
29
|
+
self.class.singular?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def value=(value)
|
|
33
|
+
@element = nil
|
|
34
|
+
@value = value.is_a?(Array) ? value : value.to_s
|
|
35
|
+
parse
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parse
|
|
39
|
+
tap(&:element)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def element
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_s
|
|
47
|
+
decoded.to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def default
|
|
51
|
+
decoded
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def decoded
|
|
55
|
+
do_decode
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def encoded
|
|
59
|
+
do_encode
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def responsible_for?(field_name)
|
|
63
|
+
name.to_s.casecmp(field_name.to_s) == 0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
|
|
69
|
+
def ensure_filename_quoted(value)
|
|
70
|
+
if value.is_a?(String)
|
|
71
|
+
value.sub FILENAME_RE, '\1="\2"'
|
|
72
|
+
else
|
|
73
|
+
value
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
require 'mail/utilities'
|
|
4
|
+
|
|
5
|
+
module Mail
|
|
6
|
+
class CommonMessageIdField < NamedStructuredField #:nodoc:
|
|
7
|
+
def element
|
|
8
|
+
@element ||= Mail::MessageIdsElement.new(value)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def message_id
|
|
12
|
+
element.message_id
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def message_ids
|
|
16
|
+
element.message_ids
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def default
|
|
20
|
+
ids = message_ids
|
|
21
|
+
ids.one? ? ids.first : ids
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_s
|
|
25
|
+
decoded.to_s
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
def do_encode
|
|
30
|
+
%Q{#{name}: #{formatted_message_ids("\r\n ")}\r\n}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def do_decode
|
|
34
|
+
formatted_message_ids
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def formatted_message_ids(join = ' ')
|
|
38
|
+
message_ids.map { |m| "<#{m}>" }.join(join) if message_ids.any?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
class ContentDispositionField < NamedStructuredField #:nodoc:
|
|
6
|
+
NAME = 'Content-Disposition'
|
|
7
|
+
|
|
8
|
+
def self.singular?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(value = nil, charset = nil)
|
|
13
|
+
super ensure_filename_quoted(value), charset
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def element
|
|
17
|
+
@element ||= Mail::ContentDispositionElement.new(value)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def disposition_type
|
|
21
|
+
element.disposition_type
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def parameters
|
|
25
|
+
@parameters = ParameterHash.new
|
|
26
|
+
element.parameters.each { |p| @parameters.merge!(p) } unless element.parameters.nil?
|
|
27
|
+
@parameters
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def filename
|
|
31
|
+
@filename ||= parameters['filename'] || parameters['name']
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def encoded
|
|
35
|
+
p = ";\r\n\s#{parameters.encoded}" if parameters.length > 0
|
|
36
|
+
"#{name}: #{disposition_type}#{p}\r\n"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def decoded
|
|
40
|
+
p = "; #{parameters.decoded}" if parameters.length > 0
|
|
41
|
+
"#{disposition_type}#{p}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
require 'mail/utilities'
|
|
4
|
+
|
|
5
|
+
module Mail
|
|
6
|
+
class ContentIdField < NamedStructuredField #:nodoc:
|
|
7
|
+
NAME = 'Content-ID'
|
|
8
|
+
|
|
9
|
+
def self.singular?
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(value = nil, charset = nil)
|
|
14
|
+
value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
|
|
15
|
+
super value, charset
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def element
|
|
19
|
+
@element ||= Mail::MessageIdsElement.new(value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def content_id
|
|
23
|
+
element.message_id
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def do_decode
|
|
28
|
+
"<#{content_id}>"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def do_encode
|
|
32
|
+
"#{name}: #{do_decode}\r\n"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
class ContentLocationField < NamedStructuredField #:nodoc:
|
|
6
|
+
NAME = 'Content-Location'
|
|
7
|
+
|
|
8
|
+
def self.singular?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def element
|
|
13
|
+
@element ||= Mail::ContentLocationElement.new(value)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def location
|
|
17
|
+
element.location
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def encoded
|
|
21
|
+
"#{name}: #{location}\r\n"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def decoded
|
|
25
|
+
location
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
class ContentTransferEncodingField < NamedStructuredField #:nodoc:
|
|
6
|
+
NAME = 'Content-Transfer-Encoding'
|
|
7
|
+
|
|
8
|
+
def self.singular?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.normalize_content_transfer_encoding(value)
|
|
13
|
+
case value
|
|
14
|
+
when /7-?bits?/i
|
|
15
|
+
'7bit'
|
|
16
|
+
when /8-?bits?/i
|
|
17
|
+
'8bit'
|
|
18
|
+
else
|
|
19
|
+
value
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def initialize(value = nil, charset = nil)
|
|
24
|
+
super self.class.normalize_content_transfer_encoding(value), charset
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def element
|
|
28
|
+
@element ||= Mail::ContentTransferEncodingElement.new(value)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def encoding
|
|
32
|
+
element.encoding
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
def do_encode
|
|
37
|
+
"#{name}: #{encoding}\r\n"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def do_decode
|
|
41
|
+
encoding
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
class ContentTypeField < NamedStructuredField #:nodoc:
|
|
6
|
+
NAME = 'Content-Type'
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def singular?
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def with_boundary(type)
|
|
14
|
+
new "#{type}; boundary=#{generate_boundary}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def generate_boundary
|
|
18
|
+
"--==_mimepart_#{Mail.random_tag}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(value = nil, charset = nil)
|
|
23
|
+
if value.is_a? Array
|
|
24
|
+
@main_type = value[0]
|
|
25
|
+
@sub_type = value[1]
|
|
26
|
+
@parameters = ParameterHash.new.merge!(value.last)
|
|
27
|
+
else
|
|
28
|
+
@main_type = nil
|
|
29
|
+
@sub_type = nil
|
|
30
|
+
value = value.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
super ensure_filename_quoted(value), charset
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def element
|
|
37
|
+
@element ||=
|
|
38
|
+
begin
|
|
39
|
+
Mail::ContentTypeElement.new(value)
|
|
40
|
+
rescue Mail::Field::ParseError
|
|
41
|
+
attempt_to_clean
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def attempt_to_clean
|
|
46
|
+
# Sanitize the value, handle special cases
|
|
47
|
+
Mail::ContentTypeElement.new(sanitize(value))
|
|
48
|
+
rescue Mail::Field::ParseError
|
|
49
|
+
# All else fails, just get the MIME media type
|
|
50
|
+
Mail::ContentTypeElement.new(get_mime_type(value))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def main_type
|
|
54
|
+
@main_type ||= element.main_type
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def sub_type
|
|
58
|
+
@sub_type ||= element.sub_type
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def string
|
|
62
|
+
"#{main_type}/#{sub_type}"
|
|
63
|
+
end
|
|
64
|
+
alias_method :content_type, :string
|
|
65
|
+
|
|
66
|
+
def default
|
|
67
|
+
decoded
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def parameters
|
|
71
|
+
unless defined? @parameters
|
|
72
|
+
@parameters = ParameterHash.new
|
|
73
|
+
element.parameters.each { |p| @parameters.merge!(p) }
|
|
74
|
+
end
|
|
75
|
+
@parameters
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def value
|
|
79
|
+
if @value.is_a? Array
|
|
80
|
+
"#{@main_type}/#{@sub_type}; #{stringify(parameters)}"
|
|
81
|
+
else
|
|
82
|
+
@value
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def stringify(params)
|
|
87
|
+
params.map { |k,v| "#{k}=#{Encodings.param_encode(v)}" }.join("; ")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def filename
|
|
91
|
+
@filename ||= parameters['filename'] || parameters['name']
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def encoded
|
|
95
|
+
p = ";\r\n\s#{parameters.encoded}" if parameters && parameters.length > 0
|
|
96
|
+
"#{name}: #{content_type}#{p}\r\n"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def decoded
|
|
100
|
+
p = "; #{parameters.decoded}" if parameters && parameters.length > 0
|
|
101
|
+
"#{content_type}#{p}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def method_missing(name, *args, &block)
|
|
107
|
+
if name.to_s =~ /(\w+)=/
|
|
108
|
+
self.parameters[$1] = args.first
|
|
109
|
+
@value = "#{content_type}; #{stringify(parameters)}"
|
|
110
|
+
else
|
|
111
|
+
super
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Various special cases from random emails found that I am not going to change
|
|
116
|
+
# the parser for
|
|
117
|
+
def sanitize(val)
|
|
118
|
+
# TODO: check if there are cases where whitespace is not a separator
|
|
119
|
+
val = val.
|
|
120
|
+
gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
|
|
121
|
+
gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL)
|
|
122
|
+
gsub(/;\s*$/,'') #remove trailing to keep examples below
|
|
123
|
+
|
|
124
|
+
if val =~ /((boundary|name|filename)=(\S*))/i
|
|
125
|
+
val = "#{$`.downcase}#{$2}=#{$3}#{$'.downcase}"
|
|
126
|
+
else
|
|
127
|
+
val.downcase!
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
val_chomp = val.chomp
|
|
131
|
+
case
|
|
132
|
+
when val_chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
|
|
133
|
+
# Microsoft helper:
|
|
134
|
+
# Handles 'type/subtype;ISO-8559-1'
|
|
135
|
+
"#{$1}/#{$2}; charset=#{Utilities.quote_atom($3)}"
|
|
136
|
+
when /^text;?$/i.match?(val_chomp)
|
|
137
|
+
# Handles 'text;' and 'text'
|
|
138
|
+
"text/plain;"
|
|
139
|
+
when val_chomp =~ /^(\w+);\s(.*)$/i
|
|
140
|
+
# Handles 'text; <parameters>'
|
|
141
|
+
"text/plain; #{$2}"
|
|
142
|
+
when val =~ /([\w\-]+\/[\w\-]+);\scharset="charset="(\w+)""/i
|
|
143
|
+
# Handles text/html; charset="charset="GB2312""
|
|
144
|
+
"#{$1}; charset=#{Utilities.quote_atom($2)}"
|
|
145
|
+
when val =~ /([\w\-]+\/[\w\-]+);\s+(.*)/i
|
|
146
|
+
type = $1
|
|
147
|
+
# Handles misquoted param values
|
|
148
|
+
# e.g: application/octet-stream; name=archiveshelp1[1].htm
|
|
149
|
+
# and: audio/x-midi;\r\n\sname=Part .exe
|
|
150
|
+
params = $2.to_s.split(/\s+/)
|
|
151
|
+
params = params.map { |i| i.to_s.chomp.strip }
|
|
152
|
+
params = params.map { |i| i.split(/\s*\=\s*/, 2) }
|
|
153
|
+
params = params.map { |i| "#{i[0]}=#{Utilities.dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
|
|
154
|
+
"#{type}; #{params}"
|
|
155
|
+
when /^\s*$/.match?(val)
|
|
156
|
+
'text/plain'
|
|
157
|
+
else
|
|
158
|
+
val
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def get_mime_type(val)
|
|
163
|
+
case val
|
|
164
|
+
when /^([\w\-]+)\/([\w\-]+);.+$/i
|
|
165
|
+
"#{$1}/#{$2}"
|
|
166
|
+
else
|
|
167
|
+
'text/plain'
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
# = Date Field
|
|
6
|
+
#
|
|
7
|
+
# The Date field inherits from StructuredField and handles the Date: header
|
|
8
|
+
# field in the email.
|
|
9
|
+
#
|
|
10
|
+
# Sending date to a mail message will instantiate a Mail::Field object that
|
|
11
|
+
# has a DateField as its field type. This includes all Mail::CommonAddress
|
|
12
|
+
# module instance methods.
|
|
13
|
+
#
|
|
14
|
+
# There must be excatly one Date field in an RFC2822 email.
|
|
15
|
+
#
|
|
16
|
+
# == Examples:
|
|
17
|
+
#
|
|
18
|
+
# mail = Mail.new
|
|
19
|
+
# mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
|
|
20
|
+
# mail.date #=> #<DateTime: 211747170121/86400,-1/3,2299161>
|
|
21
|
+
# mail.date.to_s #=> 'Mon, 24 Nov 1997 14:22:01 -0800'
|
|
22
|
+
# mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
|
|
23
|
+
# mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
|
|
24
|
+
# mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
|
|
25
|
+
class DateField < CommonDateField #:nodoc:
|
|
26
|
+
NAME = 'Date'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
# = From Field
|
|
6
|
+
#
|
|
7
|
+
# The From field inherits from StructuredField and handles the From: header
|
|
8
|
+
# field in the email.
|
|
9
|
+
#
|
|
10
|
+
# Sending from to a mail message will instantiate a Mail::Field object that
|
|
11
|
+
# has a FromField as its field type. This includes all Mail::CommonAddress
|
|
12
|
+
# module instance metods.
|
|
13
|
+
#
|
|
14
|
+
# Only one From field can appear in a header, though it can have multiple
|
|
15
|
+
# addresses and groups of addresses.
|
|
16
|
+
#
|
|
17
|
+
# == Examples:
|
|
18
|
+
#
|
|
19
|
+
# mail = Mail.new
|
|
20
|
+
# mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
21
|
+
# mail.from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
22
|
+
# mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
|
|
23
|
+
# mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
|
|
24
|
+
# mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
|
|
25
|
+
#
|
|
26
|
+
# mail[:from].encoded #=> 'from: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
|
|
27
|
+
# mail[:from].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
|
|
28
|
+
# mail[:from].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
|
|
29
|
+
# mail[:from].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
|
|
30
|
+
class FromField < CommonAddressField #:nodoc:
|
|
31
|
+
NAME = 'From'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
# = In-Reply-To Field
|
|
6
|
+
#
|
|
7
|
+
# The In-Reply-To field inherits from StructuredField and handles the
|
|
8
|
+
# In-Reply-To: header field in the email.
|
|
9
|
+
#
|
|
10
|
+
# Sending in_reply_to to a mail message will instantiate a Mail::Field object that
|
|
11
|
+
# has a InReplyToField as its field type. This includes all Mail::CommonMessageId
|
|
12
|
+
# module instance metods.
|
|
13
|
+
#
|
|
14
|
+
# Note that, the #message_ids method will return an array of message IDs without the
|
|
15
|
+
# enclosing angle brackets which per RFC are not syntactically part of the message id.
|
|
16
|
+
#
|
|
17
|
+
# Only one InReplyTo field can appear in a header, though it can have multiple
|
|
18
|
+
# Message IDs.
|
|
19
|
+
#
|
|
20
|
+
# == Examples:
|
|
21
|
+
#
|
|
22
|
+
# mail = Mail.new
|
|
23
|
+
# mail.in_reply_to = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
|
|
24
|
+
# mail.in_reply_to #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
|
|
25
|
+
# mail[:in_reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
|
|
26
|
+
# mail['in_reply_to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
|
|
27
|
+
# mail['In-Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
|
|
28
|
+
#
|
|
29
|
+
# mail[:in_reply_to].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
|
|
30
|
+
class InReplyToField < CommonMessageIdField #:nodoc:
|
|
31
|
+
NAME = 'In-Reply-To'
|
|
32
|
+
|
|
33
|
+
def self.singular?
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize(value = nil, charset = nil)
|
|
38
|
+
if value.is_a?(Array)
|
|
39
|
+
super value.join("\r\n\s"), charset
|
|
40
|
+
else
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Mail
|
|
5
|
+
# keywords = "Keywords:" phrase *("," phrase) CRLF
|
|
6
|
+
class KeywordsField < NamedStructuredField #:nodoc:
|
|
7
|
+
NAME = 'Keywords'
|
|
8
|
+
|
|
9
|
+
def element
|
|
10
|
+
@element ||= PhraseList.new(value)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def keywords
|
|
14
|
+
element.phrases
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def default
|
|
18
|
+
keywords
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
def do_decode
|
|
23
|
+
keywords.join(', ')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def do_encode
|
|
27
|
+
"#{name}: #{keywords.join(",\r\n ")}\r\n"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
require 'mail/utilities'
|
|
4
|
+
|
|
5
|
+
module Mail
|
|
6
|
+
# Only one Message-ID field may appear in a header.
|
|
7
|
+
#
|
|
8
|
+
# Note that parsed Message IDs do not contain their enclosing angle
|
|
9
|
+
# brackets which, per RFC, are not part of the ID.
|
|
10
|
+
#
|
|
11
|
+
# mail = Mail.new
|
|
12
|
+
# mail.message_id = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
|
|
13
|
+
# mail.message_id #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
|
|
14
|
+
# mail[:message_id] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
|
|
15
|
+
# mail['message_id'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
|
|
16
|
+
# mail['Message-ID'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
|
|
17
|
+
#
|
|
18
|
+
# mail[:message_id].message_id #=> 'F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom'
|
|
19
|
+
# mail[:message_id].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
|
|
20
|
+
class MessageIdField < CommonMessageIdField #:nodoc:
|
|
21
|
+
NAME = 'Message-ID'
|
|
22
|
+
|
|
23
|
+
def self.singular?
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize(value = nil, charset = nil)
|
|
28
|
+
value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
|
|
29
|
+
super value, charset
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def message_ids
|
|
33
|
+
[message_id]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|