@sendora/sdk 1.1.0 → 1.2.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.
- package/README.md +67 -46
- package/dist/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -0
- package/dist/client.js.map +1 -1
- package/dist/error.d.ts +2 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +9 -2
- package/dist/error.js.map +1 -1
- package/dist/inbound-domains.d.ts +36 -0
- package/dist/inbound-domains.d.ts.map +1 -0
- package/dist/inbound-domains.js +72 -0
- package/dist/inbound-domains.js.map +1 -0
- package/dist/inbound.d.ts +61 -0
- package/dist/inbound.d.ts.map +1 -0
- package/dist/inbound.js +106 -0
- package/dist/inbound.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/transport.d.ts +2 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +15 -5
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +142 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -8
- package/skills/sendora/SKILL.md +1 -1
- package/src/client.ts +6 -0
- package/src/error.ts +13 -2
- package/src/inbound-domains.ts +89 -0
- package/src/inbound.ts +135 -0
- package/src/index.ts +2 -0
- package/src/transport.ts +26 -5
- package/src/types.ts +147 -2
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# @sendora/sdk
|
|
2
2
|
|
|
3
3
|
The official TypeScript SDK for [Sendora](https://sendora.se), transactional
|
|
4
|
-
email delivery
|
|
5
|
-
newer and on any runtime with `fetch` and WebCrypto: Bun, Deno, Cloudflare
|
|
4
|
+
email delivery. Zero dependencies. Runs on Node 20.19 or newer and on any runtime with `fetch` and WebCrypto: Bun, Deno, Cloudflare
|
|
6
5
|
Workers. ESM only; CommonJS projects on Node 20.19 or 22.12 and newer load it
|
|
7
6
|
with `require`.
|
|
8
7
|
|
|
@@ -69,11 +68,31 @@ for (const result of results) {
|
|
|
69
68
|
|
|
70
69
|
## Messages
|
|
71
70
|
|
|
72
|
-
| Call
|
|
73
|
-
|
|
|
74
|
-
| `sendora.messages.get(messageId)`
|
|
75
|
-
| `sendora.messages.search(filters?)`
|
|
76
|
-
| `sendora.messages.searchAll(filters?)`
|
|
71
|
+
| Call | Answers |
|
|
72
|
+
| ------------------------------------------------------------ | --------------------------------------------------------------------------------- |
|
|
73
|
+
| `sendora.messages.get(messageId)` | The message with its recipients, its attachments described and its timeline |
|
|
74
|
+
| `sendora.messages.search(filters?)` | `{ messages, next }`, one page newest first |
|
|
75
|
+
| `sendora.messages.searchAll(filters?)` | Every match, page by page, for `for await` |
|
|
76
|
+
| `sendora.inbound.get(inboundMessageId)` | A received message: envelope, parties, headers, text, HTML, attachments described |
|
|
77
|
+
| `sendora.inbound.search(filters?)` | `{ messages, next }` of received mail, newest first |
|
|
78
|
+
| `sendora.inbound.searchAll(filters?)` | Every received match, page by page, for `for await` |
|
|
79
|
+
| `sendora.inbound.raw(inboundMessageId)` | The raw message as bytes, `message/rfc822` |
|
|
80
|
+
| `sendora.inbound.attachment(inboundMessageId, attachmentId)` | An attachment's bytes |
|
|
81
|
+
|
|
82
|
+
A stream can also receive on a domain of yours: every address on it,
|
|
83
|
+
whatever the local part, lands on the stream. Claim it with the stream
|
|
84
|
+
id, add the two records the answer gives, an MX that names Sendora and a
|
|
85
|
+
TXT record that proves the claim, and mail is accepted once both are
|
|
86
|
+
seen. A stream holds one domain, and the first account to verify a name
|
|
87
|
+
holds it.
|
|
88
|
+
|
|
89
|
+
| Call | Answers |
|
|
90
|
+
| ----------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
91
|
+
| `sendora.inboundDomains.create({ streamId, domain })` | The domain with `mx` and `txt` to add |
|
|
92
|
+
| `sendora.inboundDomains.list()` | `{ domains }` of the server |
|
|
93
|
+
| `sendora.inboundDomains.get(inboundDomainId)` | One domain with the state of its records |
|
|
94
|
+
| `sendora.inboundDomains.verify(inboundDomainId)` | The domain plus `check` per record: `ok`, `missing`, `mismatch`, `dns_error` |
|
|
95
|
+
| `sendora.inboundDomains.delete(inboundDomainId)` | Nothing; mail to it is refused from then on |
|
|
77
96
|
|
|
78
97
|
Filters: `recipient`, `streamId`, `tag`, `status` (`queued`, `delivered`,
|
|
79
98
|
`deferred`, `bounced`, `expired`), `from` and `to` as `Date` or ISO 8601,
|
|
@@ -298,45 +317,47 @@ try {
|
|
|
298
317
|
}
|
|
299
318
|
```
|
|
300
319
|
|
|
301
|
-
| Code | Status | Meaning
|
|
302
|
-
| --------------------------------- | ------ |
|
|
303
|
-
| `invalid_request` | 400 | A field is wrong; `issues` says which.
|
|
304
|
-
| `idempotency_key_required` | 400 | A batch was sent without a key.
|
|
305
|
-
| `unauthorized` | 401 | The token is missing, malformed or revoked.
|
|
306
|
-
| `payment_required` | 402 | The account has no active subscription.
|
|
307
|
-
| `tenant_paused` | 403 | Sendora has paused the account.
|
|
308
|
-
| `tenant_not_active` | 403 | The account is not approved to send, or not active for an inbound stream.
|
|
309
|
-
| `spam_complaint_locked` | 403 | Only support can lift a spam-complaint suppression.
|
|
310
|
-
| `unsubscribe_locked` | 403 | Only support can lift a recipient's own unsubscribe.
|
|
311
|
-
| `not_found` | 404 | No such id on this server, or no such suppressed address.
|
|
312
|
-
| `domain_exists` | 409 | The account already has the domain; `existingId` names it.
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
321
|
-
| `
|
|
322
|
-
| `
|
|
323
|
-
| `
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
326
|
-
| `
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
320
|
+
| Code | Status | Meaning |
|
|
321
|
+
| --------------------------------- | ------ | ---------------------------------------------------------------------------------------------------- |
|
|
322
|
+
| `invalid_request` | 400 | A field is wrong; `issues` says which. |
|
|
323
|
+
| `idempotency_key_required` | 400 | A batch was sent without a key. |
|
|
324
|
+
| `unauthorized` | 401 | The token is missing, malformed or revoked. |
|
|
325
|
+
| `payment_required` | 402 | The account has no active subscription. |
|
|
326
|
+
| `tenant_paused` | 403 | Sendora has paused the account. |
|
|
327
|
+
| `tenant_not_active` | 403 | The account is not approved to send, or not active for an inbound stream. |
|
|
328
|
+
| `spam_complaint_locked` | 403 | Only support can lift a spam-complaint suppression. |
|
|
329
|
+
| `unsubscribe_locked` | 403 | Only support can lift a recipient's own unsubscribe. |
|
|
330
|
+
| `not_found` | 404 | No such id on this server, or no such suppressed address. |
|
|
331
|
+
| `domain_exists` | 409 | The account already has the domain; `existingId` names it. |
|
|
332
|
+
| `domain_reserved` | 400 | The name is Sendora's own; no account can receive on it. |
|
|
333
|
+
| `inbound_domain_exists` | 409 | The stream already has a domain (`existingId` names it), or another account holds the name verified. |
|
|
334
|
+
| `webhook_exists` | 409 | The server already has a webhook for that URL; `existingId` names it. |
|
|
335
|
+
| `stream_exists` | 409 | The server already has a stream with that name; `existingId` names it. |
|
|
336
|
+
| `inbound_stream_exists` | 409 | The server already has a live inbound stream; `existingId` names it. |
|
|
337
|
+
| `default_stream` | 409 | The default stream cannot be archived. |
|
|
338
|
+
| `last_token` | 409 | The only live token cannot be revoked. |
|
|
339
|
+
| `request_too_large` | 413 | The body exceeds 10 MB. |
|
|
340
|
+
| `from_domain_not_verified` | 422 | The From domain is not a verified sending domain. |
|
|
341
|
+
| `stream_not_found` | 422 | `streamId` names no stream of this server. |
|
|
342
|
+
| `stream_archived` | 422 | The stream is archived and takes no new messages. |
|
|
343
|
+
| `stream_paused` | 422 | Sendora paused the stream after complaints; support resumes it. |
|
|
344
|
+
| `stream_not_sendable` | 422 | An inbound stream receives mail; it takes no messages and has no list. |
|
|
345
|
+
| `stream_not_broadcast` | 422 | A broadcast goes on a broadcast stream; this one is transactional. |
|
|
346
|
+
| `substitution_missing` | 422 | The content names a `{{ key }}` a message does not give. |
|
|
347
|
+
| `broadcast_not_open` | 409 | The broadcast is completed or cancelled; nothing is left to cancel. |
|
|
348
|
+
| `broadcast_not_enabled` | 422 | Broadcast is not enabled for the account: no broadcast stream, no send. |
|
|
349
|
+
| `unsubscribe_placeholder_missing` | 422 | A broadcast message lacks `{{ unsubscribe_url }}` in a part. |
|
|
350
|
+
| `list_unsubscribe_reserved` | 422 | Sendora writes List-Unsubscribe on broadcast streams; leave it out. |
|
|
351
|
+
| `recipient_suppressed` | 422 | Recipients on the suppression list; `suppressed` lists them. |
|
|
352
|
+
| `idempotency_key_mismatch` | 422 | The key was used before with a different body. |
|
|
353
|
+
| `rate_limited` | 429 | Per-minute limit; `retryAfter`, `scope`, `limit`. |
|
|
354
|
+
| `monthly_cap_reached` | 429 | The monthly cap is used up; `scope`, `cap`, `used`, `resetsAt`. |
|
|
355
|
+
| `sending_disabled` | 503 | Sending is paused for everyone; `retryAfter`. |
|
|
356
|
+
| `connection_failed` | none | The request never reached the API; `cause` holds the failure. |
|
|
357
|
+
| `timeout` | none | No answer within `timeoutMs`. |
|
|
358
|
+
| `unexpected_response` | any | An answer without a JSON error body, such as from a proxy. |
|
|
359
|
+
| `invalid_signature` | none | A webhook's signature is missing, malformed or wrong. |
|
|
360
|
+
| `stale_signature` | none | A webhook's signature is older than the tolerance. |
|
|
340
361
|
|
|
341
362
|
`error.retryable` is true when waiting and calling again could succeed.
|
|
342
363
|
Neither the token nor a request body is ever part of an error.
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DomainsResource } from './domains.ts';
|
|
2
2
|
import { BroadcastsResource } from './broadcasts.ts';
|
|
3
3
|
import { EmailResource } from './email.ts';
|
|
4
|
+
import { InboundResource } from './inbound.ts';
|
|
5
|
+
import { InboundDomainsResource } from './inbound-domains.ts';
|
|
4
6
|
import { MessagesResource } from './messages.ts';
|
|
5
7
|
import { StreamsResource } from './streams.ts';
|
|
6
8
|
import { SuppressionsResource } from './suppressions.ts';
|
|
@@ -41,6 +43,8 @@ export declare class Sendora {
|
|
|
41
43
|
readonly email: EmailResource;
|
|
42
44
|
readonly broadcasts: BroadcastsResource;
|
|
43
45
|
readonly messages: MessagesResource;
|
|
46
|
+
readonly inbound: InboundResource;
|
|
47
|
+
readonly inboundDomains: InboundDomainsResource;
|
|
44
48
|
readonly streams: StreamsResource;
|
|
45
49
|
readonly suppressions: SuppressionsResource;
|
|
46
50
|
readonly tokens: TokensResource;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AAGzD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;IACjC,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,0GAA0G;IAC1G,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAO;IAClB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;gBAEtB,OAAO,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AAGzD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;IACjC,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,0GAA0G;IAC1G,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAO;IAClB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,sBAAsB,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;gBAEtB,OAAO,EAAE,cAAc;CAiCpC"}
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DomainsResource } from "./domains.js";
|
|
2
2
|
import { BroadcastsResource } from "./broadcasts.js";
|
|
3
3
|
import { EmailResource } from "./email.js";
|
|
4
|
+
import { InboundResource } from "./inbound.js";
|
|
5
|
+
import { InboundDomainsResource } from "./inbound-domains.js";
|
|
4
6
|
import { MessagesResource } from "./messages.js";
|
|
5
7
|
import { DEFAULT_MAX_RETRIES } from "./retry.js";
|
|
6
8
|
import { StreamsResource } from "./streams.js";
|
|
@@ -29,6 +31,8 @@ export class Sendora {
|
|
|
29
31
|
email;
|
|
30
32
|
broadcasts;
|
|
31
33
|
messages;
|
|
34
|
+
inbound;
|
|
35
|
+
inboundDomains;
|
|
32
36
|
streams;
|
|
33
37
|
suppressions;
|
|
34
38
|
tokens;
|
|
@@ -59,6 +63,8 @@ export class Sendora {
|
|
|
59
63
|
this.email = new EmailResource(transport);
|
|
60
64
|
this.broadcasts = new BroadcastsResource(transport);
|
|
61
65
|
this.messages = new MessagesResource(transport);
|
|
66
|
+
this.inbound = new InboundResource(transport);
|
|
67
|
+
this.inboundDomains = new InboundDomainsResource(transport);
|
|
62
68
|
this.streams = new StreamsResource(transport);
|
|
63
69
|
this.suppressions = new SuppressionsResource(transport);
|
|
64
70
|
this.tokens = new TokensResource(transport);
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AACzD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAmBlC;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,OAAO;IACT,KAAK,CAAgB;IACrB,UAAU,CAAqB;IAC/B,QAAQ,CAAmB;IAC3B,OAAO,CAAkB;IACzB,YAAY,CAAuB;IACnC,MAAM,CAAiB;IACvB,QAAQ,CAAmB;IAC3B,OAAO,CAAkB;IAElC,YAAY,OAAuB;QACjC,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,MAAM,IAAI,SAAS,CAAC,gEAAgE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;QACpD,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QACjB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;QAC1D,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,sDAAsD,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;YAC9B,OAAO;YACP,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;YAC7B,SAAS;YACT,UAAU;YACV,SAAS,EAAE,eAAe,WAAW,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,IAAI,cAAc,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/error.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LimitScope, SuppressedRecipient, ValidationIssue } from './types.ts';
|
|
2
2
|
/** Every code the API answers, the three the SDK raises when it never got a proper answer, and the two of the webhook verifier. */
|
|
3
|
-
export type SendoraErrorCode = 'invalid_request' | 'unauthorized' | 'payment_required' | 'tenant_paused' | 'tenant_not_active' | 'spam_complaint_locked' | 'unsubscribe_locked' | 'not_found' | 'domain_exists' | 'webhook_exists' | 'stream_exists' | 'inbound_stream_exists' | 'default_stream' | 'last_token' | 'request_too_large' | 'from_domain_not_verified' | 'stream_not_found' | 'stream_archived' | 'stream_paused' | 'stream_not_sendable' | 'stream_not_broadcast' | 'broadcast_not_enabled' | 'broadcast_not_open' | 'substitution_missing' | 'unsubscribe_placeholder_missing' | 'list_unsubscribe_reserved' | 'recipient_suppressed' | 'idempotency_key_mismatch' | 'idempotency_key_required' | 'rate_limited' | 'monthly_cap_reached' | 'sending_disabled' | 'connection_failed' | 'timeout' | 'unexpected_response' | 'invalid_signature' | 'stale_signature';
|
|
3
|
+
export type SendoraErrorCode = 'invalid_request' | 'unauthorized' | 'payment_required' | 'tenant_paused' | 'tenant_not_active' | 'spam_complaint_locked' | 'unsubscribe_locked' | 'not_found' | 'domain_exists' | 'domain_reserved' | 'inbound_domain_exists' | 'webhook_exists' | 'stream_exists' | 'inbound_stream_exists' | 'default_stream' | 'last_token' | 'request_too_large' | 'from_domain_not_verified' | 'stream_not_found' | 'stream_archived' | 'stream_paused' | 'stream_not_sendable' | 'stream_not_broadcast' | 'broadcast_not_enabled' | 'broadcast_not_open' | 'substitution_missing' | 'unsubscribe_placeholder_missing' | 'list_unsubscribe_reserved' | 'content_expired' | 'content_unreadable' | 'recipient_suppressed' | 'idempotency_key_mismatch' | 'idempotency_key_required' | 'rate_limited' | 'monthly_cap_reached' | 'sending_disabled' | 'connection_failed' | 'timeout' | 'unexpected_response' | 'invalid_signature' | 'stale_signature';
|
|
4
4
|
export interface SendoraErrorFields {
|
|
5
5
|
code: SendoraErrorCode;
|
|
6
6
|
message: string;
|
|
@@ -55,7 +55,7 @@ export declare class SendoraError extends Error {
|
|
|
55
55
|
readonly suppressed: SuppressedRecipient[];
|
|
56
56
|
/** The stream whose suppression list refused the send, on recipient_suppressed. */
|
|
57
57
|
readonly streamId: string | null;
|
|
58
|
-
/** The id of the domain, webhook or stream that already exists, on domain_exists, webhook_exists and
|
|
58
|
+
/** The id of the domain, webhook or stream that already exists, on domain_exists, webhook_exists, stream_exists, inbound_stream_exists and, when the stream already has a domain, inbound_domain_exists. */
|
|
59
59
|
readonly existingId: string | null;
|
|
60
60
|
constructor(fields: SendoraErrorFields);
|
|
61
61
|
/** True when waiting and calling again could succeed: a rate limit, sending paused for everyone, a lost connection, a timeout, or a server-side failure. */
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEnF,mIAAmI;AACnI,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,uBAAuB,GACvB,oBAAoB,GACpB,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,uBAAuB,GACvB,gBAAgB,GAChB,YAAY,GACZ,mBAAmB,GACnB,0BAA0B,GAC1B,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,qBAAqB,GACrB,sBAAsB,GACtB,uBAAuB,GACvB,oBAAoB,GACpB,sBAAsB,GACtB,iCAAiC,GACjC,2BAA2B,GAC3B,sBAAsB,GACtB,0BAA0B,GAC1B,0BAA0B,GAC1B,cAAc,GACd,qBAAqB,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,SAAS,GACT,qBAAqB,GACrB,mBAAmB,GACnB,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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"}
|
package/dist/error.js
CHANGED
|
@@ -8,6 +8,8 @@ const apiCodes = new Set([
|
|
|
8
8
|
'unsubscribe_locked',
|
|
9
9
|
'not_found',
|
|
10
10
|
'domain_exists',
|
|
11
|
+
'domain_reserved',
|
|
12
|
+
'inbound_domain_exists',
|
|
11
13
|
'webhook_exists',
|
|
12
14
|
'stream_exists',
|
|
13
15
|
'inbound_stream_exists',
|
|
@@ -25,6 +27,8 @@ const apiCodes = new Set([
|
|
|
25
27
|
'substitution_missing',
|
|
26
28
|
'unsubscribe_placeholder_missing',
|
|
27
29
|
'list_unsubscribe_reserved',
|
|
30
|
+
'content_expired',
|
|
31
|
+
'content_unreadable',
|
|
28
32
|
'recipient_suppressed',
|
|
29
33
|
'idempotency_key_mismatch',
|
|
30
34
|
'idempotency_key_required',
|
|
@@ -70,7 +74,7 @@ export class SendoraError extends Error {
|
|
|
70
74
|
suppressed;
|
|
71
75
|
/** The stream whose suppression list refused the send, on recipient_suppressed. */
|
|
72
76
|
streamId;
|
|
73
|
-
/** The id of the domain, webhook or stream that already exists, on domain_exists, webhook_exists and
|
|
77
|
+
/** The id of the domain, webhook or stream that already exists, on domain_exists, webhook_exists, stream_exists, inbound_stream_exists and, when the stream already has a domain, inbound_domain_exists. */
|
|
74
78
|
existingId;
|
|
75
79
|
constructor(fields) {
|
|
76
80
|
super(fields.message, { cause: fields.cause });
|
|
@@ -137,7 +141,10 @@ export function errorFromAnswer(status, body, retryAfterHeader) {
|
|
|
137
141
|
issues,
|
|
138
142
|
suppressed: Array.isArray(answer.suppressed) ? answer.suppressed.filter(isSuppressed) : [],
|
|
139
143
|
streamId: code === 'recipient_suppressed' ? stringOf(answer.streamId) : null,
|
|
140
|
-
existingId: stringOf(answer.domainId) ??
|
|
144
|
+
existingId: stringOf(answer.domainId) ??
|
|
145
|
+
stringOf(answer.webhookId) ??
|
|
146
|
+
stringOf(answer.streamId) ??
|
|
147
|
+
stringOf(answer.inboundDomainId),
|
|
141
148
|
});
|
|
142
149
|
}
|
|
143
150
|
function stringOf(value) {
|
package/dist/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Transport } from './transport.ts';
|
|
2
|
+
import type { CreateInboundDomainRequest, InboundDomain, InboundDomainList, RequestOptions, VerifiedInboundDomain } from './types.ts';
|
|
3
|
+
/** The server's own domains for receiving: one per inbound stream, catch-all, with the two DNS records each one needs. */
|
|
4
|
+
export declare class InboundDomainsResource {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(transport: Transport);
|
|
7
|
+
/**
|
|
8
|
+
* Claims a domain for an inbound stream and answers the two records to
|
|
9
|
+
* create: an MX that brings the domain's mail to Sendora and a TXT
|
|
10
|
+
* record that proves the claim. Mail is accepted once both are seen.
|
|
11
|
+
* `domain_reserved` is a name of Sendora's own; `inbound_domain_exists`
|
|
12
|
+
* is a stream that already has a domain (`existingId` names it) or a
|
|
13
|
+
* name another account holds verified.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const domain = await sendora.inboundDomains.create({ streamId, domain: 'post.example.se' });
|
|
17
|
+
* console.log(domain.mx.host, domain.mx.value);
|
|
18
|
+
* console.log(domain.txt.host, domain.txt.value);
|
|
19
|
+
*/
|
|
20
|
+
create(request: CreateInboundDomainRequest, options?: RequestOptions): Promise<InboundDomain>;
|
|
21
|
+
/** Every inbound domain of the token's server. */
|
|
22
|
+
list(options?: RequestOptions): Promise<InboundDomainList>;
|
|
23
|
+
/** One domain by id, with the state of its records. */
|
|
24
|
+
get(inboundDomainId: string, options?: RequestOptions): Promise<InboundDomain>;
|
|
25
|
+
/**
|
|
26
|
+
* Looks both records up now and answers the domain as it stands plus
|
|
27
|
+
* what each lookup found: `ok`, `missing`, `mismatch` or `dns_error`.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const { verified, check } = await sendora.inboundDomains.verify(inboundDomainId);
|
|
31
|
+
*/
|
|
32
|
+
verify(inboundDomainId: string, options?: RequestOptions): Promise<VerifiedInboundDomain>;
|
|
33
|
+
/** Removes the domain; mail to it is refused from then on, and the name is free for another claim. */
|
|
34
|
+
delete(inboundDomainId: string, options?: RequestOptions): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=inbound-domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-domains.d.ts","sourceRoot":"","sources":["../src/inbound-domains.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,0HAA0H;AAC1H,qBAAa,sBAAsB;;gBAGrB,SAAS,EAAE,SAAS;IAIhC;;;;;;;;;;;;OAYG;IACH,MAAM,CACJ,OAAO,EAAE,0BAA0B,EACnC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC;IAUzB,kDAAkD;IAClD,IAAI,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAS9D,uDAAuD;IACvD,GAAG,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IASlF;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAS7F,sGAAsG;IACtG,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ7E"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** The server's own domains for receiving: one per inbound stream, catch-all, with the two DNS records each one needs. */
|
|
2
|
+
export class InboundDomainsResource {
|
|
3
|
+
#transport;
|
|
4
|
+
constructor(transport) {
|
|
5
|
+
this.#transport = transport;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Claims a domain for an inbound stream and answers the two records to
|
|
9
|
+
* create: an MX that brings the domain's mail to Sendora and a TXT
|
|
10
|
+
* record that proves the claim. Mail is accepted once both are seen.
|
|
11
|
+
* `domain_reserved` is a name of Sendora's own; `inbound_domain_exists`
|
|
12
|
+
* is a stream that already has a domain (`existingId` names it) or a
|
|
13
|
+
* name another account holds verified.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const domain = await sendora.inboundDomains.create({ streamId, domain: 'post.example.se' });
|
|
17
|
+
* console.log(domain.mx.host, domain.mx.value);
|
|
18
|
+
* console.log(domain.txt.host, domain.txt.value);
|
|
19
|
+
*/
|
|
20
|
+
create(request, options = {}) {
|
|
21
|
+
return this.#transport.request({
|
|
22
|
+
method: 'POST',
|
|
23
|
+
path: '/v1/inbound/domains',
|
|
24
|
+
body: request,
|
|
25
|
+
idempotent: false,
|
|
26
|
+
signal: options.signal,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** Every inbound domain of the token's server. */
|
|
30
|
+
list(options = {}) {
|
|
31
|
+
return this.#transport.request({
|
|
32
|
+
method: 'GET',
|
|
33
|
+
path: '/v1/inbound/domains',
|
|
34
|
+
idempotent: true,
|
|
35
|
+
signal: options.signal,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** One domain by id, with the state of its records. */
|
|
39
|
+
get(inboundDomainId, options = {}) {
|
|
40
|
+
return this.#transport.request({
|
|
41
|
+
method: 'GET',
|
|
42
|
+
path: `/v1/inbound/domains/${encodeURIComponent(inboundDomainId)}`,
|
|
43
|
+
idempotent: true,
|
|
44
|
+
signal: options.signal,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Looks both records up now and answers the domain as it stands plus
|
|
49
|
+
* what each lookup found: `ok`, `missing`, `mismatch` or `dns_error`.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const { verified, check } = await sendora.inboundDomains.verify(inboundDomainId);
|
|
53
|
+
*/
|
|
54
|
+
verify(inboundDomainId, options = {}) {
|
|
55
|
+
return this.#transport.request({
|
|
56
|
+
method: 'POST',
|
|
57
|
+
path: `/v1/inbound/domains/${encodeURIComponent(inboundDomainId)}/verify`,
|
|
58
|
+
idempotent: true,
|
|
59
|
+
signal: options.signal,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Removes the domain; mail to it is refused from then on, and the name is free for another claim. */
|
|
63
|
+
delete(inboundDomainId, options = {}) {
|
|
64
|
+
return this.#transport.request({
|
|
65
|
+
method: 'DELETE',
|
|
66
|
+
path: `/v1/inbound/domains/${encodeURIComponent(inboundDomainId)}`,
|
|
67
|
+
idempotent: true,
|
|
68
|
+
signal: options.signal,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=inbound-domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-domains.js","sourceRoot":"","sources":["../src/inbound-domains.ts"],"names":[],"mappings":"AASA,0HAA0H;AAC1H,MAAM,OAAO,sBAAsB;IACxB,UAAU,CAAY;IAE/B,YAAY,SAAoB;QAC9B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CACJ,OAAmC,EACnC,UAA0B,EAAE;QAE5B,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAgB;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED,kDAAkD;IAClD,IAAI,CAAC,UAA0B,EAAE;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAoB;YAChD,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,qBAAqB;YAC3B,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED,uDAAuD;IACvD,GAAG,CAAC,eAAuB,EAAE,UAA0B,EAAE;QACvD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAgB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,uBAAuB,kBAAkB,CAAC,eAAe,CAAC,EAAE;YAClE,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,eAAuB,EAAE,UAA0B,EAAE;QAC1D,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAwB;YACpD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,uBAAuB,kBAAkB,CAAC,eAAe,CAAC,SAAS;YACzE,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED,sGAAsG;IACtG,MAAM,CAAC,eAAuB,EAAE,UAA0B,EAAE;QAC1D,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAY;YACxC,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,uBAAuB,kBAAkB,CAAC,eAAe,CAAC,EAAE;YAClE,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Transport } from './transport.ts';
|
|
2
|
+
import type { InboundMessage, InboundMessageDetail, InboundPage, InboundSearch, InboundSearchBody, RequestOptions } from './types.ts';
|
|
3
|
+
/** The mail the token's server has received on its inbound stream. */
|
|
4
|
+
export declare class InboundResource {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(transport: Transport);
|
|
7
|
+
/**
|
|
8
|
+
* One received message: its envelope, parties, headers, text and HTML,
|
|
9
|
+
* and its attachments described. The attachment bytes and the raw
|
|
10
|
+
* message are downloads of their own. Once the stream's content window
|
|
11
|
+
* has passed, `contentAvailable` is false and the content fields are
|
|
12
|
+
* null.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const message = await sendora.inbound.get(inboundMessageId);
|
|
16
|
+
* console.log(message.from?.address, message.subject, message.text);
|
|
17
|
+
*/
|
|
18
|
+
get(inboundMessageId: string, options?: RequestOptions): Promise<InboundMessageDetail>;
|
|
19
|
+
/**
|
|
20
|
+
* One page of received messages, newest first. Every filter is
|
|
21
|
+
* optional; pass the page's `next` as `after` for the following page,
|
|
22
|
+
* or use `searchAll`.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const page = await sendora.inbound.search({ from: 'anna@example.com', limit: 20 });
|
|
26
|
+
*/
|
|
27
|
+
search(search?: InboundSearch, options?: RequestOptions): Promise<InboundPage>;
|
|
28
|
+
/**
|
|
29
|
+
* Every received message the filters match, page by page, for `for await`.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* for await (const message of sendora.inbound.searchAll({ recipient: address })) {
|
|
33
|
+
* console.log(message.receivedAt, message.subject);
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
searchAll(search?: InboundSearch, options?: RequestOptions): AsyncIterable<InboundMessage>;
|
|
37
|
+
/**
|
|
38
|
+
* The message byte for byte as it was received, as `message/rfc822`.
|
|
39
|
+
* Throws `content_expired` once the stream's content window has passed.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const raw = await sendora.inbound.raw(inboundMessageId);
|
|
43
|
+
* await writeFile(`${inboundMessageId}.eml`, raw);
|
|
44
|
+
*/
|
|
45
|
+
raw(inboundMessageId: string, options?: RequestOptions): Promise<Uint8Array>;
|
|
46
|
+
/**
|
|
47
|
+
* An attachment's bytes, whatever the sender declared them to be; the
|
|
48
|
+
* name and the declared type are on the message. Throws
|
|
49
|
+
* `content_expired` once the stream's content window has passed.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const message = await sendora.inbound.get(inboundMessageId);
|
|
53
|
+
* for (const attachment of message.attachments) {
|
|
54
|
+
* const bytes = await sendora.inbound.attachment(inboundMessageId, attachment.attachmentId);
|
|
55
|
+
* }
|
|
56
|
+
*/
|
|
57
|
+
attachment(inboundMessageId: string, attachmentId: string, options?: RequestOptions): Promise<Uint8Array>;
|
|
58
|
+
}
|
|
59
|
+
/** The body as the API takes it: times as ISO 8601 strings. */
|
|
60
|
+
export declare function encodeInboundSearch(search: InboundSearch): InboundSearchBody;
|
|
61
|
+
//# sourceMappingURL=inbound.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,sEAAsE;AACtE,qBAAa,eAAe;;gBAGd,SAAS,EAAE,SAAS;IAIhC;;;;;;;;;;OAUG;IACH,GAAG,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAS1F;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,GAAE,aAAkB,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IAUtF;;;;;;;OAOG;IACH,SAAS,CACP,MAAM,GAAE,aAAkB,EAC1B,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAAC,cAAc,CAAC;IAShC;;;;;;;OAOG;IACH,GAAG,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,UAAU,CAAC;IAShF;;;;;;;;;;OAUG;IACH,UAAU,CACR,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC;CAQvB;AAED,+DAA+D;AAC/D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,iBAAiB,CAU5E"}
|
package/dist/inbound.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { paginate } from "./pagination.js";
|
|
2
|
+
/** The mail the token's server has received on its inbound stream. */
|
|
3
|
+
export class InboundResource {
|
|
4
|
+
#transport;
|
|
5
|
+
constructor(transport) {
|
|
6
|
+
this.#transport = transport;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* One received message: its envelope, parties, headers, text and HTML,
|
|
10
|
+
* and its attachments described. The attachment bytes and the raw
|
|
11
|
+
* message are downloads of their own. Once the stream's content window
|
|
12
|
+
* has passed, `contentAvailable` is false and the content fields are
|
|
13
|
+
* null.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const message = await sendora.inbound.get(inboundMessageId);
|
|
17
|
+
* console.log(message.from?.address, message.subject, message.text);
|
|
18
|
+
*/
|
|
19
|
+
get(inboundMessageId, options = {}) {
|
|
20
|
+
return this.#transport.request({
|
|
21
|
+
method: 'GET',
|
|
22
|
+
path: `/v1/inbound/${encodeURIComponent(inboundMessageId)}`,
|
|
23
|
+
idempotent: true,
|
|
24
|
+
signal: options.signal,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* One page of received messages, newest first. Every filter is
|
|
29
|
+
* optional; pass the page's `next` as `after` for the following page,
|
|
30
|
+
* or use `searchAll`.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const page = await sendora.inbound.search({ from: 'anna@example.com', limit: 20 });
|
|
34
|
+
*/
|
|
35
|
+
search(search = {}, options = {}) {
|
|
36
|
+
return this.#transport.request({
|
|
37
|
+
method: 'POST',
|
|
38
|
+
path: '/v1/inbound/search',
|
|
39
|
+
body: encodeInboundSearch(search),
|
|
40
|
+
idempotent: true,
|
|
41
|
+
signal: options.signal,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Every received message the filters match, page by page, for `for await`.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* for await (const message of sendora.inbound.searchAll({ recipient: address })) {
|
|
49
|
+
* console.log(message.receivedAt, message.subject);
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
searchAll(search = {}, options = {}) {
|
|
53
|
+
return paginate((after) => this.search({ ...search, after }, options), (page) => page.messages, (page) => page.next, search.after);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The message byte for byte as it was received, as `message/rfc822`.
|
|
57
|
+
* Throws `content_expired` once the stream's content window has passed.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const raw = await sendora.inbound.raw(inboundMessageId);
|
|
61
|
+
* await writeFile(`${inboundMessageId}.eml`, raw);
|
|
62
|
+
*/
|
|
63
|
+
raw(inboundMessageId, options = {}) {
|
|
64
|
+
return this.#transport.requestBytes({
|
|
65
|
+
method: 'GET',
|
|
66
|
+
path: `/v1/inbound/${encodeURIComponent(inboundMessageId)}/raw`,
|
|
67
|
+
idempotent: true,
|
|
68
|
+
signal: options.signal,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* An attachment's bytes, whatever the sender declared them to be; the
|
|
73
|
+
* name and the declared type are on the message. Throws
|
|
74
|
+
* `content_expired` once the stream's content window has passed.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* const message = await sendora.inbound.get(inboundMessageId);
|
|
78
|
+
* for (const attachment of message.attachments) {
|
|
79
|
+
* const bytes = await sendora.inbound.attachment(inboundMessageId, attachment.attachmentId);
|
|
80
|
+
* }
|
|
81
|
+
*/
|
|
82
|
+
attachment(inboundMessageId, attachmentId, options = {}) {
|
|
83
|
+
return this.#transport.requestBytes({
|
|
84
|
+
method: 'GET',
|
|
85
|
+
path: `/v1/inbound/${encodeURIComponent(inboundMessageId)}/attachments/${encodeURIComponent(attachmentId)}`,
|
|
86
|
+
idempotent: true,
|
|
87
|
+
signal: options.signal,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** The body as the API takes it: times as ISO 8601 strings. */
|
|
92
|
+
export function encodeInboundSearch(search) {
|
|
93
|
+
const { receivedFrom, receivedTo, ...fields } = search;
|
|
94
|
+
const body = { ...fields };
|
|
95
|
+
if (receivedFrom !== undefined) {
|
|
96
|
+
body.receivedFrom = isoOf(receivedFrom);
|
|
97
|
+
}
|
|
98
|
+
if (receivedTo !== undefined) {
|
|
99
|
+
body.receivedTo = isoOf(receivedTo);
|
|
100
|
+
}
|
|
101
|
+
return body;
|
|
102
|
+
}
|
|
103
|
+
function isoOf(value) {
|
|
104
|
+
return typeof value === 'string' ? value : value.toISOString();
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=inbound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"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"}
|