wakio 0.1.3 → 0.1.5

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: 41b4696d5b5dcea8872174fce7d104adeb163eb775555de498214e2ba1c49711
4
- data.tar.gz: 1b7eaa7f2b2e4540b4f60a4beb979718262b54a35e64c34a52fc931aa1a748d0
3
+ metadata.gz: c56589be9b5b1aad5624c49fef67e6d58f9299f9dbd759152c68da3cb1c65ac0
4
+ data.tar.gz: 398e7340b34f7911a7a3fe071c517d6dbfeb83774869439874f57e47b97a9205
5
5
  SHA512:
6
- metadata.gz: ec7af6244e5c01a97da9b8455b23475dbf4d26a86df036e0cc97ec341020b19dc7b9b851307185f5d4d2a8052a3e53cb4db37a28f350c39acd23ea6762baae07
7
- data.tar.gz: 99b951382c14c5ee5732411f3ce2f4fc75c3128c9283d495d48763881fae5d1593630886970c55a82f89148a519a881f2e7ddc41b8968d2e252726381ffaf97b
6
+ metadata.gz: 95cef2ba3cc45f89e79c7213b127dae7bde0e1e4b6b77560bbd73df861e81787cb9d53650a098e5ead2a83bb79208331058ae652f5637d92b7b7e4454ee2eff9
7
+ data.tar.gz: a2c935c3a981028a09985e90a0ac50a53a540dae1403e699fc7664b6039e9c2fae7a1ae02bc8e44d597b76ed77fec2cb03a58f06b53fc6a475a1c2c53401922c
data/README.md CHANGED
@@ -18,18 +18,18 @@ config.action_mailer.wakio_settings = {
18
18
 
19
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.
20
20
 
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.
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. Recipients keep their display names (`to`, `cc`, `bcc`); `reply_to` is sent as bare addresses.
22
22
 
23
- The `from` domain must be one of your account's sendable sending domains, matched exactly: `hello@acme.com` needs `acme.com` itself verified, and a verified `mail.acme.com` does not cover it. A mismatch is refused with `422 no_verified_sending_domain`. A mailer with no `from` goes out as `no-reply@` your first sendable domain. `GET /v1/sending-identities` reports which domains are currently sendable.
23
+ The `from` domain must be one of your account's sendable sending domains, matched exactly: `hello@acme.com` needs `acme.com` itself verified, and a verified `mail.acme.com` does not cover it. A mismatch is refused with `422 no_verified_sending_domain`. A mailer with no `from` goes out as `no-reply@` your first sendable domain, as long as your account has one brand. Once it has more than one, every mailer needs a `from`, and one without it raises `Wakio::Misconfigured` with `422 from_required`. `GET /v1/sending-identities` reports which domains are currently sendable.
24
24
 
25
25
  ## Limitations worth knowing before you switch a mailer over
26
26
 
27
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.
28
28
 
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`.
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`. `code` is nil when the response is not JSON or names no `error`, so fall back to `status` when you log it.
30
30
 
31
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.
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 from_required`, `422 unknown_template`, a redirect, an `http` host, and any 4xx this gem does not know. Retry it.
33
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
34
 
35
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:
@@ -43,6 +43,8 @@ end
43
43
  config.action_mailer.delivery_job = "WakioDeliveryJob"
44
44
  ```
45
45
 
46
+ On Sidekiq, skip that job. Sidekiq already retries every failed job, about 25 times over three weeks, so the risk runs the other way: a message that can never send is retried for weeks. What you need there is the `rescue_from` below, which stops `Suppressed` and `Rejected` from reaching Sidekiq at all.
47
+
46
48
  The mailer's `rescue_from` below catches `Suppressed` and `Rejected` before the job sees them.
47
49
 
48
50
  ```ruby
@@ -66,10 +68,9 @@ ever approaches it. It reads "per request" and not "per message" for that reason
66
68
  the limit bounds what one `deliver!` call may name, not what any single message
67
69
  contains.
68
70
 
69
- **This gem does not send the mailer's `attachments`.** No files reach the recipient. Call the HTTP API directly for a send that needs them.
71
+ **Attachments are sent; inline attachments are refused.** Every file in the mailer's `attachments` reaches each recipient. Wakio cannot reference a part by `cid:`, so a mailer using `attachments.inline` raises `Wakio::Rejected` before anything is sent, rather than delivering a broken image.
70
72
 
71
- **Ten megabytes of attachments per request** — a limit of the HTTP API you would call
72
- directly for the send above, since this gem posts no attachments of its own. Attachment
73
+ **Ten megabytes of attachments per request**, checked by the API, which refuses a request over any limit below with `Wakio::Rejected`. Attachment
73
74
  content is read once from the request, not once per recipient — but Wakio still writes an
74
75
  independent copy of it to every recipient's own delivery record, so the same bytes are
75
76
  materialised once per recipient server-side. A second ceiling catches that: attachment
@@ -73,17 +73,42 @@ module Wakio
73
73
  def payload_for(mail)
74
74
  html, text = bodies_for(mail)
75
75
  {
76
- to: Array(mail.to),
77
- cc: Array(mail.cc),
78
- bcc: Array(mail.bcc),
76
+ to: named(mail, :to),
77
+ cc: named(mail, :cc),
78
+ bcc: named(mail, :bcc),
79
79
  reply_to: Array(mail.reply_to),
80
80
  from: mail[:from]&.value,
81
81
  subject: mail.subject.to_s.gsub(/[[:space:]]+/, " ").strip,
82
82
  html: html,
83
- text: text
83
+ text: text,
84
+ attachments: attachments_for(mail)
84
85
  }.compact
85
86
  end
86
87
 
88
+ # Wakio has no content_id, so an inline part would arrive as a separate file and its cid: image
89
+ # would break. Refused here, before the request, rather than delivered broken.
90
+ def attachments_for(mail)
91
+ return if mail.attachments.empty?
92
+
93
+ inline = mail.attachments.select(&:inline?)
94
+ raise Rejected, "Wakio does not send inline attachments: #{inline.map(&:filename).join(', ')}" if inline.any?
95
+
96
+ mail.attachments.map do |file|
97
+ { filename: file.filename, content_type: file.mime_type, content: [ file.decoded ].pack("m0") }
98
+ end
99
+ end
100
+
101
+ # `formatted` keeps each recipient's display name, which Wakio shows in the To line and ignores
102
+ # for matching. reply_to stays bare above: Wakio takes no name there.
103
+ # A header Mail cannot parse is an UnstructuredField with no #formatted; sent as written, Wakio
104
+ # refuses it and the host sees Wakio::Rejected rather than a NoMethodError.
105
+ def named(mail, field)
106
+ header = mail[field]
107
+ return [] if header.nil?
108
+
109
+ header.respond_to?(:formatted) ? Array(header.formatted) : [ header.value.to_s ]
110
+ end
111
+
87
112
  # Parts, not `mail.body.decoded`: on a multipart message that is `""`, and multipart is
88
113
  # what every Rails mailer with both an .html.erb and a .text.erb view produces.
89
114
  def bodies_for(mail)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wakio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - WorkersLab LLC