deliverable 0.2.0 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 789cda6bdfbcd5cbd6f552775c78227c1901fba7c7f792e97e9d87f1f0f0411e
4
- data.tar.gz: 5d63aee7ce38ad7b098022909a025d688624eef3bfec1f7418085086eac2eb9b
3
+ metadata.gz: 5707310fb2fd5f22483319b1c826265fab57c588577c55ea9d1a035fc1798819
4
+ data.tar.gz: 221821a449e41fcef0bf7a6ed4628aae8b329377319bbafce912904f268ad662
5
5
  SHA512:
6
- metadata.gz: b1ec53c65f23b78024ef0b4ef4741f8cd55f57f3ab85405ae1376fcb6988220985a1655bcf36ca18996bcfa8e30f63048d6b2a010a9149cc19e8047a0a2a900d
7
- data.tar.gz: e663054eba78bfe71a4638e1e07bd098e17850d32d2de5cdebe96bad7721f897c5bcbc05976126a54ed46d52e0d7f0e74baa6e6f7be821f15d19483492faeb98
6
+ metadata.gz: 7a9078a8afc6269ac8ffd2b8f08ad3e2553d60ec6cbbedd11f9a4632dfb6fca6a1d37116ddf5f09af8992d33337c26105c749d6bafed471d29d1cd31a87a7b10
7
+ data.tar.gz: 2d87ee0c900bc6582186d5d6ab2799e3ac08de8d1757e086414a1929636aa84e97c2c580f72f9508bb1de758e0dbd24393c470e9f08816c117ef1d54e4a2022f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.2
4
+
5
+ - Fix: when every SMTP port refused the connection on a non-problematic
6
+ MX, the verifier classified the address as `invalid` and turned off
7
+ `retryable`. A refused connection is not evidence that the mailbox
8
+ doesn't exist (firewall rules, IP reputation, or a temporarily down
9
+ server look identical), so the result is now `risky` + `retryable`,
10
+ matching the behavior already in place for problematic MX hosts.
11
+ - Tests: added coverage for the SMTP probing path (catch-all leak,
12
+ hard/soft RCPT responses, problematic-server fallback, refused
13
+ connections).
14
+
15
+ ## 0.2.1
16
+
17
+ - Fix: the catch-all probe was overwriting `smtp_response` and
18
+ `retryable` on the Result. A verification that returned a clean 250
19
+ for the real address could surface a 550 from the fake address used
20
+ to detect accept-all servers, making it look like the verifier had
21
+ ignored a hard bounce. The catch-all probe now runs silently and
22
+ only the real address's SMTP response is reported.
23
+
3
24
  ## 0.2.0
4
25
 
5
26
  - Add `smtp_response` to the result: the SMTP code and message returned by
@@ -206,23 +206,20 @@ module Deliverable
206
206
  end
207
207
 
208
208
  def probe_ports(mail_server)
209
- last = nil
210
-
211
209
  SMTP_PORTS.each do |port|
212
210
  result = attempt_rcpt(mail_server, port, @email)
213
211
 
214
212
  return result if result == :verified || result == :invalid
215
213
 
216
- last = result
217
214
  next if result == :connection_failed
218
215
 
219
216
  return result if result == :assumed && !problematic_server?(mail_server)
220
217
  end
221
218
 
222
- problematic_server?(mail_server) ? :assumed : (last || :assumed)
219
+ :assumed
223
220
  end
224
221
 
225
- def attempt_rcpt(mail_server, port, recipient)
222
+ def attempt_rcpt(mail_server, port, recipient, record: true)
226
223
  Timeout.timeout(@timeout) do
227
224
  smtp = Net::SMTP.new(mail_server, port)
228
225
  smtp.enable_starttls_auto if port == 587 || port == 465
@@ -231,47 +228,47 @@ module Deliverable
231
228
  conn.mailfrom(@sender_email)
232
229
  begin
233
230
  response = conn.rcptto(recipient)
234
- record_response(response.status, response.message) if response.respond_to?(:status)
231
+ record_response(response.status, response.message) if record && response.respond_to?(:status)
235
232
  return :verified
236
233
  rescue Net::SMTPFatalError => e
237
- record_error(e)
238
- classify_fatal(e.message)
234
+ record_error(e) if record
235
+ classify_fatal(e.message, record: record)
239
236
  rescue Net::SMTPServerBusy => e
240
- record_error(e, retryable: true)
237
+ record_error(e, retryable: true) if record
241
238
  return :assumed
242
239
  rescue Net::SMTPSyntaxError, Net::SMTPAuthenticationError => e
243
- record_error(e)
240
+ record_error(e) if record
244
241
  return :assumed
245
242
  end
246
243
  end
247
244
  end
248
245
  rescue Timeout::Error => e
249
- record_transient(e.message)
246
+ record_transient(e.message) if record
250
247
  :connection_failed
251
248
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
252
- record_transient(e.message)
249
+ record_transient(e.message) if record
253
250
  :connection_failed
254
251
  rescue Net::SMTPAuthenticationError => e
255
- record_error(e)
252
+ record_error(e) if record
256
253
  :assumed
257
254
  rescue Net::SMTPServerBusy => e
258
- record_error(e, retryable: true)
255
+ record_error(e, retryable: true) if record
259
256
  :assumed
260
257
  rescue StandardError => e
261
258
  log "SMTP probe failed for #{recipient} on #{mail_server}:#{port}: #{e.message}"
262
259
  :connection_failed
263
260
  end
264
261
 
265
- def classify_fatal(message)
262
+ def classify_fatal(message, record: true)
266
263
  code = extract_code(message)
267
264
  case code&.[](0)
268
265
  when "5"
269
266
  :invalid
270
267
  when "4"
271
- @smtp_retryable = true
268
+ @smtp_retryable = true if record
272
269
  :assumed
273
270
  else
274
- if message.to_s.downcase.include?("temporary")
271
+ if record && message.to_s.downcase.include?("temporary")
275
272
  @smtp_retryable = true
276
273
  end
277
274
  :assumed
@@ -303,7 +300,7 @@ module Deliverable
303
300
 
304
301
  fake = "definitely-does-not-exist-#{rand(10**10)}@#{domain}"
305
302
  result = SMTP_PORTS.each do |port|
306
- outcome = attempt_rcpt(mail_server, port, fake)
303
+ outcome = attempt_rcpt(mail_server, port, fake, record: false)
307
304
  break :accepted if outcome == :verified
308
305
  break :rejected if outcome == :invalid
309
306
  end
@@ -1,3 +1,3 @@
1
1
  module Deliverable
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deliverable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Strömberg
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-05-11 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: valid_email2
@@ -84,7 +83,6 @@ metadata:
84
83
  homepage_uri: https://github.com/peopledb/deliverable
85
84
  source_code_uri: https://github.com/peopledb/deliverable
86
85
  changelog_uri: https://github.com/peopledb/deliverable/blob/main/CHANGELOG.md
87
- post_install_message:
88
86
  rdoc_options: []
89
87
  require_paths:
90
88
  - lib
@@ -99,8 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
97
  - !ruby/object:Gem::Version
100
98
  version: '0'
101
99
  requirements: []
102
- rubygems_version: 3.5.11
103
- signing_key:
100
+ rubygems_version: 3.7.2
104
101
  specification_version: 4
105
102
  summary: 'Honest email verification: syntax, MX, SMTP RCPT, and catch-all detection.'
106
103
  test_files: []