anypost 1.1.0 → 1.3.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/README.md +8 -1
- data/lib/anypost/resources/email.rb +28 -7
- data/lib/anypost/resources/suppressions.rb +15 -1
- data/lib/anypost/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 143a52ee24a58206c7af144a0ca378aa1741e8a77faa2524ba4552aa565824af
|
|
4
|
+
data.tar.gz: 3756ec2603f282ff45c0004cccf53496829f3cba612c36ad05de01a0ff706123
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 595ab92c756ca037038ce60ca5b89eba8cbea436776c459b20853a2ea6f5a75940c559aeb80b7704ba0ba437ed78473bb86af5e42c67549b1735351ccef759ff
|
|
7
|
+
data.tar.gz: 18a5f08424ac853a62e4dfd0c77039a75521d0b968b992bc27e3dd81397f212bf3c7ddcea9ab9357bf690971ca1d330b2b9358ac29c27174cce438a1e25424ad
|
data/README.md
CHANGED
|
@@ -62,7 +62,7 @@ client.email.send(
|
|
|
62
62
|
)
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
Attachment `content` is the raw file bytes: pass what `File.binread` returns and the SDK base64-encodes it.
|
|
65
|
+
Attachment `content` is the raw file bytes: pass what `File.binread` returns and the SDK base64-encodes it. When the content is already base64 at rest, pass it as `content_base64` instead — that string is sent verbatim, so nothing is decoded just to be re-encoded. Set exactly one of the two. The request body is capped at 5 MB.
|
|
66
66
|
|
|
67
67
|
```ruby
|
|
68
68
|
client.email.send(
|
|
@@ -174,8 +174,15 @@ A suppression blocks sends to an address, scoped to a `topic`. The wildcard `*`
|
|
|
174
174
|
client.suppressions.create(email: "alice@example.com", topic: "marketing", note: "Customer requested removal")
|
|
175
175
|
|
|
176
176
|
client.suppressions.delete("alice@example.com", "marketing")
|
|
177
|
+
|
|
178
|
+
client.suppressions.create_batch([
|
|
179
|
+
{email: "bob@example.com"},
|
|
180
|
+
{email: "carol@example.com", topic: "marketing", reason: "unsubscribed"}
|
|
181
|
+
])
|
|
177
182
|
```
|
|
178
183
|
|
|
184
|
+
`create_batch` takes up to 1,000 items per call and returns `imported`, `already_suppressed`, and `invalid`. Existing entries are left unchanged, so retrying a batch is safe, and invalid addresses are reported in `invalid` instead of failing the call. A batch that would pass your team's suppression limit raises a validation error and adds nothing. Suppressions do not expire.
|
|
185
|
+
|
|
179
186
|
`get`, `list` (with `email_contains`, `topic`, `reason`, and `origin` filters), `list_for_email`, and `delete_for_email` round out the resource. See [Suppressions](https://anypost.com/docs/reference/suppressions) for scoping and the automatic-suppression rules for bounces and complaints.
|
|
180
187
|
|
|
181
188
|
## Webhooks
|
|
@@ -4,8 +4,12 @@ module Anypost
|
|
|
4
4
|
module Resources
|
|
5
5
|
# Operations on the `/email` endpoints.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
7
|
+
# Give each attachment its content exactly one of two ways: `content` for raw
|
|
8
|
+
# file bytes (e.g. from `File.binread`), which the SDK base64-encodes for
|
|
9
|
+
# transport, or `content_base64` for content that is already base64 at rest,
|
|
10
|
+
# which is sent through verbatim so nothing is decoded just to be re-encoded.
|
|
11
|
+
# Ruby has no type-level distinction between the two — both are Strings — so
|
|
12
|
+
# the key you choose is the signal.
|
|
9
13
|
class Email < Base
|
|
10
14
|
# Send a single message.
|
|
11
15
|
#
|
|
@@ -35,13 +39,30 @@ module Anypost
|
|
|
35
39
|
return message unless attachments.is_a?(Array)
|
|
36
40
|
|
|
37
41
|
message = message.dup
|
|
38
|
-
message[:attachments] = attachments.map
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
message[:attachments] = attachments.map { |attachment| encode_attachment(attachment) }
|
|
43
|
+
message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Collapse an attachment's two possible content keys onto the single
|
|
47
|
+
# base64 `content` field the API takes.
|
|
48
|
+
def encode_attachment(attachment)
|
|
49
|
+
return attachment unless attachment.is_a?(Hash)
|
|
50
|
+
|
|
51
|
+
raw = attachment[:content]
|
|
52
|
+
encoded = attachment[:content_base64]
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
if raw && encoded
|
|
55
|
+
raise ArgumentError,
|
|
56
|
+
"attachment #{attachment[:filename].inspect} sets both :content and " \
|
|
57
|
+
":content_base64; set exactly one"
|
|
43
58
|
end
|
|
44
|
-
|
|
59
|
+
|
|
60
|
+
return attachment.except(:content_base64).merge(content: encoded) if encoded
|
|
61
|
+
return attachment.merge(content: [raw].pack("m0")) if raw.is_a?(String)
|
|
62
|
+
|
|
63
|
+
raise ArgumentError,
|
|
64
|
+
"attachment #{attachment[:filename].inspect} has no content; set :content " \
|
|
65
|
+
"(raw bytes) or :content_base64"
|
|
45
66
|
end
|
|
46
67
|
end
|
|
47
68
|
end
|
|
@@ -4,7 +4,7 @@ module Anypost
|
|
|
4
4
|
module Resources
|
|
5
5
|
# Operations on the `/suppressions` endpoints. Entries key on `(email, topic)`.
|
|
6
6
|
class Suppressions < Base
|
|
7
|
-
# List the team's suppressions, newest-first.
|
|
7
|
+
# List the team's suppressions, newest-first.
|
|
8
8
|
# Filter with `email_contains`, `topic`, `reason`, and `origin`.
|
|
9
9
|
def list(params = {})
|
|
10
10
|
paginate("/suppressions", {
|
|
@@ -23,6 +23,20 @@ module Anypost
|
|
|
23
23
|
request_object(:post, "/suppressions", body: params)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# Add up to 1,000 suppressions in one call. Pass the list of items, each a
|
|
27
|
+
# hash with `email` and optionally `topic` (default `*`), `reason` (a free-form
|
|
28
|
+
# string; common aliases like `bounce` or `opt-out` are mapped, anything else
|
|
29
|
+
# records `manual`), and `note`. Entries that already exist are counted in
|
|
30
|
+
# `already_suppressed` and left unchanged, so a batch is safe to retry.
|
|
31
|
+
# Invalid addresses come back in `invalid` (with their `index` and `email`)
|
|
32
|
+
# instead of failing the batch. Raises validation_error, adding nothing, if
|
|
33
|
+
# the batch would pass the team's suppression limit.
|
|
34
|
+
#
|
|
35
|
+
# @return [Response] with `imported`, `already_suppressed`, and `invalid`
|
|
36
|
+
def create_batch(suppressions)
|
|
37
|
+
request_object(:post, "/suppressions/batch", body: {suppressions: suppressions})
|
|
38
|
+
end
|
|
39
|
+
|
|
26
40
|
# Retrieve the suppression for an `(email, topic)` pair. Use `*` as the
|
|
27
41
|
# topic for the global row. Raises not_found if the pair isn't suppressed.
|
|
28
42
|
def get(email, topic)
|
data/lib/anypost/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: anypost
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anypost
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|