uri-smtp 0.4.0 → 0.6.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/.yardopts +6 -0
- data/CHANGELOG.md +26 -0
- data/README.md +33 -8
- data/lib/uri/smtp/version.rb +1 -1
- data/lib/uri/smtp.rb +202 -23
- data/rakelib/yard.rake +12 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9aa4d8b92e611c33b96e27f740ed87ecabb90dd69c454828d8246e3c405b9ba5
|
4
|
+
data.tar.gz: 476ad95a2ef969f89fb9bf1b56f278686091bb99ad9de8c5ab379e1bcb10aaf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63b77eee5fd37f45f1f270bf956ab2ff6f5ae4699907e3b86ebf249dc3b4d7228f6ff95bbf7f36aff748b3d80a0d124162808a2a034ea9c721f361eab0f0ee0e
|
7
|
+
data.tar.gz: 031a0988bc86f82cfb8dd6998fbe3f188f0957e25bd80845bc80f5f4bc7ff06e33df30bbe1a0e57a77d7614f6cb2979424b974e2bfa40a51ca21c9713a1ba488
|
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.6.0] - 2025-07-27
|
4
|
+
|
5
|
+
- Add: API-docs at https://eval.github.io/uri-smtp/
|
6
|
+
- Fix: "smtp+insecure+foo://..." not considered `#insecure?`
|
7
|
+
- Fix: "smtp://foo.org?auth=none" being ignored
|
8
|
+
- Fix: "smtp+insecure://..." having auth "insecure"
|
9
|
+
- Remove: `#starttls?`
|
10
|
+
|
11
|
+
## [0.5.0] - 2025-07-25
|
12
|
+
|
13
|
+
- Add: `uri#read_timeout`, `uri#open_timeout`
|
14
|
+
Coerced integers from query:
|
15
|
+
```ruby
|
16
|
+
URI("smtp://foo?read_timeout=1").read_timeout #=> 1
|
17
|
+
```
|
18
|
+
Included in `to_h`.
|
19
|
+
- Add: `uri.decoded_userinfo(format: ...)`
|
20
|
+
`:format` can be one of `[:string :array :hash]`
|
21
|
+
- Add: domain can appear in fragment
|
22
|
+
```ruby
|
23
|
+
URI("smtp://foo.org#sender.org").domain #=> "sender.org"
|
24
|
+
```
|
25
|
+
NOTE Any domain from the query takes precedence.
|
26
|
+
- Fix: "smtps+foo://..." having no tls
|
27
|
+
|
3
28
|
## [0.4.0] - 2025-07-23
|
4
29
|
|
5
30
|
- FIX: correct settings for action_mailer using mail v2.8.1
|
@@ -11,3 +36,4 @@
|
|
11
36
|
## [0.2.0] - 2025-07-18
|
12
37
|
|
13
38
|
- Feature complete
|
39
|
+
|
data/README.md
CHANGED
@@ -1,6 +1,25 @@
|
|
1
1
|
# URI::SMTP
|
2
2
|
|
3
|
-
|
3
|
+
Extends Ruby's `URI` with support for SMTP-uri's.
|
4
|
+
This allows for more concise SMTP-config:
|
5
|
+
```diff
|
6
|
+
# config/environments/production.rb
|
7
|
+
config.action_mailer.delivery_method = :smtp
|
8
|
+
- config.action_mailer.smtp_settings = {
|
9
|
+
- address: "smtp.gmail.com",
|
10
|
+
- port: 587,
|
11
|
+
- domain: "example.com",
|
12
|
+
- user_name: Rails.application.credentials.dig(:smtp, :user_name),
|
13
|
+
- password: Rails.application.credentials.dig(:smtp, :password),
|
14
|
+
- authentication: "plain",
|
15
|
+
- enable_starttls: true,
|
16
|
+
- open_timeout: 5,
|
17
|
+
- read_timeout: 5
|
18
|
+
- }
|
19
|
+
# given ENV["SMPT_URL"]:
|
20
|
+
# "smtp://user_name:password@smtp.gmail.com?open_timeout=5&read_timeout=5#example.com"
|
21
|
+
+ config.action_mailer.smtp_settings = URI(ENV.fetch("SMTP_URL")).to_h(format: :am)
|
22
|
+
```
|
4
23
|
|
5
24
|
## Installation
|
6
25
|
|
@@ -21,27 +40,29 @@ gem install uri-smtp
|
|
21
40
|
### parse
|
22
41
|
|
23
42
|
```ruby
|
24
|
-
u = URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com
|
43
|
+
u = URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com#sender.org")
|
25
44
|
|
26
45
|
url.scheme #=> "smtps+login"
|
27
46
|
url.auth #=> "login"
|
28
47
|
url.starttls #=> false
|
48
|
+
url.starttls? #=> false
|
29
49
|
url.tls? #=> true
|
30
50
|
url.userinfo #=> "user%40gmail.com:p%40ss"
|
51
|
+
url.decoded_userinfo #=> "user@gmail.com:p@ss"
|
31
52
|
url.decoded_user #=> "user@gmail.com"
|
32
53
|
url.user #=> "user%40gmail.com"
|
33
54
|
url.decoded_password #=> "p@ss"
|
34
55
|
url.password #=> "p%40ss"
|
35
56
|
url.host #=> "smtp.gmail.com"
|
36
57
|
url.port #=> 465
|
37
|
-
url.domain #=>
|
38
|
-
url.query #=> "domain=sender.org"
|
58
|
+
url.domain #=> "sender.org"
|
39
59
|
```
|
40
60
|
|
41
61
|
### to_h
|
42
62
|
|
43
63
|
```ruby
|
44
64
|
URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com?domain=sender.org").to_h
|
65
|
+
#=>
|
45
66
|
{auth: "login",
|
46
67
|
domain: "sender.org",
|
47
68
|
host: "smtp.gmail.com",
|
@@ -53,9 +74,10 @@ URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com?domain=sender.org").to
|
|
53
74
|
password: "p@ss"}
|
54
75
|
```
|
55
76
|
|
56
|
-
|
77
|
+
For [ActionMailer configuration](https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration), use `format: :action_mailer` (or `:am`):
|
57
78
|
```ruby
|
58
79
|
URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com?domain=sender.org").to_h(format: :am)
|
80
|
+
#=>
|
59
81
|
{address: "smtp.gmail.com",
|
60
82
|
authentication: "login",
|
61
83
|
domain: "sender.org",
|
@@ -65,6 +87,8 @@ URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com?domain=sender.org").to
|
|
65
87
|
password: "p@ss"}
|
66
88
|
```
|
67
89
|
|
90
|
+
Besides renaming some keys, this also works around a quirk in `v2.8.1` of the mail-gem (e.g. `tls: false` [skips setting up STARTTLS](https://github.com/mikel/mail/blob/2.8.1/lib/mail/network/delivery_methods/smtp.rb#L115)).
|
91
|
+
|
68
92
|
|
69
93
|
Full Rails config:
|
70
94
|
```ruby
|
@@ -89,17 +113,17 @@ There's no official specification for SMTP-URIs. There's some prior work though.
|
|
89
113
|
SMTP with TLS.
|
90
114
|
|
91
115
|
> [!NOTE]
|
92
|
-
> to get `url.starttls #=> :auto`, provide it in the query: `smtp://foo?auth=auto`. In that case `net-smtp` uses STARTTLS when the server supports it (but won't halt like when using `:always`).
|
116
|
+
> to get `url.starttls #=> :auto`, provide it in the query: `smtp://user:pw@foo?auth=auto`. In that case `net-smtp` uses STARTTLS when the server supports it (but won't halt like when using `:always`).
|
93
117
|
|
94
118
|
|
95
119
|
### auth
|
96
120
|
|
97
|
-
|
121
|
+
Any value for auth that passes the URI-parser is acceptable. Though the following values have special meaning:
|
98
122
|
|
99
123
|
- `none`
|
100
124
|
No authentication is required.
|
101
125
|
- `plain`
|
102
|
-
Authenticate with a username and password using AUTH PLAIN. This is the default behavior.
|
126
|
+
Authenticate with a username and password using AUTH PLAIN. This is the default behavior when no authentication is provided.
|
103
127
|
|
104
128
|
> [!NOTE]
|
105
129
|
> any query's value for `auth` takes precedence.
|
@@ -136,6 +160,7 @@ There's no restriction to the value of auth. Though the following values have sp
|
|
136
160
|
## Development
|
137
161
|
|
138
162
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
163
|
+
Use `bin/yard server --reload` when working on documentation.
|
139
164
|
|
140
165
|
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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
141
166
|
|
data/lib/uri/smtp/version.rb
CHANGED
data/lib/uri/smtp.rb
CHANGED
@@ -3,77 +3,226 @@
|
|
3
3
|
require "uri"
|
4
4
|
require_relative "smtp/version"
|
5
5
|
|
6
|
+
# See https://docs.ruby-lang.org/en/master/URI.html
|
6
7
|
module URI
|
8
|
+
# Class that adds smtp(s)-scheme to the standard URI-module.
|
7
9
|
class SMTP < URI::Generic
|
8
10
|
class Error < StandardError; end
|
9
11
|
|
10
|
-
|
11
|
-
userinfo, host, port, registry,
|
12
|
-
path, opaque,
|
13
|
-
query,
|
14
|
-
fragment,
|
15
|
-
parser = DEFAULT_PARSER,
|
16
|
-
arg_check = false)
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
12
|
+
# @return [Integer]
|
20
13
|
def port
|
21
14
|
return @port if @port
|
22
15
|
return 25 if host_local?
|
23
16
|
return 465 if tls?
|
17
|
+
|
24
18
|
587
|
25
19
|
end
|
26
20
|
|
21
|
+
# Return mechanism of authentication (default `"plain"`).
|
22
|
+
#
|
23
|
+
# Only returns value when {URI::SMTP#userinfo} is provided and authentication is not `"none"`.
|
24
|
+
#
|
25
|
+
# Authentication can be provided via scheme (e.g. `"smtp+login://..."`) or via
|
26
|
+
# query-params (e.g. `"smtp://foo.org?auth=cram-md5"`). The latter takes precedence when both are provided.
|
27
|
+
# A provided value of `"none"` results in `nil`. Other values are returned as is.
|
28
|
+
# @example
|
29
|
+
# # no userinfo
|
30
|
+
# URI("smtp://foo.org").auth #=> nil
|
31
|
+
#
|
32
|
+
# # "none"
|
33
|
+
# URI("smtp+none://user@foo.org").auth #=> nil
|
34
|
+
#
|
35
|
+
# # default value
|
36
|
+
# URI("smtp://user@foo.org").auth #=> "plain"
|
37
|
+
#
|
38
|
+
# # query takes precedence
|
39
|
+
# URI("smtp+login://user@foo.org?auth=cram-md5").auth #=> "cram-md5"
|
40
|
+
# @return [String, nil] mechanism of authentication or `nil`:
|
41
|
+
# @return [nil] when there's no `userinfo`.
|
42
|
+
# @return [nil] if 'auth via query' is `"none"`, e.g. `"smtp://foo.org?auth=none"`.
|
43
|
+
# @return [String] 'auth via query' when present.
|
44
|
+
# @return [nil] if 'auth via scheme' is `"none"`, e.g. `"smtp+none://foo.org"`.
|
45
|
+
# @return [String] 'auth via scheme' when present, e.g. `"smtp+login://foo.org"`.
|
46
|
+
# @return [String] else `"plain"`
|
27
47
|
def auth
|
28
48
|
# net-smtp: passing authtype without user/pw raises error
|
29
49
|
return nil unless userinfo
|
50
|
+
return nil if parsed_query["auth"] == "none"
|
30
51
|
return parsed_query["auth"] if parsed_query.has_key?("auth")
|
31
52
|
return nil if scheme_auth == "none"
|
32
53
|
return scheme_auth if scheme_auth
|
54
|
+
|
33
55
|
"plain"
|
34
56
|
end
|
35
57
|
|
58
|
+
# Decoded userinfo formatted as String, Array or Hash.
|
59
|
+
#
|
60
|
+
# **NOTE** not provided user or password result in `nil` (format: :array) or absent keys (format: :hash).
|
61
|
+
#
|
62
|
+
# @example no userinfo => `nil`
|
63
|
+
# URI("smtp://foo.org").decoded_userinfo #=> nil
|
64
|
+
# URI("smtp://foo.org").decoded_userinfo(format: :array) #=> nil
|
65
|
+
# URI("smtp://foo.org").decoded_userinfo(format: :hash) #=> nil
|
66
|
+
#
|
67
|
+
# @example format `:array`
|
68
|
+
# # absent user/password is `nil`
|
69
|
+
# URI("smtp://user@foo.org").decoded_userinfo(format: :array) #=> ["user", nil]
|
70
|
+
# URI("smtp://:pw@foo.org").decoded_userinfo(format: :array) #=> [nil, "pw"]
|
71
|
+
# # decoded values
|
72
|
+
# URI("smtp://user%40gmail.com:p%40ss@foo.org").decoded_userinfo(format: :array) #=> ["user@gmail.com", "p@ss"]
|
73
|
+
#
|
74
|
+
# @example format `:hash`
|
75
|
+
# # absent user/password is left out
|
76
|
+
# URI("smtp://user%40gmail.com@foo.org").decoded_userinfo(format: :hash) #=> {user: "user@gmail.com"}
|
77
|
+
# URI("smtp://:p%40ss@foo.org").decoded_userinfo(format: :hash) #=> {password: "p@ss"}
|
78
|
+
#
|
79
|
+
# @param format [Symbol] the format type, `:string` (default), `:array` or `:hash`.
|
80
|
+
# @return [String, Array, Hash] Decoded userinfo formatted as String, Array or Hash.
|
81
|
+
def decoded_userinfo(format: :string)
|
82
|
+
return if userinfo.nil?
|
83
|
+
|
84
|
+
case format
|
85
|
+
when :string
|
86
|
+
[decoded_user, decoded_password].join(":")
|
87
|
+
when :array
|
88
|
+
[string_presence(decoded_user), string_presence(decoded_password)]
|
89
|
+
when :hash
|
90
|
+
{
|
91
|
+
user: string_presence(decoded_user),
|
92
|
+
password: string_presence(decoded_password)
|
93
|
+
}.delete_if { |_k, v| v.nil? }
|
94
|
+
else
|
95
|
+
raise ArgumentError,
|
96
|
+
"Unknown format #{format.inspect}. Should be one of #{%i[string array hash].inspect}."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# The host to send mail from, i.e. the `HELO` domain.
|
101
|
+
# @return [String] the query-key `domain` when present, e.g. `"smtp://foo.org?domain=sender.org"`.
|
102
|
+
# @return [String] the `fragment` when present, e.g. `"smtp://foo.org#sender.org"`.
|
103
|
+
# @return [nil] otherwise
|
36
104
|
def domain
|
37
|
-
parsed_query["domain"]
|
105
|
+
parsed_query["domain"] || fragment
|
38
106
|
end
|
39
107
|
|
40
|
-
|
41
|
-
|
108
|
+
# @return [Integer]
|
109
|
+
def read_timeout
|
110
|
+
parsed_query["read_timeout"]
|
42
111
|
end
|
43
112
|
|
113
|
+
# @return [Integer]
|
114
|
+
def open_timeout
|
115
|
+
parsed_query["open_timeout"]
|
116
|
+
end
|
117
|
+
|
118
|
+
# Whether or not to use `STARTTLS`.
|
119
|
+
#
|
120
|
+
# The possible return values (i.e. `:always`, `:auto` and `false`) map to what {https://github.com/ruby/net-smtp net-smtp} uses:
|
121
|
+
# - `:always` use `STARTTLS` or disconnect when server does not support it.
|
122
|
+
# - `:auto` use `STARTTLS` when supported, otherwise continue unencrypted.
|
123
|
+
# - `false` don't use `STARTTLS`.
|
124
|
+
#
|
125
|
+
# @return [false] when `tls?`.
|
126
|
+
# @return [:always, :auto, false] when query-key `starttls` is present, e.g. `"smtp://foo.org?starttls=auto"`.
|
127
|
+
# @return [false] when `host_local?` (the host is considered one for local development).
|
128
|
+
# @return [false] when `insecure?` (i.e. `scheme` starts with `"smtp+insecure"`).
|
129
|
+
# @return [:always] otherwise.
|
44
130
|
def starttls
|
45
131
|
return false if tls?
|
46
132
|
return parsed_query["starttls"] if parsed_query.has_key?("starttls")
|
47
133
|
return false if host_local?
|
48
134
|
return false if insecure?
|
135
|
+
|
49
136
|
:always
|
50
137
|
end
|
51
|
-
alias_method :starttls?, :starttls
|
52
138
|
|
139
|
+
# @return [Boolean] whether or not `scheme` starts with `"smtps"`.
|
53
140
|
def tls
|
54
|
-
scheme
|
141
|
+
!!scheme[/^smtps/]
|
55
142
|
end
|
56
143
|
alias_method :tls?, :tls
|
57
144
|
|
145
|
+
# Whether or not the scheme indicates to skip STARTTLS.
|
146
|
+
#
|
147
|
+
# @see #starttls
|
148
|
+
#
|
149
|
+
# @example
|
150
|
+
# URI("smtp+insecure://foo.org").insecure? #=> true
|
151
|
+
# # This is equivalent (though shorter and more descriptive) to
|
152
|
+
# URI("smtp://foo.org?starttls=false")
|
153
|
+
#
|
154
|
+
# # combine with authentication
|
155
|
+
# URI("smtp+insecure+login://user:pw@foo.org").insecure? #=> true
|
156
|
+
# @return [Boolean] whether `scheme` starts with `"smtp+insecure"`.
|
58
157
|
def insecure?
|
59
|
-
scheme
|
158
|
+
scheme.start_with?("smtp+insecure")
|
60
159
|
end
|
61
160
|
|
161
|
+
# Whether or not `host` is considered local.
|
162
|
+
#
|
163
|
+
# Hostnames that are considered local have certain defaults (i.e. port `25` and no `STARTTLS`).
|
164
|
+
# @example
|
165
|
+
# # Point to mailcatcher (https://github.com/sj26/mailcatcher)
|
166
|
+
# URI("smtp://127.0.0.1:1025").host_local? #=> true
|
167
|
+
#
|
168
|
+
# URI("smtp://localhost").host_local? #=> true
|
169
|
+
# @return [Boolean] whether or not `host` is considered local.
|
62
170
|
def host_local?
|
63
171
|
%w[127.0.0.1 localhost].include?(host)
|
64
172
|
end
|
65
173
|
|
174
|
+
# `query` as Hash with values `starttls`, `read_timeout` and `open_timeout` coerced.
|
175
|
+
# @return [Hash] `query` parsed.
|
66
176
|
def parsed_query
|
67
|
-
@parsed_query ||= URI.decode_www_form(query.to_s).to_h
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
177
|
+
@parsed_query ||= URI.decode_www_form(query.to_s).to_h
|
178
|
+
.delete_if { |_k, v| !string_presence(v) }
|
179
|
+
.tap do
|
180
|
+
_1["read_timeout"] &&= _1["read_timeout"].to_i
|
181
|
+
_1["open_timeout"] &&= _1["open_timeout"].to_i
|
182
|
+
_1["starttls"] &&= case _1["starttls"]
|
183
|
+
when "always", "auto" then _1["starttls"].to_sym
|
184
|
+
when "false" then false
|
185
|
+
else
|
186
|
+
:always
|
187
|
+
end
|
73
188
|
end
|
74
|
-
end
|
75
189
|
end
|
76
190
|
|
191
|
+
# Return {Hash} representing the URI.
|
192
|
+
#
|
193
|
+
# `format` should be one of: `nil` or `:action_mailer` (or `:am`).
|
194
|
+
#
|
195
|
+
# Format `:action_mailer` matches how {https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration ActionMailer} should be configured and works around some quirks in Mail v2.8.1.
|
196
|
+
#
|
197
|
+
# **NOTE** keys with nil-values are stripped.
|
198
|
+
# @example default format
|
199
|
+
# URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com#sender.org").to_h
|
200
|
+
# # =>
|
201
|
+
# # {auth: "login",
|
202
|
+
# # domain: "sender.org",
|
203
|
+
# # host: "smtp.gmail.com",
|
204
|
+
# # port: 465,
|
205
|
+
# # scheme: "smtps+login",
|
206
|
+
# # starttls: false,
|
207
|
+
# # tls: true,
|
208
|
+
# # user: "user@gmail.com",
|
209
|
+
# # password: "p@ss"}
|
210
|
+
# @example format `:action_mailer`/`:am`, ActionMailer configuration
|
211
|
+
# URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com#sender.org").to_h(format: :am)
|
212
|
+
# # =>
|
213
|
+
# # {address: "smtp.gmail.com",
|
214
|
+
# # authentication: "login",
|
215
|
+
# # domain: "sender.org",
|
216
|
+
# # port: 465,
|
217
|
+
# # tls: true,
|
218
|
+
# # user_name: "user@gmail.com",
|
219
|
+
# # password: "p@ss"}
|
220
|
+
# @example Rails configuration
|
221
|
+
# # file: config/environments/development.rb
|
222
|
+
# # Config via env-var SMTP_URL or fallback to mailcatcher.
|
223
|
+
# config.action_mailer.smtp_settings = URI(ENV.fetch("SMTP_URL", "http://127.0.0.1:1025")).to_h(format: :am)
|
224
|
+
# @param format [Symbol] the format type, `nil` (default), `:action_mailer`/`:am`.
|
225
|
+
# @return [Hash]
|
77
226
|
def to_h(format: nil)
|
78
227
|
case format
|
79
228
|
when :am, :action_mailer
|
@@ -83,7 +232,9 @@ module URI
|
|
83
232
|
domain:,
|
84
233
|
enable_starttls: starttls == :always,
|
85
234
|
enable_starttls_auto: starttls == :auto,
|
235
|
+
open_timeout:,
|
86
236
|
port:,
|
237
|
+
read_timeout:,
|
87
238
|
tls:
|
88
239
|
}.tap do
|
89
240
|
unless _1[:authentication].nil?
|
@@ -104,7 +255,9 @@ module URI
|
|
104
255
|
auth:,
|
105
256
|
domain:,
|
106
257
|
host:,
|
258
|
+
open_timeout:,
|
107
259
|
port:,
|
260
|
+
read_timeout:,
|
108
261
|
scheme:,
|
109
262
|
starttls:,
|
110
263
|
tls:
|
@@ -117,9 +270,33 @@ module URI
|
|
117
270
|
end
|
118
271
|
end
|
119
272
|
|
273
|
+
# Parse `uri` and instantiate instance of URI::SMTP.
|
274
|
+
# @example
|
275
|
+
# URI::SMTP.parse("smtps+plain://user:pw@foo.org#sender.org")
|
276
|
+
# #=> #<URI::SMTP smtps+plain://user:pw@foo.org#sender.org>
|
277
|
+
# @return [URI::SMTP] URI::SMTP instance from `uri`.
|
120
278
|
def self.parse(uri)
|
121
279
|
new(*URI.split(uri))
|
122
280
|
end
|
281
|
+
|
282
|
+
private
|
283
|
+
|
284
|
+
def scheme_auth
|
285
|
+
string_absense_in(scheme.split("+").last, %w[smtp smtps insecure])
|
286
|
+
end
|
287
|
+
|
288
|
+
# string_presence("") #=> nil
|
289
|
+
# string_presence(" ") #=> nil
|
290
|
+
# string_presence(" FOO ") #=> " FOO "
|
291
|
+
def string_presence(s)
|
292
|
+
s.to_s.strip.then { _1 unless _1.empty? }
|
293
|
+
end
|
294
|
+
|
295
|
+
# string_absense_in("foo", %w[bar baz]) #=> "foo"
|
296
|
+
# string_absense_in("bar", %w[bar baz]) #=> nil
|
297
|
+
def string_absense_in(s, array)
|
298
|
+
s unless array.include?(s)
|
299
|
+
end
|
123
300
|
end
|
124
301
|
|
125
302
|
register_scheme "SMTP", SMTP
|
@@ -128,6 +305,8 @@ end
|
|
128
305
|
|
129
306
|
module UriSmtpExtensions
|
130
307
|
def parse(uri)
|
308
|
+
# Ensure 'plus schemes' (e.g., `smtp+login://`, `smtp+oauth://`) are parsed as URI::SMTP
|
309
|
+
# instead of URI::Generic objects.
|
131
310
|
if uri.is_a?(String) && uri.start_with?("smtp")
|
132
311
|
return URI::SMTP.parse(uri)
|
133
312
|
end
|
data/rakelib/yard.rake
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "yard"
|
2
|
+
|
3
|
+
YARD::Rake::YardocTask.new(:docs) do |t|
|
4
|
+
# Options defined in `.yardopts` are read first, then merged with
|
5
|
+
# options defined here.
|
6
|
+
#
|
7
|
+
# It's recommended to define options in `.yardopts` instead of here,
|
8
|
+
# as `.yardopts` can be read by external YARD tools, like the
|
9
|
+
# hot-reload YARD server `yard server --reload`.
|
10
|
+
|
11
|
+
# t.options += ['--title', "Something custom"]
|
12
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uri-smtp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gert Goet
|
@@ -17,12 +17,14 @@ extra_rdoc_files: []
|
|
17
17
|
files:
|
18
18
|
- ".rspec"
|
19
19
|
- ".standard.yml"
|
20
|
+
- ".yardopts"
|
20
21
|
- CHANGELOG.md
|
21
22
|
- LICENSE.txt
|
22
23
|
- README.md
|
23
24
|
- Rakefile
|
24
25
|
- lib/uri/smtp.rb
|
25
26
|
- lib/uri/smtp/version.rb
|
27
|
+
- rakelib/yard.rake
|
26
28
|
- sig/uri/smtp.rbs
|
27
29
|
homepage: https://github.com/eval/uri-smtp
|
28
30
|
licenses:
|
@@ -31,6 +33,7 @@ metadata:
|
|
31
33
|
homepage_uri: https://github.com/eval/uri-smtp
|
32
34
|
source_code_uri: https://github.com/eval/uri-smtp
|
33
35
|
changelog_uri: https://github.com/eval/uri-smtp/blob/main/CHANGELOG.md
|
36
|
+
documentation_uri: https://eval.github.io/uri-smtp/
|
34
37
|
rdoc_options: []
|
35
38
|
require_paths:
|
36
39
|
- lib
|