sendora 2.4.0__tar.gz → 2.5.0__tar.gz

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.
Files changed (40) hide show
  1. {sendora-2.4.0 → sendora-2.5.0}/CHANGELOG.md +6 -0
  2. {sendora-2.4.0 → sendora-2.5.0}/PKG-INFO +12 -4
  3. {sendora-2.4.0 → sendora-2.5.0}/README.md +11 -3
  4. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/__init__.py +2 -0
  5. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_version.py +1 -1
  6. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_webhooks.py +2 -0
  7. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/types.py +21 -2
  8. {sendora-2.4.0 → sendora-2.5.0}/.gitignore +0 -0
  9. {sendora-2.4.0 → sendora-2.5.0}/LICENSE +0 -0
  10. {sendora-2.4.0 → sendora-2.5.0}/pyproject.toml +0 -0
  11. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_account.py +0 -0
  12. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_answers.py +0 -0
  13. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_client.py +0 -0
  14. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_errors.py +0 -0
  15. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_json.py +0 -0
  16. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_keys.py +0 -0
  17. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_model.py +0 -0
  18. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_options.py +0 -0
  19. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_pages.py +0 -0
  20. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_retry.py +0 -0
  21. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_transport.py +0 -0
  22. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/_wire.py +0 -0
  23. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/py.typed +0 -0
  24. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/__init__.py +0 -0
  25. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/broadcasts.py +0 -0
  26. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/domains.py +0 -0
  27. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/email.py +0 -0
  28. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/erasures.py +0 -0
  29. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/inbound.py +0 -0
  30. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/inbound_domains.py +0 -0
  31. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/messages.py +0 -0
  32. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/server.py +0 -0
  33. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/servers.py +0 -0
  34. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/streams.py +0 -0
  35. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/suppressions.py +0 -0
  36. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/tokens.py +0 -0
  37. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/tracking_domains.py +0 -0
  38. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/tracking_opt_outs.py +0 -0
  39. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/resources/webhooks.py +0 -0
  40. {sendora-2.4.0 → sendora-2.5.0}/src/sendora/skills/sendora/SKILL.md +0 -0
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.5.0
4
+
5
+ - A new event, `TrackingOptedOutEvent`, for `tracking_opted_out`: a recipient
6
+ asked not to be tracked, through the link that `{{ tracking_opt_out_url }}`
7
+ puts in your mail. `webhooks.create` without `events` takes it.
8
+
3
9
  ## 2.4.0
4
10
 
5
11
  - `sendora.tracking_opt_outs` manages a server's not-tracked list: `list`,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sendora
3
- Version: 2.4.0
3
+ Version: 2.5.0
4
4
  Summary: The Python client for Sendora's email API.
5
5
  Project-URL: Homepage, https://sendora.se/docs
6
6
  License-Expression: MIT
@@ -262,8 +262,14 @@ until it is.
262
262
 
263
263
  An entry's `source` is `manual`, or `recipient` if the recipient asked for it.
264
264
  Remove a recipient's own entry only after new consent. An entry's `address` is
265
- `None` once an erasure has left only a keyed hash of it. `delete` still finds
266
- that entry by its address, and nothing removes it without the address.
265
+ `None` when only a keyed hash of it is left, after an erasure or when the
266
+ recipient asked from mail that had left the log. `delete` still finds that entry
267
+ by its address, and nothing removes it without the address.
268
+
269
+ To let a recipient ask, write `{{ tracking_opt_out_url }}` in the text or the
270
+ HTML of a message on any stream. Each recipient then gets a copy with their own
271
+ link to a page in Swedish and English. Its button lists the address with the
272
+ `source` `recipient`, and sends the `tracking_opted_out` event.
267
273
 
268
274
  ```python
269
275
  sendora.tracking_opt_outs.add(address="anna@example.com")
@@ -335,7 +341,9 @@ Events: `delivered`, `bounced`, `deferred`, `spam_complaint` and
335
341
  `details` from the receiver, or for `unsubscribed` the `source` (`link` or
336
342
  `one_click`); `opened` and `clicked` about a tracked copy, sent only to a
337
343
  webhook that names them, with the same fields and `details` that say whether
338
- a machine did it and, for `clicked`, give the `link`; `cap_warning` and `cap_reached` about usage, with `scope`,
344
+ a machine did it and, for `clicked`, give the `link`; `tracking_opted_out`
345
+ about a recipient who asked not to be tracked, with the same fields and no
346
+ `details`; `cap_warning` and `cap_reached` about usage, with `scope`,
339
347
  `cap`, `used` and the period; `inbound` about a message received on an
340
348
  inbound stream, with `inbound_message_id`, `envelope_recipient`, the
341
349
  sizes, the `authentication` verdicts and, for a webhook with
@@ -240,8 +240,14 @@ until it is.
240
240
 
241
241
  An entry's `source` is `manual`, or `recipient` if the recipient asked for it.
242
242
  Remove a recipient's own entry only after new consent. An entry's `address` is
243
- `None` once an erasure has left only a keyed hash of it. `delete` still finds
244
- that entry by its address, and nothing removes it without the address.
243
+ `None` when only a keyed hash of it is left, after an erasure or when the
244
+ recipient asked from mail that had left the log. `delete` still finds that entry
245
+ by its address, and nothing removes it without the address.
246
+
247
+ To let a recipient ask, write `{{ tracking_opt_out_url }}` in the text or the
248
+ HTML of a message on any stream. Each recipient then gets a copy with their own
249
+ link to a page in Swedish and English. Its button lists the address with the
250
+ `source` `recipient`, and sends the `tracking_opted_out` event.
245
251
 
246
252
  ```python
