wakio 0.1.2 → 0.1.3
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/README.md +20 -5
- data/lib/wakio/delivery_method.rb +8 -2
- 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: 41b4696d5b5dcea8872174fce7d104adeb163eb775555de498214e2ba1c49711
|
|
4
|
+
data.tar.gz: 1b7eaa7f2b2e4540b4f60a4beb979718262b54a35e64c34a52fc931aa1a748d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec7af6244e5c01a97da9b8455b23475dbf4d26a86df036e0cc97ec341020b19dc7b9b851307185f5d4d2a8052a3e53cb4db37a28f350c39acd23ea6762baae07
|
|
7
|
+
data.tar.gz: 99b951382c14c5ee5732411f3ce2f4fc75c3128c9283d495d48763881fae5d1593630886970c55a82f89148a519a881f2e7ddc41b8968d2e252726381ffaf97b
|
data/README.md
CHANGED
|
@@ -14,7 +14,9 @@ config.action_mailer.wakio_settings = {
|
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
`open_timeout` and `read_timeout` are optional, in seconds, and default to 5 and 10. A timeout raises `Net::OpenTimeout` or `Net::ReadTimeout`, not `Wakio::DeliveryError`. A read timeout can come after Wakio accepted the send, so a retry without an idempotency key (below) may send twice.
|
|
17
|
+
`open_timeout` and `read_timeout` are optional, in seconds, and default to 5 and 10. A timeout raises `Net::OpenTimeout` or `Net::ReadTimeout`, and any other network failure raises Ruby's own error, not `Wakio::DeliveryError`. A read timeout can come after Wakio accepted the send, so a retry without an idempotency key (below) may send twice.
|
|
18
|
+
|
|
19
|
+
`host` must be `https`. An `http` host other than `localhost` raises `Wakio::Misconfigured` before anything is sent, so the API key never travels in cleartext.
|
|
18
20
|
|
|
19
21
|
Every existing mailer keeps working unchanged. Its rendered subject, its HTML and text parts, and its `from` go to Wakio as they are, with no server-side template involved. A text-only mailer sends a text-only email.
|
|
20
22
|
|
|
@@ -24,11 +26,24 @@ The `from` domain must be one of your account's sendable sending domains, matche
|
|
|
24
26
|
|
|
25
27
|
**A suppressed address raises.** Wakio suppresses addresses that have hard-bounced or complained, and accepts a send to one rather than refusing it. The response names each recipient's status, and `deliver!` raises `Wakio::Suppressed` (a `Wakio::DeliveryError`) when every recipient was suppressed, so a one-recipient mailer to a suppressed address fails loudly instead of reporting success. Retrying cannot help, so handle it rather than letting a job backend retry it: `rescue_from Wakio::Suppressed` in your mailer also catches it under `deliver_later`. A send where only some recipients were suppressed returns normally; check the returned response's `deliveries` for which ones.
|
|
26
28
|
|
|
27
|
-
**Refusals split by whether a retry can ever send the message.**
|
|
29
|
+
**Refusals split by whether a retry can ever send the message.** A refusal from Wakio is a `Wakio::DeliveryError` carrying `status`, `code` (the response's `error`, such as `"invalid_request"`) and the parsed `body`.
|
|
30
|
+
|
|
31
|
+
- `Wakio::Rejected`: retrying this message cannot help. `400`, `413`, `422 invalid_request` (usually a mailer bug; `detail` names the field) and `422 idempotency_key_reused` (an earlier request with that key already went out). Report it and drop it.
|
|
32
|
+
- `Wakio::Misconfigured`: the account or its configuration is wrong, and the same message sends once that is fixed. `401 invalid_api_key`, `402 not_entitled`, `403 account_suspended`, `404`, `422 no_verified_sending_domain`, `422 unknown_template`, a redirect, an `http` host, and any 4xx this gem does not know. Retry it.
|
|
33
|
+
- A plain `Wakio::DeliveryError`: `409 request_in_flight`, every 5xx, and a success response the gem cannot read. Retry it; after an unreadable success only a keyed send is safe to repeat.
|
|
34
|
+
|
|
35
|
+
Action Mailer's delivery job retries nothing itself, and Solid Queue and GoodJob do not retry a failed job by default, so give it a policy:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
class WakioDeliveryJob < ActionMailer::MailDeliveryJob
|
|
39
|
+
retry_on Wakio::DeliveryError, Net::OpenTimeout, Net::ReadTimeout, wait: :polynomially_longer, attempts: 25
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# config/application.rb
|
|
43
|
+
config.action_mailer.delivery_job = "WakioDeliveryJob"
|
|
44
|
+
```
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
- `Wakio::Misconfigured`: the account or its configuration is wrong, and the same message sends once that is fixed. `401 invalid_api_key`, `402 not_entitled`, `403 account_suspended`, `404`, `422 no_verified_sending_domain`, `422 unknown_template`, and any 4xx this gem does not know. Let it raise so the job retries and your error tracker shows it.
|
|
31
|
-
- A plain `Wakio::DeliveryError`: `409 request_in_flight` and every 5xx. Let it retry.
|
|
46
|
+
The mailer's `rescue_from` below catches `Suppressed` and `Rejected` before the job sees them.
|
|
32
47
|
|
|
33
48
|
```ruby
|
|
34
49
|
class ApplicationMailer < ActionMailer::Base
|
|
@@ -37,6 +37,8 @@ module Wakio
|
|
|
37
37
|
# towards retrying rather than towards dropping mail.
|
|
38
38
|
REJECTED_STATUSES = [ 400, 413 ].freeze
|
|
39
39
|
REJECTED_CODES = %w[invalid_request idempotency_key_reused].freeze
|
|
40
|
+
LOCAL_HOSTS = %w[localhost 127.0.0.1 ::1].freeze
|
|
41
|
+
MESSAGE_BODY_LIMIT = 300
|
|
40
42
|
|
|
41
43
|
def deliver!(mail)
|
|
42
44
|
# Caller-supplied, never derived — and no key at all when the caller gives none.
|
|
@@ -135,11 +137,12 @@ module Wakio
|
|
|
135
137
|
body = parsed(raw)
|
|
136
138
|
code = body["error"] if body.is_a?(Hash)
|
|
137
139
|
kind =
|
|
138
|
-
if
|
|
140
|
+
if status.between?(300, 399) then Misconfigured
|
|
141
|
+
elsif !status.between?(400, 499) || status == 409 then DeliveryError
|
|
139
142
|
elsif REJECTED_STATUSES.include?(status) || REJECTED_CODES.include?(code) then Rejected
|
|
140
143
|
else Misconfigured
|
|
141
144
|
end
|
|
142
|
-
kind.new("Wakio returned #{status}: #{raw}", status: status, body: body)
|
|
145
|
+
kind.new("Wakio returned #{status}: #{raw.to_s[0, MESSAGE_BODY_LIMIT]}", status: status, body: body)
|
|
143
146
|
end
|
|
144
147
|
|
|
145
148
|
def parsed(body)
|
|
@@ -154,6 +157,9 @@ module Wakio
|
|
|
154
157
|
|
|
155
158
|
def post(payload, idempotency_key:)
|
|
156
159
|
uri = URI.join(settings.fetch(:host), "/v1/emails")
|
|
160
|
+
unless uri.scheme == "https" || LOCAL_HOSTS.include?(uri.hostname)
|
|
161
|
+
raise Misconfigured, "Wakio host must be https, or the API key travels in cleartext: #{settings.fetch(:host)}"
|
|
162
|
+
end
|
|
157
163
|
request = Net::HTTP::Post.new(uri)
|
|
158
164
|
request["Authorization"] = "Bearer #{settings.fetch(:api_key)}"
|
|
159
165
|
request["Content-Type"] = "application/json"
|