mail 2.5.5 → 2.8.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 +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +170 -108
- data/lib/mail/attachments_list.rb +13 -10
- data/lib/mail/body.rb +105 -91
- data/lib/mail/check_delivery_params.rb +30 -22
- data/lib/mail/configuration.rb +3 -0
- data/lib/mail/constants.rb +79 -0
- data/lib/mail/elements/address.rb +118 -174
- data/lib/mail/elements/address_list.rb +16 -56
- data/lib/mail/elements/content_disposition_element.rb +12 -22
- data/lib/mail/elements/content_location_element.rb +9 -17
- data/lib/mail/elements/content_transfer_encoding_element.rb +8 -19
- data/lib/mail/elements/content_type_element.rb +20 -30
- data/lib/mail/elements/date_time_element.rb +10 -21
- data/lib/mail/elements/envelope_from_element.rb +23 -31
- data/lib/mail/elements/message_ids_element.rb +22 -20
- data/lib/mail/elements/mime_version_element.rb +10 -21
- data/lib/mail/elements/phrase_list.rb +13 -15
- data/lib/mail/elements/received_element.rb +26 -21
- data/lib/mail/elements.rb +1 -0
- data/lib/mail/encodings/7bit.rb +10 -14
- data/lib/mail/encodings/8bit.rb +5 -18
- data/lib/mail/encodings/base64.rb +15 -10
- data/lib/mail/encodings/binary.rb +4 -22
- data/lib/mail/encodings/identity.rb +24 -0
- data/lib/mail/encodings/quoted_printable.rb +13 -7
- data/lib/mail/encodings/transfer_encoding.rb +47 -28
- data/lib/mail/encodings/unix_to_unix.rb +20 -0
- data/lib/mail/encodings.rb +102 -93
- data/lib/mail/envelope.rb +12 -19
- data/lib/mail/field.rb +143 -71
- data/lib/mail/field_list.rb +73 -19
- data/lib/mail/fields/bcc_field.rb +42 -48
- data/lib/mail/fields/cc_field.rb +29 -50
- data/lib/mail/fields/comments_field.rb +28 -37
- data/lib/mail/fields/common_address_field.rb +170 -0
- data/lib/mail/fields/common_date_field.rb +58 -0
- data/lib/mail/fields/common_field.rb +77 -0
- data/lib/mail/fields/common_message_id_field.rb +42 -0
- data/lib/mail/fields/content_description_field.rb +8 -14
- data/lib/mail/fields/content_disposition_field.rb +20 -44
- data/lib/mail/fields/content_id_field.rb +25 -51
- data/lib/mail/fields/content_location_field.rb +12 -25
- data/lib/mail/fields/content_transfer_encoding_field.rb +31 -36
- data/lib/mail/fields/content_type_field.rb +51 -80
- data/lib/mail/fields/date_field.rb +24 -52
- data/lib/mail/fields/from_field.rb +29 -50
- data/lib/mail/fields/in_reply_to_field.rb +39 -49
- data/lib/mail/fields/keywords_field.rb +19 -32
- data/lib/mail/fields/message_id_field.rb +26 -71
- data/lib/mail/fields/mime_version_field.rb +20 -30
- data/lib/mail/fields/named_structured_field.rb +11 -0
- data/lib/mail/fields/named_unstructured_field.rb +11 -0
- data/lib/mail/fields/optional_field.rb +10 -7
- data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +16 -13
- data/lib/mail/fields/received_field.rb +44 -57
- data/lib/mail/fields/references_field.rb +36 -49
- data/lib/mail/fields/reply_to_field.rb +29 -50
- data/lib/mail/fields/resent_bcc_field.rb +29 -50
- data/lib/mail/fields/resent_cc_field.rb +29 -50
- data/lib/mail/fields/resent_date_field.rb +6 -30
- data/lib/mail/fields/resent_from_field.rb +29 -50
- data/lib/mail/fields/resent_message_id_field.rb +6 -29
- data/lib/mail/fields/resent_sender_field.rb +28 -57
- data/lib/mail/fields/resent_to_field.rb +29 -50
- data/lib/mail/fields/return_path_field.rb +51 -55
- data/lib/mail/fields/sender_field.rb +35 -56
- data/lib/mail/fields/structured_field.rb +4 -30
- data/lib/mail/fields/subject_field.rb +10 -11
- data/lib/mail/fields/to_field.rb +29 -50
- data/lib/mail/fields/unstructured_field.rb +43 -51
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +78 -129
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +18 -11
- data/lib/mail/matchers/attachment_matchers.rb +44 -0
- data/lib/mail/matchers/has_sent_mail.rb +81 -4
- data/lib/mail/message.rb +142 -139
- data/lib/mail/multibyte/chars.rb +24 -180
- data/lib/mail/multibyte/unicode.rb +32 -27
- data/lib/mail/multibyte/utils.rb +27 -43
- data/lib/mail/multibyte.rb +56 -16
- data/lib/mail/network/delivery_methods/exim.rb +6 -4
- data/lib/mail/network/delivery_methods/file_delivery.rb +12 -10
- data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +63 -21
- data/lib/mail/network/delivery_methods/smtp.rb +76 -50
- data/lib/mail/network/delivery_methods/smtp_connection.rb +4 -4
- data/lib/mail/network/delivery_methods/test_mailer.rb +5 -2
- data/lib/mail/network/retriever_methods/base.rb +9 -8
- data/lib/mail/network/retriever_methods/imap.rb +37 -18
- data/lib/mail/network/retriever_methods/pop3.rb +6 -3
- data/lib/mail/network/retriever_methods/test_retriever.rb +4 -2
- data/lib/mail/network.rb +2 -0
- data/lib/mail/parser_tools.rb +15 -0
- data/lib/mail/parsers/address_lists_parser.rb +33242 -0
- data/lib/mail/parsers/address_lists_parser.rl +179 -0
- data/lib/mail/parsers/content_disposition_parser.rb +901 -0
- data/lib/mail/parsers/content_disposition_parser.rl +89 -0
- data/lib/mail/parsers/content_location_parser.rb +822 -0
- data/lib/mail/parsers/content_location_parser.rl +78 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +522 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
- data/lib/mail/parsers/content_type_parser.rb +1048 -0
- data/lib/mail/parsers/content_type_parser.rl +90 -0
- data/lib/mail/parsers/date_time_parser.rb +891 -0
- data/lib/mail/parsers/date_time_parser.rl +69 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3675 -0
- data/lib/mail/parsers/envelope_from_parser.rl +89 -0
- data/lib/mail/parsers/message_ids_parser.rb +5161 -0
- data/lib/mail/parsers/message_ids_parser.rl +93 -0
- data/lib/mail/parsers/mime_version_parser.rb +513 -0
- data/lib/mail/parsers/mime_version_parser.rl +68 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +884 -0
- data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
- data/lib/mail/parsers/received_parser.rb +8782 -0
- data/lib/mail/parsers/received_parser.rl +91 -0
- data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
- data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
- data/lib/mail/parsers/rfc2045_mime.rl +16 -0
- data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
- data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
- data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
- data/lib/mail/parsers/rfc5322.rl +74 -0
- data/lib/mail/parsers/rfc5322_address.rl +72 -0
- data/lib/mail/parsers/rfc5322_date_time.rl +37 -0
- data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
- data/lib/mail/parsers.rb +13 -0
- data/lib/mail/part.rb +11 -12
- data/lib/mail/parts_list.rb +90 -14
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +415 -76
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +8 -15
- data/lib/mail/yaml.rb +30 -0
- data/lib/mail.rb +9 -32
- metadata +127 -79
- data/CHANGELOG.rdoc +0 -742
- data/CONTRIBUTING.md +0 -45
- data/Dependencies.txt +0 -3
- data/Gemfile +0 -32
- data/Rakefile +0 -21
- data/TODO.rdoc +0 -9
- data/lib/VERSION +0 -4
- data/lib/load_parsers.rb +0 -35
- data/lib/mail/core_extensions/nil.rb +0 -19
- data/lib/mail/core_extensions/object.rb +0 -13
- data/lib/mail/core_extensions/smtp.rb +0 -24
- data/lib/mail/core_extensions/string/access.rb +0 -145
- data/lib/mail/core_extensions/string/multibyte.rb +0 -78
- data/lib/mail/core_extensions/string.rb +0 -33
- data/lib/mail/fields/common/address_container.rb +0 -16
- data/lib/mail/fields/common/common_address.rb +0 -140
- data/lib/mail/fields/common/common_date.rb +0 -42
- data/lib/mail/fields/common/common_field.rb +0 -57
- data/lib/mail/fields/common/common_message_id.rb +0 -48
- data/lib/mail/multibyte/exceptions.rb +0 -8
- 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/mail/patterns.rb +0 -35
- data/lib/mail/version_specific/ruby_1_8.rb +0 -119
- data/lib/mail/version_specific/ruby_1_9.rb +0 -147
- data/lib/tasks/corpus.rake +0 -125
- data/lib/tasks/treetop.rake +0 -10
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'mail/smtp_envelope'
|
2
|
+
|
3
|
+
module Mail
|
4
|
+
class LoggerDelivery
|
5
|
+
attr_reader :logger, :severity, :settings
|
6
|
+
|
7
|
+
def initialize(settings)
|
8
|
+
@settings = settings
|
9
|
+
@logger = settings.fetch(:logger) { default_logger }
|
10
|
+
@severity = derive_severity(settings[:severity])
|
11
|
+
end
|
12
|
+
|
13
|
+
def deliver!(mail)
|
14
|
+
logger.log(severity) { Mail::SmtpEnvelope.new(mail).message }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def default_logger
|
19
|
+
require 'logger'
|
20
|
+
::Logger.new($stdout)
|
21
|
+
end
|
22
|
+
|
23
|
+
def derive_severity(severity)
|
24
|
+
case severity
|
25
|
+
when nil
|
26
|
+
Logger::INFO
|
27
|
+
when Integer
|
28
|
+
severity
|
29
|
+
else
|
30
|
+
Logger.const_get(severity.to_s.upcase)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'mail/smtp_envelope'
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
# A delivery method implementation which sends via sendmail.
|
@@ -39,53 +40,94 @@ module Mail
|
|
39
40
|
class Sendmail
|
40
41
|
DEFAULTS = {
|
41
42
|
:location => '/usr/sbin/sendmail',
|
42
|
-
:arguments =>
|
43
|
+
:arguments => %w[ -i ]
|
43
44
|
}
|
44
45
|
|
45
46
|
attr_accessor :settings
|
46
47
|
|
48
|
+
class DeliveryError < StandardError
|
49
|
+
end
|
50
|
+
|
47
51
|
def initialize(values)
|
52
|
+
if values[:arguments].is_a?(String)
|
53
|
+
deprecation_warn.call \
|
54
|
+
'Initializing Mail::Sendmail with :arguments of type String is deprecated.' \
|
55
|
+
' Instead ensure :arguments is an array of strings, e.g. ["-i", "-t"]'
|
56
|
+
end
|
48
57
|
self.settings = self.class::DEFAULTS.merge(values)
|
49
58
|
end
|
50
59
|
|
60
|
+
def destinations_for(envelope)
|
61
|
+
envelope.to
|
62
|
+
end
|
63
|
+
|
51
64
|
def deliver!(mail)
|
52
|
-
|
65
|
+
envelope = Mail::SmtpEnvelope.new(mail)
|
53
66
|
|
54
|
-
|
55
|
-
|
67
|
+
arguments = settings[:arguments]
|
68
|
+
if arguments.is_a? String
|
69
|
+
return old_deliver(envelope)
|
70
|
+
end
|
56
71
|
|
57
|
-
|
58
|
-
|
59
|
-
|
72
|
+
command = [settings[:location]]
|
73
|
+
command.concat Array(arguments)
|
74
|
+
command.concat [ '-f', envelope.from ] if envelope.from
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
|
76
|
+
if destinations = destinations_for(envelope)
|
77
|
+
command.push '--'
|
78
|
+
command.concat destinations
|
79
|
+
end
|
80
|
+
|
81
|
+
popen(command) do |io|
|
82
|
+
io.puts ::Mail::Utilities.binary_unsafe_to_lf(envelope.message)
|
64
83
|
io.flush
|
65
84
|
end
|
66
85
|
end
|
67
86
|
|
68
|
-
|
69
|
-
def
|
70
|
-
IO.popen
|
87
|
+
private
|
88
|
+
def popen(command, &block)
|
89
|
+
IO.popen(command, 'w+', :err => :out, &block).tap do
|
90
|
+
if $?.exitstatus != 0
|
91
|
+
raise DeliveryError, "Delivery failed with exitstatus #{$?.exitstatus}: #{command.inspect}"
|
92
|
+
end
|
93
|
+
end
|
71
94
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
95
|
+
|
96
|
+
#+ support for delivery using string arguments (deprecated)
|
97
|
+
def old_deliver(envelope)
|
98
|
+
smtp_from = envelope.from
|
99
|
+
smtp_to = destinations_for(envelope)
|
100
|
+
|
101
|
+
from = "-f #{shellquote(smtp_from)}" if smtp_from
|
102
|
+
destination = smtp_to.map { |to| shellquote(to) }.join(' ')
|
103
|
+
|
104
|
+
arguments = "#{settings[:arguments]} #{from} --"
|
105
|
+
command = "#{settings[:location]} #{arguments} #{destination}"
|
106
|
+
popen command do |io|
|
107
|
+
io.puts ::Mail::Utilities.binary_unsafe_to_lf(envelope.message)
|
108
|
+
io.flush
|
75
109
|
end
|
76
110
|
end
|
77
111
|
|
78
112
|
# The following is an adaptation of ruby 1.9.2's shellwords.rb file,
|
79
|
-
#
|
80
|
-
#
|
81
|
-
|
113
|
+
# with the following modifications:
|
114
|
+
#
|
115
|
+
# - Wraps in double quotes
|
116
|
+
# - Allows '+' to accept email addresses with them
|
117
|
+
# - Allows '~' as it is not unescaped in double quotes
|
118
|
+
def shellquote(address)
|
82
119
|
# Process as a single byte sequence because not all shell
|
83
120
|
# implementations are multibyte aware.
|
84
121
|
#
|
85
122
|
# A LF cannot be escaped with a backslash because a backslash + LF
|
86
123
|
# combo is regarded as line continuation and simply ignored. Strip it.
|
87
|
-
escaped = address.gsub(/([^A-Za-z0-9_\s
|
124
|
+
escaped = address.gsub(/([^A-Za-z0-9_\s\+\-.,:\/@~])/n, "\\\\\\1").gsub("\n", '')
|
88
125
|
%("#{escaped}")
|
89
126
|
end
|
127
|
+
#- support for delivery using string arguments
|
128
|
+
|
129
|
+
def deprecation_warn
|
130
|
+
defined?(ActiveSupport::Deprecation.warn) ? ActiveSupport::Deprecation.method(:warn) : Kernel.method(:warn)
|
131
|
+
end
|
90
132
|
end
|
91
133
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'mail/smtp_envelope'
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
# == Sending Email with SMTP
|
@@ -44,9 +45,8 @@ module Mail
|
|
44
45
|
# hostname or update the certificate authorities trusted by your ruby. If
|
45
46
|
# that isn't possible, you can control this behavior with
|
46
47
|
# an :openssl_verify_mode setting. Its value may be either an OpenSSL
|
47
|
-
# verify mode constant (OpenSSL::SSL::VERIFY_NONE),
|
48
|
-
# the name of an OpenSSL verify mode (none, peer
|
49
|
-
# fail_if_no_peer_cert).
|
48
|
+
# verify mode constant (OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER),
|
49
|
+
# or a string containing the name of an OpenSSL verify mode (none, peer).
|
50
50
|
#
|
51
51
|
# === Others
|
52
52
|
#
|
@@ -76,64 +76,90 @@ module Mail
|
|
76
76
|
class SMTP
|
77
77
|
attr_accessor :settings
|
78
78
|
|
79
|
+
DEFAULTS = {
|
80
|
+
:address => 'localhost',
|
81
|
+
:port => 25,
|
82
|
+
:domain => 'localhost.localdomain',
|
83
|
+
:user_name => nil,
|
84
|
+
:password => nil,
|
85
|
+
:authentication => nil,
|
86
|
+
:enable_starttls => nil,
|
87
|
+
:enable_starttls_auto => true,
|
88
|
+
:openssl_verify_mode => nil,
|
89
|
+
:ssl => nil,
|
90
|
+
:tls => nil,
|
91
|
+
:open_timeout => 5,
|
92
|
+
:read_timeout => 5
|
93
|
+
}
|
94
|
+
|
79
95
|
def initialize(values)
|
80
|
-
self.settings =
|
81
|
-
:port => 25,
|
82
|
-
:domain => 'localhost.localdomain',
|
83
|
-
:user_name => nil,
|
84
|
-
:password => nil,
|
85
|
-
:authentication => nil,
|
86
|
-
:enable_starttls_auto => true,
|
87
|
-
:openssl_verify_mode => nil,
|
88
|
-
:ssl => nil,
|
89
|
-
:tls => nil
|
90
|
-
}.merge!(values)
|
96
|
+
self.settings = DEFAULTS.merge(values)
|
91
97
|
end
|
92
98
|
|
93
|
-
# Send the message via SMTP.
|
94
|
-
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
95
99
|
def deliver!(mail)
|
96
|
-
|
97
|
-
|
98
|
-
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
99
|
-
if settings[:tls] || settings[:ssl]
|
100
|
-
if smtp.respond_to?(:enable_tls)
|
101
|
-
smtp.enable_tls(ssl_context)
|
102
|
-
end
|
103
|
-
elsif settings[:enable_starttls_auto]
|
104
|
-
if smtp.respond_to?(:enable_starttls_auto)
|
105
|
-
smtp.enable_starttls_auto(ssl_context)
|
106
|
-
end
|
100
|
+
response = start_smtp_session do |smtp|
|
101
|
+
Mail::SMTPConnection.new(:connection => smtp, :return_response => true).deliver!(mail)
|
107
102
|
end
|
108
103
|
|
109
|
-
response
|
110
|
-
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp_obj|
|
111
|
-
response = smtp_obj.sendmail(message, smtp_from, smtp_to)
|
112
|
-
end
|
113
|
-
|
114
|
-
if settings[:return_response]
|
115
|
-
response
|
116
|
-
else
|
117
|
-
self
|
118
|
-
end
|
104
|
+
settings[:return_response] ? response : self
|
119
105
|
end
|
120
106
|
|
121
107
|
private
|
108
|
+
def start_smtp_session(&block)
|
109
|
+
build_smtp_session.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication], &block)
|
110
|
+
end
|
122
111
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
112
|
+
def build_smtp_session
|
113
|
+
Net::SMTP.new(settings[:address], settings[:port]).tap do |smtp|
|
114
|
+
tls = settings[:tls] || settings[:ssl]
|
115
|
+
if !tls.nil?
|
116
|
+
case tls
|
117
|
+
when true
|
118
|
+
smtp.enable_tls(ssl_context)
|
119
|
+
when false
|
120
|
+
smtp.disable_tls
|
121
|
+
else
|
122
|
+
raise ArgumentError, "Unrecognized :tls value #{settings[:tls].inspect}; expected true, false, or nil"
|
123
|
+
end
|
124
|
+
elsif settings.include?(:enable_starttls) && !settings[:enable_starttls].nil?
|
125
|
+
case settings[:enable_starttls]
|
126
|
+
when true
|
127
|
+
smtp.enable_starttls(ssl_context)
|
128
|
+
when false
|
129
|
+
smtp.disable_starttls
|
130
|
+
else
|
131
|
+
raise ArgumentError, "Unrecognized :enable_starttls value #{settings[:enable_starttls].inspect}; expected true, false, or nil"
|
132
|
+
end
|
133
|
+
elsif settings.include?(:enable_starttls_auto) && !settings[:enable_starttls_auto].nil?
|
134
|
+
case settings[:enable_starttls_auto]
|
135
|
+
when true
|
136
|
+
smtp.enable_starttls_auto(ssl_context)
|
137
|
+
when false
|
138
|
+
smtp.disable_starttls
|
139
|
+
else
|
140
|
+
raise ArgumentError, "Unrecognized :enable_starttls_auto value #{settings[:enable_starttls_auto].inspect}; expected true, false, or nil"
|
141
|
+
end
|
142
|
+
end
|
127
143
|
|
128
|
-
|
129
|
-
|
144
|
+
smtp.open_timeout = settings[:open_timeout] if settings[:open_timeout]
|
145
|
+
smtp.read_timeout = settings[:read_timeout] if settings[:read_timeout]
|
146
|
+
end
|
130
147
|
end
|
131
148
|
|
132
|
-
context
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
149
|
+
# Allow SSL context to be configured via settings, for Ruby >= 1.9
|
150
|
+
# Just returns openssl verify mode for Ruby 1.8.x
|
151
|
+
def ssl_context
|
152
|
+
openssl_verify_mode = settings[:openssl_verify_mode]
|
153
|
+
|
154
|
+
if openssl_verify_mode.kind_of?(String)
|
155
|
+
openssl_verify_mode = OpenSSL::SSL.const_get("VERIFY_#{openssl_verify_mode.upcase}")
|
156
|
+
end
|
157
|
+
|
158
|
+
context = Net::SMTP.default_ssl_context
|
159
|
+
context.verify_mode = openssl_verify_mode if openssl_verify_mode
|
160
|
+
context.ca_path = settings[:ca_path] if settings[:ca_path]
|
161
|
+
context.ca_file = settings[:ca_file] if settings[:ca_file]
|
162
|
+
context
|
163
|
+
end
|
138
164
|
end
|
139
165
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'mail/smtp_envelope'
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
# == Sending Email with SMTP
|
@@ -48,9 +49,8 @@ module Mail
|
|
48
49
|
# Send the message via SMTP.
|
49
50
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
50
51
|
def deliver!(mail)
|
51
|
-
|
52
|
-
response = smtp.sendmail(message,
|
53
|
-
|
52
|
+
envelope = Mail::SmtpEnvelope.new(mail)
|
53
|
+
response = smtp.sendmail(envelope.message, envelope.from, envelope.to)
|
54
54
|
settings[:return_response] ? response : self
|
55
55
|
end
|
56
56
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'mail/smtp_envelope'
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
# The TestMailer is a bare bones mailer that does nothing. It is useful
|
@@ -34,7 +35,9 @@ module Mail
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def deliver!(mail)
|
37
|
-
|
38
|
+
# Create the envelope to validate it
|
39
|
+
Mail::SmtpEnvelope.new(mail)
|
40
|
+
|
38
41
|
Mail::TestMailer.deliveries << mail
|
39
42
|
end
|
40
43
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
|
@@ -10,8 +11,8 @@ module Mail
|
|
10
11
|
# count: number of emails to retrieve. The default value is 1.
|
11
12
|
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
12
13
|
#
|
13
|
-
def first(options =
|
14
|
-
options
|
14
|
+
def first(options = nil, &block)
|
15
|
+
options = options ? Hash[options] : {}
|
15
16
|
options[:what] = :first
|
16
17
|
options[:count] ||= 1
|
17
18
|
find(options, &block)
|
@@ -23,8 +24,8 @@ module Mail
|
|
23
24
|
# count: number of emails to retrieve. The default value is 1.
|
24
25
|
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
25
26
|
#
|
26
|
-
def last(options =
|
27
|
-
options
|
27
|
+
def last(options = nil, &block)
|
28
|
+
options = options ? Hash[options] : {}
|
28
29
|
options[:what] = :last
|
29
30
|
options[:count] ||= 1
|
30
31
|
find(options, &block)
|
@@ -35,8 +36,8 @@ module Mail
|
|
35
36
|
# Possible options:
|
36
37
|
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
37
38
|
#
|
38
|
-
def all(options =
|
39
|
-
options
|
39
|
+
def all(options = nil, &block)
|
40
|
+
options = options ? Hash[options] : {}
|
40
41
|
options[:count] = :all
|
41
42
|
find(options, &block)
|
42
43
|
end
|
@@ -52,8 +53,8 @@ module Mail
|
|
52
53
|
# delete_after_find: flag for whether to delete each retreived email after find. Default
|
53
54
|
# is true. Call #find if you would like this to default to false.
|
54
55
|
#
|
55
|
-
def find_and_delete(options =
|
56
|
-
options
|
56
|
+
def find_and_delete(options = nil, &block)
|
57
|
+
options = options ? Hash[options] : {}
|
57
58
|
options[:delete_after_find] ||= true
|
58
59
|
find(options, &block)
|
59
60
|
end
|
@@ -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.
|
@@ -44,7 +45,8 @@ module Mail
|
|
44
45
|
:user_name => nil,
|
45
46
|
:password => nil,
|
46
47
|
:authentication => nil,
|
47
|
-
:enable_ssl => false
|
48
|
+
:enable_ssl => false,
|
49
|
+
:enable_starttls => false }.merge!(values)
|
48
50
|
end
|
49
51
|
|
50
52
|
attr_accessor :settings
|
@@ -66,38 +68,46 @@ module Mail
|
|
66
68
|
# keys: are passed as criteria to the SEARCH command. They can either be a string holding the entire search string,
|
67
69
|
# or a single-dimension array of search keywords and arguments. Refer to [IMAP] section 6.4.4 for a full list
|
68
70
|
# The default is 'ALL'
|
71
|
+
# search_charset: charset to pass to IMAP server search. Omitted by default. Example: 'UTF-8' or 'ASCII'.
|
69
72
|
#
|
70
|
-
def find(options=
|
73
|
+
def find(options=nil, &block)
|
71
74
|
options = validate_options(options)
|
72
75
|
|
73
76
|
start do |imap|
|
74
77
|
options[:read_only] ? imap.examine(options[:mailbox]) : imap.select(options[:mailbox])
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
message_ids.reverse! if (options[:what].to_sym == :last && options[:order].to_sym == :asc) ||
|
78
|
+
uids = imap.uid_search(options[:keys], options[:search_charset])
|
79
|
+
uids.reverse! if options[:what].to_sym == :last
|
80
|
+
uids = uids.first(options[:count]) if options[:count].is_a?(Integer)
|
81
|
+
uids.reverse! if (options[:what].to_sym == :last && options[:order].to_sym == :asc) ||
|
80
82
|
(options[:what].to_sym != :last && options[:order].to_sym == :desc)
|
81
83
|
|
82
84
|
if block_given?
|
83
|
-
|
84
|
-
|
85
|
+
uids.each do |uid|
|
86
|
+
uid = options[:uid].to_i unless options[:uid].nil?
|
87
|
+
fetchdata = imap.uid_fetch(uid, ['RFC822', 'FLAGS'])[0]
|
85
88
|
new_message = Mail.new(fetchdata.attr['RFC822'])
|
86
89
|
new_message.mark_for_delete = true if options[:delete_after_find]
|
87
|
-
|
88
|
-
|
90
|
+
|
91
|
+
if block.arity == 4
|
92
|
+
yield new_message, imap, uid, fetchdata.attr['FLAGS']
|
93
|
+
elsif block.arity == 3
|
94
|
+
yield new_message, imap, uid
|
89
95
|
else
|
90
96
|
yield new_message
|
91
97
|
end
|
92
|
-
|
98
|
+
|
99
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find] && new_message.is_marked_for_delete?
|
100
|
+
break unless options[:uid].nil?
|
93
101
|
end
|
94
102
|
imap.expunge if options[:delete_after_find]
|
95
103
|
else
|
96
104
|
emails = []
|
97
|
-
|
98
|
-
|
105
|
+
uids.each do |uid|
|
106
|
+
uid = options[:uid].to_i unless options[:uid].nil?
|
107
|
+
fetchdata = imap.uid_fetch(uid, ['RFC822'])[0]
|
99
108
|
emails << Mail.new(fetchdata.attr['RFC822'])
|
100
|
-
imap.uid_store(
|
109
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED]) if options[:delete_after_find]
|
110
|
+
break unless options[:uid].nil?
|
101
111
|
end
|
102
112
|
imap.expunge if options[:delete_after_find]
|
103
113
|
emails.size == 1 && options[:count] == 1 ? emails.first : emails
|
@@ -111,8 +121,9 @@ module Mail
|
|
111
121
|
mailbox = Net::IMAP.encode_utf7(mailbox)
|
112
122
|
|
113
123
|
start do |imap|
|
114
|
-
imap.
|
115
|
-
|
124
|
+
imap.select(mailbox)
|
125
|
+
imap.uid_search(['ALL']).each do |uid|
|
126
|
+
imap.uid_store(uid, "+FLAGS", [Net::IMAP::DELETED])
|
116
127
|
end
|
117
128
|
imap.expunge
|
118
129
|
end
|
@@ -131,12 +142,13 @@ module Mail
|
|
131
142
|
|
132
143
|
# Set default options
|
133
144
|
def validate_options(options)
|
134
|
-
options
|
145
|
+
options = options ? Hash[options] : {}
|
135
146
|
options[:mailbox] ||= 'INBOX'
|
136
147
|
options[:count] ||= 10
|
137
148
|
options[:order] ||= :asc
|
138
149
|
options[:what] ||= :first
|
139
150
|
options[:keys] ||= 'ALL'
|
151
|
+
options[:uid] ||= nil
|
140
152
|
options[:delete_after_find] ||= false
|
141
153
|
options[:mailbox] = Net::IMAP.encode_utf7(options[:mailbox])
|
142
154
|
options[:read_only] ||= false
|
@@ -148,7 +160,14 @@ module Mail
|
|
148
160
|
def start(config=Mail::Configuration.instance, &block)
|
149
161
|
raise ArgumentError.new("Mail::Retrievable#imap_start takes a block") unless block_given?
|
150
162
|
|
163
|
+
if settings[:enable_starttls] && settings[:enable_ssl]
|
164
|
+
raise ArgumentError, ":enable_starttls and :enable_ssl are mutually exclusive. Set :enable_ssl if you're on an IMAPS connection. Set :enable_starttls if you're on an IMAP connection and using STARTTLS for secure TLS upgrade."
|
165
|
+
end
|
166
|
+
|
151
167
|
imap = Net::IMAP.new(settings[:address], settings[:port], settings[:enable_ssl], nil, false)
|
168
|
+
|
169
|
+
imap.starttls if settings[:enable_starttls]
|
170
|
+
|
152
171
|
if settings[:authentication].nil?
|
153
172
|
imap.login(settings[:user_name], settings[:password])
|
154
173
|
else
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
# The Pop3 retriever allows to get the last, first or all emails from a POP3 server.
|
@@ -40,7 +41,8 @@ module Mail
|
|
40
41
|
:user_name => nil,
|
41
42
|
:password => nil,
|
42
43
|
:authentication => nil,
|
43
|
-
:enable_ssl => false
|
44
|
+
:enable_ssl => false,
|
45
|
+
:read_timeout => nil }.merge!(values)
|
44
46
|
end
|
45
47
|
|
46
48
|
attr_accessor :settings
|
@@ -55,7 +57,7 @@ module Mail
|
|
55
57
|
# delete_after_find: flag for whether to delete each retreived email after find. Default
|
56
58
|
# is false. Use #find_and_delete if you would like this to default to true.
|
57
59
|
#
|
58
|
-
def find(options =
|
60
|
+
def find(options = nil, &block)
|
59
61
|
options = validate_options(options)
|
60
62
|
|
61
63
|
start do |pop3|
|
@@ -111,7 +113,7 @@ module Mail
|
|
111
113
|
|
112
114
|
# Set default options
|
113
115
|
def validate_options(options)
|
114
|
-
options
|
116
|
+
options = options ? Hash[options] : {}
|
115
117
|
options[:count] ||= 10
|
116
118
|
options[:order] ||= :asc
|
117
119
|
options[:what] ||= :first
|
@@ -127,6 +129,7 @@ module Mail
|
|
127
129
|
|
128
130
|
pop3 = Net::POP3.new(settings[:address], settings[:port], false)
|
129
131
|
pop3.enable_ssl(OpenSSL::SSL::VERIFY_NONE) if settings[:enable_ssl]
|
132
|
+
pop3.read_timeout = settings[:read_timeout] if settings[:read_timeout]
|
130
133
|
pop3.start(settings[:user_name], settings[:password])
|
131
134
|
|
132
135
|
yield pop3
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
|
@@ -16,7 +17,8 @@ module Mail
|
|
16
17
|
@@emails = []
|
17
18
|
end
|
18
19
|
|
19
|
-
def find(options =
|
20
|
+
def find(options = nil, &block)
|
21
|
+
options = options ? Hash[options] : {}
|
20
22
|
options[:count] ||= :all
|
21
23
|
options[:order] ||= :asc
|
22
24
|
options[:what] ||= :first
|
@@ -24,7 +26,7 @@ module Mail
|
|
24
26
|
emails_index.reverse! if options[:what] == :last
|
25
27
|
emails_index = case count = options[:count]
|
26
28
|
when :all then emails_index
|
27
|
-
when
|
29
|
+
when Integer then emails_index[0, count]
|
28
30
|
else
|
29
31
|
raise 'Invalid count option value: ' + count.inspect
|
30
32
|
end
|
data/lib/mail/network.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'mail/network/retriever_methods/base'
|
2
3
|
|
3
4
|
module Mail
|
4
5
|
register_autoload :SMTP, 'mail/network/delivery_methods/smtp'
|
5
6
|
register_autoload :FileDelivery, 'mail/network/delivery_methods/file_delivery'
|
7
|
+
register_autoload :LoggerDelivery, 'mail/network/delivery_methods/logger_delivery'
|
6
8
|
register_autoload :Sendmail, 'mail/network/delivery_methods/sendmail'
|
7
9
|
register_autoload :Exim, 'mail/network/delivery_methods/exim'
|
8
10
|
register_autoload :SMTPConnection, 'mail/network/delivery_methods/smtp_connection'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Mail
|
2
|
+
# Extends each field parser with utility methods.
|
3
|
+
module ParserTools #:nodoc:
|
4
|
+
# Slice bytes from ASCII-8BIT data and mark as UTF-8.
|
5
|
+
if 'string'.respond_to?(:force_encoding)
|
6
|
+
def chars(data, from_bytes, to_bytes)
|
7
|
+
data.slice(from_bytes..to_bytes).force_encoding(Encoding::UTF_8)
|
8
|
+
end
|
9
|
+
else
|
10
|
+
def chars(data, from_bytes, to_bytes)
|
11
|
+
data.slice(from_bytes..to_bytes)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|