uri-smtp 0.3.0 → 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/CHANGELOG.md +22 -0
- data/README.md +27 -5
- data/lib/uri/smtp/version.rb +1 -1
- data/lib/uri/smtp.rb +84 -13
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 457b3741b5ef4678c7f1c6e19574f24d68d5f515ef58c6879f64516c8d472049
|
4
|
+
data.tar.gz: ecd3d5e89df1874095936cd804fd4241feefed5f2e8f6eb0f3015906d1f63cf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98b76dad4efd9c9c53f674ef06139844f8845415592bb9927ad90a7d903c62ef388a944779f55987d219035fac120e67247f50251228016db86c346e4d3bc8d3
|
7
|
+
data.tar.gz: 530215f54f3c2e1e1c78d99f476b30c11438136e1313d6abc26e7e830ee885f999c0dc90ce3e4874ac9ca11c7e45c3606a156e236ccf676bba33917b58534e18
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.0] - 2025-07-25
|
4
|
+
|
5
|
+
- Add: `uri#read_timeout`, `uri#open_timeout`
|
6
|
+
Coerced integers from query:
|
7
|
+
```ruby
|
8
|
+
URI("smtp://foo?read_timeout=1").read_timeout #=> 1
|
9
|
+
```
|
10
|
+
Included in `to_h`.
|
11
|
+
- Add: `uri.decoded_userinfo(format: ...)`
|
12
|
+
`:format` can be one of `[:string :array :hash]`
|
13
|
+
- Add: domain can appear in fragment
|
14
|
+
```ruby
|
15
|
+
URI("smtp://foo.org#sender.org").domain #=> "sender.org"
|
16
|
+
```
|
17
|
+
NOTE Any domain from the query takes precedence.
|
18
|
+
- Fix: "smtps+foo://..." having no tls
|
19
|
+
|
20
|
+
## [0.4.0] - 2025-07-23
|
21
|
+
|
22
|
+
- FIX: correct settings for action_mailer using mail v2.8.1
|
23
|
+
|
3
24
|
## [0.3.0] - 2025-07-23
|
4
25
|
|
5
26
|
- FIX: Kernel.URI should accept URI's
|
@@ -7,3 +28,4 @@
|
|
7
28
|
## [0.2.0] - 2025-07-18
|
8
29
|
|
9
30
|
- Feature complete
|
31
|
+
|
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",
|
@@ -56,6 +77,7 @@ URI("smtps+login://user%40gmail.com:p%40ss@smtp.gmail.com?domain=sender.org").to
|
|
56
77
|
Formatting for action_mailer configuration, use `to_h(format: :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",
|
@@ -89,7 +111,7 @@ There's no official specification for SMTP-URIs. There's some prior work though.
|
|
89
111
|
SMTP with TLS.
|
90
112
|
|
91
113
|
> [!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`).
|
114
|
+
> 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
115
|
|
94
116
|
|
95
117
|
### auth
|
data/lib/uri/smtp/version.rb
CHANGED
data/lib/uri/smtp.rb
CHANGED
@@ -21,6 +21,7 @@ module URI
|
|
21
21
|
return @port if @port
|
22
22
|
return 25 if host_local?
|
23
23
|
return 465 if tls?
|
24
|
+
|
24
25
|
587
|
25
26
|
end
|
26
27
|
|
@@ -30,15 +31,56 @@ module URI
|
|
30
31
|
return parsed_query["auth"] if parsed_query.has_key?("auth")
|
31
32
|
return nil if scheme_auth == "none"
|
32
33
|
return scheme_auth if scheme_auth
|
34
|
+
|
33
35
|
"plain"
|
34
36
|
end
|
35
37
|
|
38
|
+
# all formats: return nil when userinfo == nil.
|
39
|
+
#
|
40
|
+
# format: :array
|
41
|
+
# Never contains empty strings (as opposed to [#user, #password]).
|
42
|
+
# Example:
|
43
|
+
# Given #<URI::SMTP smtps://:token@smtp.gmail.com>
|
44
|
+
# Then:
|
45
|
+
# [uri.user, uri.password] #=> ["", "token"]
|
46
|
+
# uri.decoded_userinfo #=> [nil, "token"]
|
47
|
+
#
|
48
|
+
# format: :hash
|
49
|
+
# Keys are absent when value would be `nil`.
|
50
|
+
# Example:
|
51
|
+
# Given #<URI::SMTP smtps://:token@smtp.gmail.com>
|
52
|
+
# Then:
|
53
|
+
# uri.decoded_userinfo(format: :array) #=> [nil, "token"]
|
54
|
+
# uri.decoded_userinfo(format: :to_h) #=> {password: "token"}
|
55
|
+
def decoded_userinfo(format: :string)
|
56
|
+
return if userinfo.nil?
|
57
|
+
|
58
|
+
case format
|
59
|
+
when :string
|
60
|
+
[decoded_user, decoded_password].compact.join(":")
|
61
|
+
when :array
|
62
|
+
[string_presence(decoded_user), string_presence(decoded_password)]
|
63
|
+
when :hash
|
64
|
+
{
|
65
|
+
user: string_presence(decoded_user),
|
66
|
+
password: string_presence(decoded_password)
|
67
|
+
}.delete_if { |_k, v| v.nil? }
|
68
|
+
else
|
69
|
+
raise ArgumentError,
|
70
|
+
"Unknown format #{format.inspect}. Should be one of #{%i[string array hash].inspect}."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
36
74
|
def domain
|
37
|
-
parsed_query["domain"]
|
75
|
+
parsed_query["domain"] || fragment
|
38
76
|
end
|
39
77
|
|
40
|
-
def
|
41
|
-
|
78
|
+
def read_timeout
|
79
|
+
parsed_query["read_timeout"]
|
80
|
+
end
|
81
|
+
|
82
|
+
def open_timeout
|
83
|
+
parsed_query["open_timeout"]
|
42
84
|
end
|
43
85
|
|
44
86
|
def starttls
|
@@ -46,12 +88,13 @@ module URI
|
|
46
88
|
return parsed_query["starttls"] if parsed_query.has_key?("starttls")
|
47
89
|
return false if host_local?
|
48
90
|
return false if insecure?
|
91
|
+
|
49
92
|
:always
|
50
93
|
end
|
51
94
|
alias_method :starttls?, :starttls
|
52
95
|
|
53
96
|
def tls
|
54
|
-
scheme
|
97
|
+
!!scheme[/^smtps/]
|
55
98
|
end
|
56
99
|
alias_method :tls?, :tls
|
57
100
|
|
@@ -64,14 +107,18 @@ module URI
|
|
64
107
|
end
|
65
108
|
|
66
109
|
def parsed_query
|
67
|
-
@parsed_query ||= URI.decode_www_form(query.to_s).to_h
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
110
|
+
@parsed_query ||= URI.decode_www_form(query.to_s).to_h
|
111
|
+
.delete_if { |_k, v| !string_presence(v) }
|
112
|
+
.tap do
|
113
|
+
_1["read_timeout"] &&= _1["read_timeout"].to_i
|
114
|
+
_1["open_timeout"] &&= _1["open_timeout"].to_i
|
115
|
+
_1["starttls"] &&= case _1["starttls"]
|
116
|
+
when "always", "auto" then _1["starttls"].to_sym
|
117
|
+
when "false" then false
|
118
|
+
else
|
119
|
+
:always
|
120
|
+
end
|
73
121
|
end
|
74
|
-
end
|
75
122
|
end
|
76
123
|
|
77
124
|
def to_h(format: nil)
|
@@ -81,20 +128,34 @@ module URI
|
|
81
128
|
address: host,
|
82
129
|
authentication: auth,
|
83
130
|
domain:,
|
84
|
-
enable_starttls: starttls,
|
85
|
-
|
131
|
+
enable_starttls: starttls == :always,
|
132
|
+
enable_starttls_auto: starttls == :auto,
|
133
|
+
open_timeout:,
|
134
|
+
port:,
|
135
|
+
read_timeout:,
|
136
|
+
tls:
|
86
137
|
}.tap do
|
87
138
|
unless _1[:authentication].nil?
|
88
139
|
_1[:user_name] = decoded_user
|
89
140
|
_1[:password] = decoded_password
|
90
141
|
end
|
142
|
+
# mail 2.8.1 logic is faulty in that it shortcuts
|
143
|
+
# (start)tls-settings when they are false.
|
144
|
+
# So we delete these flags.
|
145
|
+
_1.delete(:tls) unless _1[:tls]
|
146
|
+
_1.delete(:enable_starttls) unless _1[:enable_starttls]
|
147
|
+
_1.delete(:enable_starttls) if _1[:tls]
|
148
|
+
_1.delete(:enable_starttls_auto) unless _1[:enable_starttls_auto]
|
149
|
+
_1.delete(:enable_starttls_auto) if _1[:tls]
|
91
150
|
end.delete_if { |_k, v| v.nil? }
|
92
151
|
else
|
93
152
|
{
|
94
153
|
auth:,
|
95
154
|
domain:,
|
96
155
|
host:,
|
156
|
+
open_timeout:,
|
97
157
|
port:,
|
158
|
+
read_timeout:,
|
98
159
|
scheme:,
|
99
160
|
starttls:,
|
100
161
|
tls:
|
@@ -110,6 +171,16 @@ module URI
|
|
110
171
|
def self.parse(uri)
|
111
172
|
new(*URI.split(uri))
|
112
173
|
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def scheme_auth
|
178
|
+
scheme[/.*(?:\+(.+))/, 1]
|
179
|
+
end
|
180
|
+
|
181
|
+
def string_presence(s)
|
182
|
+
s.to_s.strip.then { _1 unless _1.empty? }
|
183
|
+
end
|
113
184
|
end
|
114
185
|
|
115
186
|
register_scheme "SMTP", SMTP
|