247
253
  sendora.tracking_opt_outs.add(address="anna@example.com")
@@ -313,7 +319,9 @@ Events: `delivered`, `bounced`, `deferred`, `spam_complaint` and
313
319
  `details` from the receiver, or for `unsubscribed` the `source` (`link` or
314
320
  `one_click`); `opened` and `clicked` about a tracked copy, sent only to a
315
321
  webhook that names them, with the same fields and `details` that say whether
316
- a machine did it and, for `clicked`, give the `link`; `cap_warning` and `cap_reached` about usage, with `scope`,
322
+ a machine did it and, for `clicked`, give the `link`; `tracking_opted_out`
323
+ about a recipient who asked not to be tracked, with the same fields and no
324
+ `details`; `cap_warning` and `cap_reached` about usage, with `scope`,
317
325
  `cap`, `used` and the period; `inbound` about a message received on an
318
326
  inbound stream, with `inbound_message_id`, `envelope_recipient`, the
319
327
  sizes, the `authentication` verdicts and, for a webhook with
@@ -42,6 +42,7 @@ from .types import (
42
42
  OpenedEvent,
43
43
  SendoraErrorCode,
44
44
  SpamComplaintEvent,
45
+ TrackingOptedOutEvent,
45
46
  UnknownEvent,
46
47
  UnsubscribedEvent,
47
48
  WebhookEvent,
@@ -79,6 +80,7 @@ __all__ = [
79
80
  "SendoraError",
80
81
  "SendoraErrorCode",
81
82
  "SpamComplaintEvent",
83
+ "TrackingOptedOutEvent",
82
84
  "UnknownEvent",
83
85
  "UnprocessableEntityError",
84
86
  "UnsubscribedEvent",
@@ -1,3 +1,3 @@
1
1
  """The package's version: the build reads it, and every request names it."""
2
2
 
3
- __version__ = "2.4.0"
3
+ __version__ = "2.5.0"
@@ -24,6 +24,7 @@ from .types import (
24
24
  InboundEventContent,
25
25
  OpenedEvent,
26
26
  SpamComplaintEvent,
27
+ TrackingOptedOutEvent,
27
28
  UnknownEvent,
28
29
  UnsubscribedEvent,
29
30
  WebhookEvent,
@@ -173,6 +174,7 @@ _EVENTS: dict[str, Callable[[dict[str, object]], WebhookEvent]] = {
173
174
  "unsubscribed": lambda payload: decode(UnsubscribedEvent, payload),
174
175
  "opened": lambda payload: decode(OpenedEvent, payload),
175
176
  "clicked": lambda payload: decode(ClickedEvent, payload),
177
+ "tracking_opted_out": lambda payload: decode(TrackingOptedOutEvent, payload),
176
178
  "cap_warning": lambda payload: decode(CapWarningEvent, payload),
177
179
  "cap_reached": lambda payload: decode(CapReachedEvent, payload),
178
180
  "inbound": _inbound,
@@ -146,6 +146,7 @@ __all__ = [
146
146
  "TrackingOptOut",
147
147
  "TrackingOptOutPage",
148
148
  "TrackingOptOutSource",
149
+ "TrackingOptedOutEvent",
149
150
  "TrackingReason",
150
151
  "TrackingSkipped",
151
152
  "TxtRecord",
@@ -1057,8 +1058,9 @@ class TrackingOptOut(Answer):
1057
1058
  """An address that the server never tracks.
1058
1059
 
1059
1060
  Attributes:
1060
- address: The address, lower-cased. ``None`` once an erasure has left
1061
- only a keyed hash.
1061
+ address: The address, lower-cased. ``None`` when only a keyed hash is
1062
+ left: after an erasure, or when the recipient asked from mail that
1063
+ had left the log.
1062
1064
  source: ``manual`` if added through the API or the dashboard,
1063
1065
  ``recipient`` if the recipient asked for it. Remove a recipient's
1064
1066
  own entry only after new consent.
@@ -1236,6 +1238,7 @@ WebhookEventName = Literal[
1236
1238
  "unsubscribed",
1237
1239
  "opened",
1238
1240
  "clicked",
1241
+ "tracking_opted_out",
1239
1242
  "cap_warning",
1240
1243
  "cap_reached",
1241
1244
  "inbound",
@@ -2210,6 +2213,21 @@ class ClickedEvent(MessageEventFields):
2210
2213
  details: ClickedDetails
2211
2214
 
2212
2215
 
2216
+ @model
2217
+ class TrackingOptedOutEvent(MessageEventFields):
2218
+ """The recipient asked not to be tracked.
2219
+
2220
+ They used the page that ``{{ tracking_opt_out_url }}`` links to, so the
2221
+ address is on the server's not-tracked list. A webhook that leaves out
2222
+ ``events`` gets this event.
2223
+
2224
+ Attributes:
2225
+ event: ``tracking_opted_out``.
2226
+ """
2227
+
2228
+ event: Literal["tracking_opted_out"]
2229
+
2230
+
2213
2231
  @model
2214
2232
  class CapEventFields(Answer):
2215
2233
  """What both usage events carry.
@@ -2445,6 +2463,7 @@ WebhookEvent = (
2445
2463
  | UnsubscribedEvent
2446
2464
  | OpenedEvent
2447
2465
  | ClickedEvent
2466
+ | TrackingOptedOutEvent
2448
2467
  | CapWarningEvent
2449
2468
  | CapReachedEvent
2450
2469
  | InboundEvent
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes