net-smtp 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +133 -0
- data/README.md +97 -0
- data/lib/net/smtp/auth_cram_md5.rb +48 -0
- data/lib/net/smtp/auth_login.rb +11 -0
- data/lib/net/smtp/auth_plain.rb +9 -0
- data/lib/net/smtp/auth_xoauth2.rb +17 -0
- data/lib/net/smtp/authenticator.rb +57 -0
- data/lib/net/smtp.rb +152 -183
- metadata +10 -32
- data/net-smtp.gemspec +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fcccbe34b29672c33aa7515de88e88dba31882e26a4b6c0a5fc30c5a4eb697d
|
4
|
+
data.tar.gz: 5c47e6453d2cb69365edc7b4e31b17106b73e254e1bc10258f4b14ea780ba889
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6576c5b7dc21982576fa6c3a6e08641e973136148d5d5bcb27fe1e17b4e5fdd802c5f5a6f9f116dd15bf4f2a0e5f95f071ca19d47119cf60c7da9230a64d3a4c
|
7
|
+
data.tar.gz: 9b1c54b2d9a48e384d3b1a67f1aa8b8a2614a383dc31b83d49170f3ed93d69a2058f3c310f72d443f54a0947c1066249105087a1a3addc92965c289354c8156a
|
data/NEWS.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# NEWS
|
2
|
+
|
3
|
+
## Version 0.5.0 (2024-03-27)
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Allow case-insensitive strings for SASL mechanism <https://github.com/ruby/net-smtp/pull/64>
|
8
|
+
* Make #auth_capable? public <https://github.com/ruby/net-smtp/pull/63>
|
9
|
+
* Add XOAUTH2 authenticator <https://github.com/ruby/net-smtp/pull/80>
|
10
|
+
|
11
|
+
### Others
|
12
|
+
|
13
|
+
* Remove unused private auth_method <https://github.com/ruby/net-smtp/pull/67>
|
14
|
+
* Delegate checking auth args to the authenticator <https://github.com/ruby/net-smtp/pull/73>
|
15
|
+
* Updated docs, especially TLS and SASL-related <https://github.com/ruby/net-smtp/pull/66>
|
16
|
+
* Renew test certificates <https://github.com/ruby/net-smtp/pull/75>
|
17
|
+
* Fix version extraction to work with non ASCII characters with any LANG <https://github.com/ruby/net-smtp/pull/76>
|
18
|
+
* Replace non-ASCII EM DASH (U+2014) with ASCII hyphen (U+002D) <https://github.com/ruby/net-smtp/pull/78>
|
19
|
+
* Use reusing workflow for Ruby versions <https://github.com/ruby/net-smtp/pull/79>
|
20
|
+
* Make the test suite compatible with --enable-frozen-string-literal <https://github.com/ruby/net-smtp/pull/81>
|
21
|
+
|
22
|
+
## Version 0.4.0 (2023-09-20)
|
23
|
+
|
24
|
+
### Improvements
|
25
|
+
|
26
|
+
* add Net::SMTP::Authenticator class and auth_* methods are separated from the Net::SMTP class. <https://github.com/ruby/net-smtp/pull/53>
|
27
|
+
This allows you to add a new authentication method to Net::SMTP.
|
28
|
+
Create a class with an `auth` method that inherits Net::SMTP::Authenticator.
|
29
|
+
The `auth` method has two arguments, `user` and `secret`.
|
30
|
+
Send an instruction to the SMTP server by using the `continue` or `finish` method.
|
31
|
+
For more information, see lib/net/smtp/auto _*.rb.
|
32
|
+
* Add SMTPUTF8 support <https://github.com/ruby/net-smtp/pull/49>
|
33
|
+
|
34
|
+
### Fixes
|
35
|
+
|
36
|
+
* Revert "Replace Timeout.timeout with socket timeout" <https://github.com/ruby/net-smtp/pull/51>
|
37
|
+
* Fixed issue sending emails to unaffected recipients on 53x error <https://github.com/ruby/net-smtp/pull/56>
|
38
|
+
|
39
|
+
### Others
|
40
|
+
|
41
|
+
* Removed unnecessary Subversion keywords <https://github.com/ruby/net-smtp/pull/57>
|
42
|
+
|
43
|
+
## Version 0.3.3 (2022-10-29)
|
44
|
+
|
45
|
+
* No timeout library required <https://github.com/ruby/net-smtp/pull/44>
|
46
|
+
* Make the digest library optional <https://github.com/ruby/net-smtp/pull/45>
|
47
|
+
|
48
|
+
## Version 0.3.2 (2022-09-28)
|
49
|
+
|
50
|
+
* Make exception API compatible with what Ruby expects <https://github.com/ruby/net-smtp/pull/42>
|
51
|
+
|
52
|
+
## Version 0.3.1 (2021-12-12)
|
53
|
+
|
54
|
+
### Improvements
|
55
|
+
|
56
|
+
* add Net::SMTP::Address.
|
57
|
+
* add Net::SMTP#capable? and Net::SMTP#capabilities.
|
58
|
+
* add Net::SMTP#tls_verify, Net::SMTP#tls_hostname, Net::SMTP#ssl_context_params
|
59
|
+
|
60
|
+
## Version 0.3.0 (2021-10-14)
|
61
|
+
|
62
|
+
### Improvements
|
63
|
+
|
64
|
+
* Add `tls`, `starttls` keyword arguments.
|
65
|
+
```ruby
|
66
|
+
# always use TLS connection for port 465.
|
67
|
+
Net::SMTP.start(hostname, 465, tls: true)
|
68
|
+
|
69
|
+
# do not use starttls for localhost
|
70
|
+
Net::SMTP.start('localhost', starttls: false)
|
71
|
+
```
|
72
|
+
|
73
|
+
### Incompatible changes
|
74
|
+
|
75
|
+
* The tls_* paramter has been moved from start() to initialize().
|
76
|
+
|
77
|
+
## Version 0.2.2 (2021-10-09)
|
78
|
+
|
79
|
+
* Add `response` to SMTPError exceptions.
|
80
|
+
* `Net::SMTP.start()` and `#start()` accepts `ssl_context_params` keyword argument.
|
81
|
+
* Replace `Timeout.timeout` with socket timeout.
|
82
|
+
* Remove needless files from gem.
|
83
|
+
* Add dependency on digest, timeout.
|
84
|
+
|
85
|
+
## Version 0.2.1 (2020-11-18)
|
86
|
+
|
87
|
+
### Fixes
|
88
|
+
|
89
|
+
* Update the license for the default gems to dual licenses.
|
90
|
+
* Add dependency for net-protocol.
|
91
|
+
|
92
|
+
## Version 0.2.0 (2020-11-15)
|
93
|
+
|
94
|
+
### Incompatible changes
|
95
|
+
|
96
|
+
* Verify the server's certificate by default.
|
97
|
+
If you don't want verification, specify `start(tls_verify: false)`.
|
98
|
+
<https://github.com/ruby/net-smtp/pull/12>
|
99
|
+
|
100
|
+
* Use STARTTLS by default if possible.
|
101
|
+
If you don't want starttls, specify:
|
102
|
+
```
|
103
|
+
smtp = Net::SMTP.new(hostname, port)
|
104
|
+
smtp.disable_starttls
|
105
|
+
smtp.start do |s|
|
106
|
+
s.send_message ....
|
107
|
+
end
|
108
|
+
```
|
109
|
+
<https://github.com/ruby/net-smtp/pull/9>
|
110
|
+
|
111
|
+
### Improvements
|
112
|
+
|
113
|
+
* Net::SMTP.start and Net::SMTP#start arguments are keyword arguments.
|
114
|
+
```
|
115
|
+
start(address, port = nil, helo: 'localhost', user: nil, secret: nil, authtype: nil) { |smtp| ... }
|
116
|
+
```
|
117
|
+
`password` is an alias of `secret`.
|
118
|
+
<https://github.com/ruby/net-smtp/pull/7>
|
119
|
+
|
120
|
+
* Add `tls_hostname` parameter to `start()`.
|
121
|
+
If you want to use a different hostname than the certificate for the connection, you can specify the certificate hostname with `tls_hostname`.
|
122
|
+
<https://github.com/ruby/net-smtp/pull/14>
|
123
|
+
|
124
|
+
* Add SNI support to net/smtp <https://github.com/ruby/net-smtp/pull/4>
|
125
|
+
|
126
|
+
### Fixes
|
127
|
+
|
128
|
+
* enable_starttls before disable_tls causes an error. <https://github.com/ruby/net-smtp/pull/10>
|
129
|
+
* TLS should not check the hostname when verify_mode is disabled. <https://github.com/ruby/net-smtp/pull/6>
|
130
|
+
|
131
|
+
## Version 0.1.0 (2019-12-03)
|
132
|
+
|
133
|
+
This is the first release of net-smtp gem.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Net::SMTP
|
2
|
+
|
3
|
+
This library provides functionality to send internet mail via SMTP, the Simple Mail Transfer Protocol.
|
4
|
+
|
5
|
+
For details of SMTP itself, see [RFC2821](http://www.ietf.org/rfc/rfc2821.txt).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'net-smtp'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install net-smtp
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Sending Messages
|
26
|
+
|
27
|
+
You must open a connection to an SMTP server before sending messages.
|
28
|
+
The first argument is the address of your SMTP server, and the second
|
29
|
+
argument is the port number. Using SMTP.start with a block is the simplest
|
30
|
+
way to do this. This way, the SMTP connection is closed automatically
|
31
|
+
after the block is executed.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'net/smtp'
|
35
|
+
Net::SMTP.start('your.smtp.server', 25) do |smtp|
|
36
|
+
# Use the SMTP object smtp only in this block.
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
Replace 'your.smtp.server' with your SMTP server. Normally
|
41
|
+
your system manager or internet provider supplies a server
|
42
|
+
for you.
|
43
|
+
|
44
|
+
Then you can send messages.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
msgstr = <<END_OF_MESSAGE
|
48
|
+
From: Your Name <your@mail.address>
|
49
|
+
To: Destination Address <someone@example.com>
|
50
|
+
Subject: test message
|
51
|
+
Date: Sat, 23 Jun 2001 16:26:43 +0900
|
52
|
+
Message-Id: <unique.message.id.string@example.com>
|
53
|
+
|
54
|
+
This is a test message.
|
55
|
+
END_OF_MESSAGE
|
56
|
+
|
57
|
+
require 'net/smtp'
|
58
|
+
Net::SMTP.start('your.smtp.server', 25) do |smtp|
|
59
|
+
smtp.send_message msgstr,
|
60
|
+
'your@mail.address',
|
61
|
+
'his_address@example.com'
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
### Closing the Session
|
66
|
+
|
67
|
+
You MUST close the SMTP session after sending messages, by calling
|
68
|
+
the #finish method:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
# using SMTP#finish
|
72
|
+
smtp = Net::SMTP.start('your.smtp.server', 25)
|
73
|
+
smtp.send_message msgstr, 'from@address', 'to@address'
|
74
|
+
smtp.finish
|
75
|
+
```
|
76
|
+
|
77
|
+
You can also use the block form of SMTP.start/SMTP#start. This closes
|
78
|
+
the SMTP session automatically:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
# using block form of SMTP.start
|
82
|
+
Net::SMTP.start('your.smtp.server', 25) do |smtp|
|
83
|
+
smtp.send_message msgstr, 'from@address', 'to@address'
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
I strongly recommend this scheme. This form is simpler and more robust.
|
88
|
+
|
89
|
+
## Development
|
90
|
+
|
91
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
92
|
+
|
93
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
94
|
+
|
95
|
+
## Contributing
|
96
|
+
|
97
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/net-smtp.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
unless defined? OpenSSL
|
2
|
+
begin
|
3
|
+
require 'digest/md5'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Net::SMTP
|
9
|
+
class AuthCramMD5 < Net::SMTP::Authenticator
|
10
|
+
auth_type :cram_md5
|
11
|
+
|
12
|
+
def auth(user, secret)
|
13
|
+
challenge = continue('AUTH CRAM-MD5')
|
14
|
+
crammed = cram_md5_response(secret, challenge.unpack1('m'))
|
15
|
+
finish(base64_encode("#{user} #{crammed}"))
|
16
|
+
end
|
17
|
+
|
18
|
+
IMASK = 0x36
|
19
|
+
OMASK = 0x5c
|
20
|
+
|
21
|
+
# CRAM-MD5: [RFC2195]
|
22
|
+
def cram_md5_response(secret, challenge)
|
23
|
+
tmp = digest_class::MD5.digest(cram_secret(secret, IMASK) + challenge)
|
24
|
+
digest_class::MD5.hexdigest(cram_secret(secret, OMASK) + tmp)
|
25
|
+
end
|
26
|
+
|
27
|
+
CRAM_BUFSIZE = 64
|
28
|
+
|
29
|
+
def cram_secret(secret, mask)
|
30
|
+
secret = digest_class::MD5.digest(secret) if secret.size > CRAM_BUFSIZE
|
31
|
+
buf = secret.ljust(CRAM_BUFSIZE, "\0")
|
32
|
+
0.upto(buf.size - 1) do |i|
|
33
|
+
buf[i] = (buf[i].ord ^ mask).chr
|
34
|
+
end
|
35
|
+
buf
|
36
|
+
end
|
37
|
+
|
38
|
+
def digest_class
|
39
|
+
@digest_class ||= if defined?(OpenSSL::Digest)
|
40
|
+
OpenSSL::Digest
|
41
|
+
elsif defined?(::Digest)
|
42
|
+
::Digest
|
43
|
+
else
|
44
|
+
raise '"openssl" or "digest" library is required'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Net::SMTP
|
2
|
+
class AuthXoauth2 < Net::SMTP::Authenticator
|
3
|
+
auth_type :xoauth2
|
4
|
+
|
5
|
+
def auth(user, secret)
|
6
|
+
token = xoauth2_string(user, secret)
|
7
|
+
|
8
|
+
finish("AUTH XOAUTH2 #{base64_encode(token)}")
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def xoauth2_string(user, secret)
|
14
|
+
"user=#{user}\1auth=Bearer #{secret}\1\1"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Net
|
2
|
+
class SMTP
|
3
|
+
class Authenticator
|
4
|
+
def self.auth_classes
|
5
|
+
@classes ||= {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.auth_type(type)
|
9
|
+
type = type.to_s.upcase.tr(?_, ?-).to_sym
|
10
|
+
Authenticator.auth_classes[type] = self
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.auth_class(type)
|
14
|
+
type = type.to_s.upcase.tr(?_, ?-).to_sym
|
15
|
+
Authenticator.auth_classes[type]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.check_args(user_arg = nil, secret_arg = nil, *, **)
|
19
|
+
unless user_arg
|
20
|
+
raise ArgumentError, 'SMTP-AUTH requested but missing user name'
|
21
|
+
end
|
22
|
+
unless secret_arg
|
23
|
+
raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :smtp
|
28
|
+
|
29
|
+
def initialize(smtp)
|
30
|
+
@smtp = smtp
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param arg [String] message to server
|
34
|
+
# @return [String] message from server
|
35
|
+
def continue(arg)
|
36
|
+
res = smtp.get_response arg
|
37
|
+
raise res.exception_class.new(res) unless res.continue?
|
38
|
+
res.string.split[1]
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param arg [String] message to server
|
42
|
+
# @return [Net::SMTP::Response] response from server
|
43
|
+
def finish(arg)
|
44
|
+
res = smtp.get_response arg
|
45
|
+
raise SMTPAuthenticationError.new(res) unless res.success?
|
46
|
+
res
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param str [String]
|
50
|
+
# @return [String] Base64 encoded string
|
51
|
+
def base64_encode(str)
|
52
|
+
# expects "str" may not become too long
|
53
|
+
[str].pack('m0')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/net/smtp.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# = net/smtp.rb
|
3
4
|
#
|
4
5
|
# Copyright (c) 1999-2007 Yukihiro Matsumoto.
|
@@ -12,21 +13,16 @@
|
|
12
13
|
# This program is free software. You can re-distribute and/or
|
13
14
|
# modify this program under the same terms as Ruby itself.
|
14
15
|
#
|
15
|
-
# $Id$
|
16
|
-
#
|
17
16
|
# See Net::SMTP for documentation.
|
18
17
|
#
|
19
18
|
|
20
19
|
require 'net/protocol'
|
21
|
-
require 'digest/md5'
|
22
|
-
require 'timeout'
|
23
20
|
begin
|
24
21
|
require 'openssl'
|
25
22
|
rescue LoadError
|
26
23
|
end
|
27
24
|
|
28
25
|
module Net
|
29
|
-
|
30
26
|
# Module mixed in to all SMTP error classes
|
31
27
|
module SMTPError
|
32
28
|
# This *class* is a module for backward compatibility.
|
@@ -35,8 +31,13 @@ module Net
|
|
35
31
|
attr_reader :response
|
36
32
|
|
37
33
|
def initialize(response, message: nil)
|
38
|
-
|
39
|
-
|
34
|
+
if response.is_a?(::Net::SMTP::Response)
|
35
|
+
@response = response
|
36
|
+
@message = message
|
37
|
+
else
|
38
|
+
@response = nil
|
39
|
+
@message = message || response
|
40
|
+
end
|
40
41
|
end
|
41
42
|
|
42
43
|
def message
|
@@ -78,25 +79,34 @@ module Net
|
|
78
79
|
# == What is This Library?
|
79
80
|
#
|
80
81
|
# This library provides functionality to send internet
|
81
|
-
# mail via SMTP, the Simple Mail Transfer Protocol. For details of
|
82
|
-
# SMTP itself, see [
|
82
|
+
# mail via \SMTP, the Simple Mail Transfer Protocol. For details of
|
83
|
+
# \SMTP itself, see [RFC5321[https://www.rfc-editor.org/rfc/rfc5321.txt]].
|
84
|
+
# This library also implements \SMTP authentication, which is often
|
85
|
+
# necessary for message composers to submit messages to their
|
86
|
+
# outgoing \SMTP server, see
|
87
|
+
# [RFC6409[https://www.rfc-editor.org/rfc/rfc6409.html]],
|
88
|
+
# and [SMTPUTF8[https://www.rfc-editor.org/rfc/rfc6531.txt]], which is
|
89
|
+
# necessary to send messages to/from addresses containing characters
|
90
|
+
# outside the ASCII range.
|
83
91
|
#
|
84
92
|
# == What is This Library NOT?
|
85
93
|
#
|
86
94
|
# This library does NOT provide functions to compose internet mails.
|
87
95
|
# You must create them by yourself. If you want better mail support,
|
88
|
-
# try
|
96
|
+
# try the mail[https://rubygems.org/gems/mail] or
|
97
|
+
# rmail[https://rubygems.org/gems/rmail] gems, or search for alternatives in
|
89
98
|
# {RubyGems.org}[https://rubygems.org/] or {The Ruby
|
90
99
|
# Toolbox}[https://www.ruby-toolbox.com/].
|
91
100
|
#
|
92
|
-
# FYI: the official
|
101
|
+
# FYI: the official specification on internet mail is:
|
102
|
+
# [RFC5322[https://www.rfc-editor.org/rfc/rfc5322.txt]].
|
93
103
|
#
|
94
104
|
# == Examples
|
95
105
|
#
|
96
106
|
# === Sending Messages
|
97
107
|
#
|
98
|
-
# You must open a connection to an SMTP server before sending messages.
|
99
|
-
# The first argument is the address of your SMTP server, and the second
|
108
|
+
# You must open a connection to an \SMTP server before sending messages.
|
109
|
+
# The first argument is the address of your \SMTP server, and the second
|
100
110
|
# argument is the port number. Using SMTP.start with a block is the simplest
|
101
111
|
# way to do this. This way, the SMTP connection is closed automatically
|
102
112
|
# after the block is executed.
|
@@ -106,7 +116,7 @@ module Net
|
|
106
116
|
# # Use the SMTP object smtp only in this block.
|
107
117
|
# end
|
108
118
|
#
|
109
|
-
# Replace 'your.smtp.server' with your SMTP server. Normally
|
119
|
+
# Replace 'your.smtp.server' with your \SMTP server. Normally
|
110
120
|
# your system manager or internet provider supplies a server
|
111
121
|
# for you.
|
112
122
|
#
|
@@ -139,7 +149,7 @@ module Net
|
|
139
149
|
# smtp.send_message msgstr, 'from@address', 'to@address'
|
140
150
|
# smtp.finish
|
141
151
|
#
|
142
|
-
# You can also use the block form of SMTP.start
|
152
|
+
# You can also use the block form of SMTP.start or SMTP#start. This closes
|
143
153
|
# the SMTP session automatically:
|
144
154
|
#
|
145
155
|
# # using block form of SMTP.start
|
@@ -152,36 +162,37 @@ module Net
|
|
152
162
|
# === HELO domain
|
153
163
|
#
|
154
164
|
# In almost all situations, you must provide a third argument
|
155
|
-
# to SMTP.start
|
165
|
+
# to SMTP.start or SMTP#start. This is the domain name which you are on
|
156
166
|
# (the host to send mail from). It is called the "HELO domain".
|
157
|
-
# The SMTP server will judge whether it should send or reject
|
167
|
+
# The \SMTP server will judge whether it should send or reject
|
158
168
|
# the SMTP session by inspecting the HELO domain.
|
159
169
|
#
|
160
|
-
# Net::SMTP.start('your.smtp.server', 25
|
161
|
-
#
|
170
|
+
# Net::SMTP.start('your.smtp.server', 25, helo: 'mail.from.domain') do |smtp|
|
171
|
+
# smtp.send_message msgstr, 'from@address', 'to@address'
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
# === \SMTP Authentication
|
162
175
|
#
|
163
|
-
#
|
176
|
+
# The Net::SMTP class supports the \SMTP extension for SASL Authentication
|
177
|
+
# [RFC4954[https://www.rfc-editor.org/rfc/rfc4954.html]] and the following
|
178
|
+
# SASL mechanisms: +PLAIN+, +LOGIN+ _(deprecated)_, and +CRAM-MD5+
|
179
|
+
# _(deprecated)_.
|
164
180
|
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
# To use SMTP authentication, pass extra arguments to
|
168
|
-
# SMTP.start/SMTP#start.
|
181
|
+
# To use \SMTP authentication, pass extra arguments to
|
182
|
+
# SMTP.start or SMTP#start.
|
169
183
|
#
|
170
184
|
# # PLAIN
|
171
|
-
# Net::SMTP.start('your.smtp.server', 25
|
185
|
+
# Net::SMTP.start('your.smtp.server', 25,
|
172
186
|
# user: 'Your Account', secret: 'Your Password', authtype: :plain)
|
173
|
-
# # LOGIN
|
174
|
-
# Net::SMTP.start('your.smtp.server', 25
|
175
|
-
# user: 'Your Account', secret: 'Your Password', authtype: :login)
|
176
187
|
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
188
|
+
# Support for other SASL mechanisms-such as +EXTERNAL+, +OAUTHBEARER+,
|
189
|
+
# +SCRAM-SHA-256+, and +XOAUTH2+-will be added in a future release.
|
190
|
+
#
|
191
|
+
# The +LOGIN+ and +CRAM-MD5+ mechanisms are still available for backwards
|
192
|
+
# compatibility, but are deprecated and should be avoided.
|
180
193
|
#
|
181
194
|
class SMTP < Protocol
|
182
|
-
VERSION = "0.
|
183
|
-
|
184
|
-
Revision = %q$Revision$.split[1]
|
195
|
+
VERSION = "0.5.0"
|
185
196
|
|
186
197
|
# The default SMTP port number, 25.
|
187
198
|
def SMTP.default_port
|
@@ -204,7 +215,7 @@ module Net
|
|
204
215
|
|
205
216
|
def SMTP.default_ssl_context(ssl_context_params = nil)
|
206
217
|
context = OpenSSL::SSL::SSLContext.new
|
207
|
-
context.set_params(ssl_context_params
|
218
|
+
context.set_params(ssl_context_params || {})
|
208
219
|
context
|
209
220
|
end
|
210
221
|
|
@@ -223,10 +234,13 @@ module Net
|
|
223
234
|
# If the hostname in the server certificate is different from +address+,
|
224
235
|
# it can be specified with +tls_hostname+.
|
225
236
|
#
|
226
|
-
# Additional SSLContext
|
227
|
-
# +
|
237
|
+
# Additional SSLContext[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html]
|
238
|
+
# params can be added to the +ssl_context_params+ hash argument and are
|
239
|
+
# passed to {OpenSSL::SSL::SSLContext#set_params}[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html#method-i-set_params].
|
240
|
+
#
|
241
|
+
# <tt>tls_verify: true</tt> is equivalent to <tt>ssl_context_params: {
|
242
|
+
# verify_mode: OpenSSL::SSL::VERIFY_PEER }</tt>.
|
228
243
|
#
|
229
|
-
# +tls_verify: true+ is equivalent to +ssl_context_params: { verify_mode: OpenSSL::SSL::VERIFY_PEER }+.
|
230
244
|
# This method does not open the TCP connection. You can use
|
231
245
|
# SMTP.start instead of SMTP.new if you want to do everything
|
232
246
|
# at once. Otherwise, follow SMTP.new with SMTP#start.
|
@@ -275,7 +289,7 @@ module Net
|
|
275
289
|
attr_accessor :esmtp
|
276
290
|
|
277
291
|
# +true+ if the SMTP object uses ESMTP (which it does by default).
|
278
|
-
alias
|
292
|
+
alias esmtp? esmtp
|
279
293
|
|
280
294
|
# true if server advertises STARTTLS.
|
281
295
|
# You cannot get valid value before opening SMTP session.
|
@@ -310,12 +324,13 @@ module Net
|
|
310
324
|
auth_capable?('CRAM-MD5')
|
311
325
|
end
|
312
326
|
|
327
|
+
# Returns whether the server advertises support for the authentication type.
|
328
|
+
# You cannot get valid result before opening SMTP session.
|
313
329
|
def auth_capable?(type)
|
314
330
|
return nil unless @capabilities
|
315
331
|
return false unless @capabilities['AUTH']
|
316
332
|
@capabilities['AUTH'].include?(type)
|
317
333
|
end
|
318
|
-
private :auth_capable?
|
319
334
|
|
320
335
|
# Returns supported authentication methods on this server.
|
321
336
|
# You cannot get valid value before opening SMTP session.
|
@@ -332,7 +347,7 @@ module Net
|
|
332
347
|
|
333
348
|
alias ssl? tls?
|
334
349
|
|
335
|
-
# Enables SMTP/TLS (SMTPS: SMTP over direct TLS connection) for
|
350
|
+
# Enables SMTP/TLS (SMTPS: \SMTP over direct TLS connection) for
|
336
351
|
# this object. Must be called before the connection is established
|
337
352
|
# to have any effect. +context+ is a OpenSSL::SSL::SSLContext object.
|
338
353
|
def enable_tls(context = nil)
|
@@ -451,7 +466,10 @@ module Net
|
|
451
466
|
#
|
452
467
|
# This method is equivalent to:
|
453
468
|
#
|
454
|
-
# Net::SMTP.new(address, port
|
469
|
+
# Net::SMTP.new(address, port, tls_verify: flag, tls_hostname: hostname, ssl_context_params: nil)
|
470
|
+
# .start(helo: helo_domain, user: account, secret: password, authtype: authtype)
|
471
|
+
#
|
472
|
+
# See also: Net::SMTP.new, #start
|
455
473
|
#
|
456
474
|
# === Example
|
457
475
|
#
|
@@ -476,12 +494,6 @@ module Net
|
|
476
494
|
# +helo+ is the _HELO_ _domain_ provided by the client to the
|
477
495
|
# server (see overview comments); it defaults to 'localhost'.
|
478
496
|
#
|
479
|
-
# The remaining arguments are used for SMTP authentication, if required
|
480
|
-
# or desired. +user+ is the account name; +secret+ is your password
|
481
|
-
# or other authentication token; and +authtype+ is the authentication
|
482
|
-
# type, one of :plain, :login, or :cram_md5. See the discussion of
|
483
|
-
# SMTP Authentication in the overview notes.
|
484
|
-
#
|
485
497
|
# If +tls+ is true, enable TLS. The default is false.
|
486
498
|
# If +starttls+ is :always, enable STARTTLS, if +:auto+, use STARTTLS when the server supports it,
|
487
499
|
# if false, disable STARTTLS.
|
@@ -490,10 +502,26 @@ module Net
|
|
490
502
|
# If the hostname in the server certificate is different from +address+,
|
491
503
|
# it can be specified with +tls_hostname+.
|
492
504
|
#
|
493
|
-
# Additional SSLContext
|
494
|
-
# +
|
505
|
+
# Additional SSLContext[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html]
|
506
|
+
# params can be added to the +ssl_context_params+ hash argument and are
|
507
|
+
# passed to {OpenSSL::SSL::SSLContext#set_params}[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html#method-i-set_params].
|
508
|
+
#
|
509
|
+
# <tt>tls_verify: true</tt> is equivalent to <tt>ssl_context_params: {
|
510
|
+
# verify_mode: OpenSSL::SSL::VERIFY_PEER }</tt>.
|
511
|
+
#
|
512
|
+
# The remaining arguments are used for \SMTP authentication, if required or
|
513
|
+
# desired.
|
514
|
+
#
|
515
|
+
# +authtype+ is the SASL authentication mechanism.
|
516
|
+
#
|
517
|
+
# +user+ is the authentication or authorization identity.
|
518
|
+
#
|
519
|
+
# +secret+ or +password+ is your password or other authentication token.
|
495
520
|
#
|
496
|
-
#
|
521
|
+
# These will be sent to #authenticate as positional arguments-the exact
|
522
|
+
# semantics are dependent on the +authtype+.
|
523
|
+
#
|
524
|
+
# See the discussion of Net::SMTP@SMTP+Authentication in the overview notes.
|
497
525
|
#
|
498
526
|
# === Errors
|
499
527
|
#
|
@@ -521,7 +549,7 @@ module Net
|
|
521
549
|
new(address, port, tls: tls, starttls: starttls, tls_verify: tls_verify, tls_hostname: tls_hostname, ssl_context_params: ssl_context_params).start(helo: helo, user: user, secret: secret, authtype: authtype, &block)
|
522
550
|
end
|
523
551
|
|
524
|
-
# +true+ if the SMTP session has been started.
|
552
|
+
# +true+ if the \SMTP session has been started.
|
525
553
|
def started?
|
526
554
|
@started
|
527
555
|
end
|
@@ -538,11 +566,21 @@ module Net
|
|
538
566
|
# +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see
|
539
567
|
# the discussion in the overview notes.
|
540
568
|
#
|
541
|
-
#
|
542
|
-
#
|
543
|
-
#
|
544
|
-
#
|
545
|
-
#
|
569
|
+
# The remaining arguments are used for \SMTP authentication, if required or
|
570
|
+
# desired.
|
571
|
+
#
|
572
|
+
# +authtype+ is the SASL authentication mechanism.
|
573
|
+
#
|
574
|
+
# +user+ is the authentication or authorization identity.
|
575
|
+
#
|
576
|
+
# +secret+ or +password+ is your password or other authentication token.
|
577
|
+
#
|
578
|
+
# These will be sent to #authenticate as positional arguments-the exact
|
579
|
+
# semantics are dependent on the +authtype+.
|
580
|
+
#
|
581
|
+
# See the discussion of Net::SMTP@SMTP+Authentication in the overview notes.
|
582
|
+
#
|
583
|
+
# See also: Net::SMTP.start
|
546
584
|
#
|
547
585
|
# === Block Usage
|
548
586
|
#
|
@@ -622,28 +660,24 @@ module Net
|
|
622
660
|
private
|
623
661
|
|
624
662
|
def tcp_socket(address, port)
|
625
|
-
|
626
|
-
Socket.tcp address, port, nil, nil, connect_timeout: @open_timeout
|
627
|
-
rescue Errno::ETIMEDOUT #raise Net:OpenTimeout instead for compatibility with previous versions
|
628
|
-
raise Net::OpenTimeout, "Timeout to open TCP connection to "\
|
629
|
-
"#{address}:#{port} (exceeds #{@open_timeout} seconds)"
|
630
|
-
end
|
663
|
+
TCPSocket.open address, port
|
631
664
|
end
|
632
665
|
|
633
666
|
def do_start(helo_domain, user, secret, authtype)
|
634
667
|
raise IOError, 'SMTP session already started' if @started
|
635
|
-
if user
|
636
|
-
|
637
|
-
|
668
|
+
if user || secret || authtype
|
669
|
+
check_auth_args authtype, user, secret
|
670
|
+
end
|
671
|
+
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do
|
672
|
+
tcp_socket(@address, @port)
|
638
673
|
end
|
639
|
-
s = tcp_socket(@address, @port)
|
640
674
|
logging "Connection opened: #{@address}:#{@port}"
|
641
675
|
@socket = new_internet_message_io(tls? ? tlsconnect(s, @ssl_context_tls) : s)
|
642
676
|
check_response critical { recv_response() }
|
643
677
|
do_helo helo_domain
|
644
678
|
if ! tls? and (starttls_always? or (capable_starttls? and starttls_auto?))
|
645
679
|
unless capable_starttls?
|
646
|
-
raise SMTPUnsupportedCommand
|
680
|
+
raise SMTPUnsupportedCommand, "STARTTLS is not supported on this server"
|
647
681
|
end
|
648
682
|
starttls
|
649
683
|
@socket = new_internet_message_io(tlsconnect(s, @ssl_context_starttls))
|
@@ -703,6 +737,18 @@ module Net
|
|
703
737
|
@socket = nil
|
704
738
|
end
|
705
739
|
|
740
|
+
def requires_smtputf8(address)
|
741
|
+
if address.kind_of? Address
|
742
|
+
!address.address.ascii_only?
|
743
|
+
else
|
744
|
+
!address.ascii_only?
|
745
|
+
end
|
746
|
+
end
|
747
|
+
|
748
|
+
def any_require_smtputf8(addresses)
|
749
|
+
addresses.any?{ |a| requires_smtputf8(a) }
|
750
|
+
end
|
751
|
+
|
706
752
|
#
|
707
753
|
# Message Sending
|
708
754
|
#
|
@@ -746,7 +792,9 @@ module Net
|
|
746
792
|
# * IOError
|
747
793
|
#
|
748
794
|
def send_message(msgstr, from_addr, *to_addrs)
|
795
|
+
to_addrs.flatten!
|
749
796
|
raise IOError, 'closed session' unless @socket
|
797
|
+
from_addr = Address.new(from_addr, 'SMTPUTF8') if any_require_smtputf8(to_addrs) && capable?('SMTPUTF8')
|
750
798
|
mailfrom from_addr
|
751
799
|
rcptto_list(to_addrs) {data msgstr}
|
752
800
|
end
|
@@ -799,7 +847,9 @@ module Net
|
|
799
847
|
# * IOError
|
800
848
|
#
|
801
849
|
def open_message_stream(from_addr, *to_addrs, &block) # :yield: stream
|
850
|
+
to_addrs.flatten!
|
802
851
|
raise IOError, 'closed session' unless @socket
|
852
|
+
from_addr = Address.new(from_addr, 'SMTPUTF8') if any_require_smtputf8(to_addrs) && capable?('SMTPUTF8')
|
803
853
|
mailfrom from_addr
|
804
854
|
rcptto_list(to_addrs) {data(&block)}
|
805
855
|
end
|
@@ -810,92 +860,28 @@ module Net
|
|
810
860
|
# Authentication
|
811
861
|
#
|
812
862
|
|
813
|
-
public
|
814
|
-
|
815
863
|
DEFAULT_AUTH_TYPE = :plain
|
816
864
|
|
865
|
+
# Authenticates with the server, using the "AUTH" command.
|
866
|
+
#
|
867
|
+
# +authtype+ is the name of a SASL authentication mechanism.
|
868
|
+
#
|
869
|
+
# All arguments-other than +authtype+-are forwarded to the authenticator.
|
870
|
+
# Different authenticators may interpret the +user+ and +secret+
|
871
|
+
# arguments differently.
|
817
872
|
def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE)
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
end
|
822
|
-
|
823
|
-
def auth_plain(user, secret)
|
824
|
-
check_auth_args user, secret
|
825
|
-
res = critical {
|
826
|
-
get_response('AUTH PLAIN ' + base64_encode("\0#{user}\0#{secret}"))
|
827
|
-
}
|
828
|
-
check_auth_response res
|
829
|
-
res
|
830
|
-
end
|
831
|
-
|
832
|
-
def auth_login(user, secret)
|
833
|
-
check_auth_args user, secret
|
834
|
-
res = critical {
|
835
|
-
check_auth_continue get_response('AUTH LOGIN')
|
836
|
-
check_auth_continue get_response(base64_encode(user))
|
837
|
-
get_response(base64_encode(secret))
|
838
|
-
}
|
839
|
-
check_auth_response res
|
840
|
-
res
|
841
|
-
end
|
842
|
-
|
843
|
-
def auth_cram_md5(user, secret)
|
844
|
-
check_auth_args user, secret
|
845
|
-
res = critical {
|
846
|
-
res0 = get_response('AUTH CRAM-MD5')
|
847
|
-
check_auth_continue res0
|
848
|
-
crammed = cram_md5_response(secret, res0.cram_md5_challenge)
|
849
|
-
get_response(base64_encode("#{user} #{crammed}"))
|
850
|
-
}
|
851
|
-
check_auth_response res
|
852
|
-
res
|
873
|
+
check_auth_args authtype, user, secret
|
874
|
+
authenticator = Authenticator.auth_class(authtype).new(self)
|
875
|
+
authenticator.auth(user, secret)
|
853
876
|
end
|
854
877
|
|
855
878
|
private
|
856
879
|
|
857
|
-
def
|
858
|
-
|
880
|
+
def check_auth_args(type, *args, **kwargs)
|
881
|
+
type ||= DEFAULT_AUTH_TYPE
|
882
|
+
klass = Authenticator.auth_class(type) or
|
859
883
|
raise ArgumentError, "wrong authentication type #{type}"
|
860
|
-
|
861
|
-
end
|
862
|
-
|
863
|
-
def auth_method(type)
|
864
|
-
"auth_#{type.to_s.downcase}".intern
|
865
|
-
end
|
866
|
-
|
867
|
-
def check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE)
|
868
|
-
unless user
|
869
|
-
raise ArgumentError, 'SMTP-AUTH requested but missing user name'
|
870
|
-
end
|
871
|
-
unless secret
|
872
|
-
raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase'
|
873
|
-
end
|
874
|
-
end
|
875
|
-
|
876
|
-
def base64_encode(str)
|
877
|
-
# expects "str" may not become too long
|
878
|
-
[str].pack('m0')
|
879
|
-
end
|
880
|
-
|
881
|
-
IMASK = 0x36
|
882
|
-
OMASK = 0x5c
|
883
|
-
|
884
|
-
# CRAM-MD5: [RFC2195]
|
885
|
-
def cram_md5_response(secret, challenge)
|
886
|
-
tmp = Digest::MD5.digest(cram_secret(secret, IMASK) + challenge)
|
887
|
-
Digest::MD5.hexdigest(cram_secret(secret, OMASK) + tmp)
|
888
|
-
end
|
889
|
-
|
890
|
-
CRAM_BUFSIZE = 64
|
891
|
-
|
892
|
-
def cram_secret(secret, mask)
|
893
|
-
secret = Digest::MD5.digest(secret) if secret.size > CRAM_BUFSIZE
|
894
|
-
buf = secret.ljust(CRAM_BUFSIZE, "\0")
|
895
|
-
0.upto(buf.size - 1) do |i|
|
896
|
-
buf[i] = (buf[i].ord ^ mask).chr
|
897
|
-
end
|
898
|
-
buf
|
884
|
+
klass.check_args(*args, **kwargs)
|
899
885
|
end
|
900
886
|
|
901
887
|
#
|
@@ -924,29 +910,20 @@ module Net
|
|
924
910
|
|
925
911
|
# +from_addr+ is +String+ or +Net::SMTP::Address+
|
926
912
|
def mailfrom(from_addr)
|
927
|
-
addr =
|
913
|
+
addr = if requires_smtputf8(from_addr) && capable?("SMTPUTF8")
|
914
|
+
Address.new(from_addr, "SMTPUTF8")
|
915
|
+
else
|
916
|
+
Address.new(from_addr)
|
917
|
+
end
|
928
918
|
getok((["MAIL FROM:<#{addr.address}>"] + addr.parameters).join(' '))
|
929
919
|
end
|
930
920
|
|
931
921
|
def rcptto_list(to_addrs)
|
932
922
|
raise ArgumentError, 'mail destination not given' if to_addrs.empty?
|
933
|
-
ok_users = []
|
934
|
-
unknown_users = []
|
935
923
|
to_addrs.flatten.each do |addr|
|
936
|
-
|
937
|
-
rcptto addr
|
938
|
-
rescue SMTPAuthenticationError
|
939
|
-
unknown_users << addr.to_s.dump
|
940
|
-
else
|
941
|
-
ok_users << addr
|
942
|
-
end
|
924
|
+
rcptto addr
|
943
925
|
end
|
944
|
-
|
945
|
-
ret = yield
|
946
|
-
unless unknown_users.empty?
|
947
|
-
raise SMTPAuthenticationError, "failed to deliver for #{unknown_users.join(', ')}"
|
948
|
-
end
|
949
|
-
ret
|
926
|
+
yield
|
950
927
|
end
|
951
928
|
|
952
929
|
# +to_addr+ is +String+ or +Net::SMTP::Address+
|
@@ -1009,6 +986,12 @@ module Net
|
|
1009
986
|
getok('QUIT')
|
1010
987
|
end
|
1011
988
|
|
989
|
+
def get_response(reqline)
|
990
|
+
validate_line reqline
|
991
|
+
@socket.writeline reqline
|
992
|
+
recv_response()
|
993
|
+
end
|
994
|
+
|
1012
995
|
private
|
1013
996
|
|
1014
997
|
def validate_line(line)
|
@@ -1028,12 +1011,6 @@ module Net
|
|
1028
1011
|
res
|
1029
1012
|
end
|
1030
1013
|
|
1031
|
-
def get_response(reqline)
|
1032
|
-
validate_line reqline
|
1033
|
-
@socket.writeline reqline
|
1034
|
-
recv_response()
|
1035
|
-
end
|
1036
|
-
|
1037
1014
|
def recv_response
|
1038
1015
|
buf = ''.dup
|
1039
1016
|
while true
|
@@ -1066,18 +1043,6 @@ module Net
|
|
1066
1043
|
end
|
1067
1044
|
end
|
1068
1045
|
|
1069
|
-
def check_auth_response(res)
|
1070
|
-
unless res.success?
|
1071
|
-
raise SMTPAuthenticationError.new(res)
|
1072
|
-
end
|
1073
|
-
end
|
1074
|
-
|
1075
|
-
def check_auth_continue(res)
|
1076
|
-
unless res.continue?
|
1077
|
-
raise res.exception_class.new(res)
|
1078
|
-
end
|
1079
|
-
end
|
1080
|
-
|
1081
1046
|
# This class represents a response received by the SMTP server. Instances
|
1082
1047
|
# of this class are created by the SMTP class; they should not be directly
|
1083
1048
|
# created by the user. For more information on SMTP responses, view
|
@@ -1165,7 +1130,7 @@ module Net
|
|
1165
1130
|
class Address
|
1166
1131
|
# mail address [String]
|
1167
1132
|
attr_reader :address
|
1168
|
-
#
|
1133
|
+
# parameters [Array<String>]
|
1169
1134
|
attr_reader :parameters
|
1170
1135
|
|
1171
1136
|
# :call-seq:
|
@@ -1179,17 +1144,21 @@ module Net
|
|
1179
1144
|
@parameters = address.parameters
|
1180
1145
|
else
|
1181
1146
|
@address = address
|
1182
|
-
@parameters =
|
1147
|
+
@parameters = []
|
1183
1148
|
end
|
1149
|
+
@parameters = (parameters + args + [kw_args]).map{|param| Array(param)}.flatten(1).map{|param| Array(param).compact.join('=')}.uniq
|
1184
1150
|
end
|
1185
1151
|
|
1186
1152
|
def to_s
|
1187
1153
|
@address
|
1188
1154
|
end
|
1189
1155
|
end
|
1190
|
-
|
1191
1156
|
end # class SMTP
|
1192
1157
|
|
1193
1158
|
SMTPSession = SMTP # :nodoc:
|
1159
|
+
end
|
1194
1160
|
|
1161
|
+
require_relative 'smtp/authenticator'
|
1162
|
+
Dir.glob("#{__dir__}/smtp/auth_*.rb") do |r|
|
1163
|
+
require_relative r
|
1195
1164
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-smtp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yukihiro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-protocol
|
@@ -24,34 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: digest
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: timeout
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
27
|
description: Simple Mail Transfer Protocol client library for Ruby.
|
56
28
|
email:
|
57
29
|
- matz@ruby-lang.org
|
@@ -60,8 +32,14 @@ extensions: []
|
|
60
32
|
extra_rdoc_files: []
|
61
33
|
files:
|
62
34
|
- LICENSE.txt
|
35
|
+
- NEWS.md
|
36
|
+
- README.md
|
63
37
|
- lib/net/smtp.rb
|
64
|
-
- net
|
38
|
+
- lib/net/smtp/auth_cram_md5.rb
|
39
|
+
- lib/net/smtp/auth_login.rb
|
40
|
+
- lib/net/smtp/auth_plain.rb
|
41
|
+
- lib/net/smtp/auth_xoauth2.rb
|
42
|
+
- lib/net/smtp/authenticator.rb
|
65
43
|
homepage: https://github.com/ruby/net-smtp
|
66
44
|
licenses:
|
67
45
|
- Ruby
|
@@ -84,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
62
|
- !ruby/object:Gem::Version
|
85
63
|
version: '0'
|
86
64
|
requirements: []
|
87
|
-
rubygems_version: 3.3
|
65
|
+
rubygems_version: 3.5.3
|
88
66
|
signing_key:
|
89
67
|
specification_version: 4
|
90
68
|
summary: Simple Mail Transfer Protocol client library for Ruby.
|
data/net-smtp.gemspec
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
name = File.basename(__FILE__, ".gemspec")
|
4
|
-
version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
|
5
|
-
break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
|
6
|
-
/^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
|
7
|
-
end rescue nil
|
8
|
-
end
|
9
|
-
|
10
|
-
Gem::Specification.new do |spec|
|
11
|
-
spec.name = name
|
12
|
-
spec.version = version
|
13
|
-
spec.authors = ["Yukihiro Matsumoto"]
|
14
|
-
spec.email = ["matz@ruby-lang.org"]
|
15
|
-
|
16
|
-
spec.summary = %q{Simple Mail Transfer Protocol client library for Ruby.}
|
17
|
-
spec.description = %q{Simple Mail Transfer Protocol client library for Ruby.}
|
18
|
-
spec.homepage = "https://github.com/ruby/net-smtp"
|
19
|
-
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
20
|
-
spec.required_ruby_version = ">= 2.6.0"
|
21
|
-
|
22
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
23
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
24
|
-
|
25
|
-
spec.files = %w[
|
26
|
-
LICENSE.txt
|
27
|
-
lib/net/smtp.rb
|
28
|
-
net-smtp.gemspec
|
29
|
-
]
|
30
|
-
spec.require_paths = ["lib"]
|
31
|
-
|
32
|
-
spec.add_dependency "net-protocol"
|
33
|
-
spec.add_dependency "digest"
|
34
|
-
spec.add_dependency "timeout"
|
35
|
-
end
|