shipmail-cli 0.2.1 → 0.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.
- package/README.md +18 -9
- package/dist/cli.js +138 -12
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -56,10 +56,21 @@ shipmail messages send --mailbox-id mbx_123 --to user@example.com --subject "Tes
|
|
|
56
56
|
shipmail mailboxes sandbox-inbound mbx_123 --from customer@example.com --subject "Re: Test" --text "Fake inbound reply"
|
|
57
57
|
|
|
58
58
|
# Read inbound mail
|
|
59
|
-
shipmail inbox list
|
|
60
|
-
shipmail inbox
|
|
61
|
-
shipmail inbox reply-
|
|
62
|
-
shipmail inbox
|
|
59
|
+
shipmail inbox list 550e8400-e29b-41d4-a716-446655440000 --folder-role inbox --after 2025-07-20T00:00:00Z --limit 25
|
|
60
|
+
shipmail inbox message 550e8400-e29b-41d4-a716-446655440000 eml_123
|
|
61
|
+
shipmail inbox threads 550e8400-e29b-41d4-a716-446655440000 --reply-state needs_reply --after 2025-07-20T00:00:00Z --limit 50
|
|
62
|
+
shipmail inbox thread 550e8400-e29b-41d4-a716-446655440000 thr_123
|
|
63
|
+
shipmail inbox draft 550e8400-e29b-41d4-a716-446655440000 thr_123 --expected-reply-version 7 --text "Thanks for the note"
|
|
64
|
+
# Apply your approval policy; stale drafts fail with 409 without delivery.
|
|
65
|
+
shipmail inbox send-draft 550e8400-e29b-41d4-a716-446655440000 thr_123 drf_123
|
|
66
|
+
shipmail inbox thread-state 550e8400-e29b-41d4-a716-446655440000 thr_123 --reply-state resolved --expected-reply-version 8
|
|
67
|
+
shipmail inbox reply-message 550e8400-e29b-41d4-a716-446655440000 eml_123 --to user@example.com --text "Thanks"
|
|
68
|
+
shipmail inbox reply-thread 550e8400-e29b-41d4-a716-446655440000 thr_123 --to user@example.com --text "Following up"
|
|
69
|
+
|
|
70
|
+
# Frozen historical scan, retained for 30 days (repeat --mailbox-id for more mailboxes)
|
|
71
|
+
shipmail reply-scans create --mailbox-id 550e8400-e29b-41d4-a716-446655440000 --after 2025-07-20T00:00:00Z
|
|
72
|
+
shipmail reply-scans status rsc_123
|
|
73
|
+
shipmail reply-scans results rsc_123 --limit 100
|
|
63
74
|
|
|
64
75
|
# Find newsletter sending domain IDs, then create a draft with blocks
|
|
65
76
|
shipmail newsletter-domains list
|
|
@@ -106,9 +117,6 @@ shipmail api GET /domains
|
|
|
106
117
|
|
|
107
118
|
shipmail api PATCH /mailboxes/mbx_123/spam-filter \
|
|
108
119
|
--data '{"threshold":6}'
|
|
109
|
-
|
|
110
|
-
shipmail api PUT /mailboxes/mbx_123/rules \
|
|
111
|
-
--data @rules.json
|
|
112
120
|
```
|
|
113
121
|
|
|
114
122
|
Use repeatable `--header "Name: value"` flags for request headers. Use `--output path` to write non-JSON responses, such as attachment downloads.
|
|
@@ -118,8 +126,9 @@ Use repeatable `--header "Name: value"` flags for request headers. Use `--output
|
|
|
118
126
|
- `status`
|
|
119
127
|
- `api <METHOD> <PATH>`
|
|
120
128
|
- `domains list|search|create|get|verify|delete`
|
|
121
|
-
- `mailboxes list|create|get|suspend|resume|forwarding|forwarding-add|forwarding-remove|app-passwords|folders|identities
|
|
122
|
-
- `inbox list|thread|reply-message|reply-thread|update|move`
|
|
129
|
+
- `mailboxes list|create|get|suspend|resume|forwarding|forwarding-add|forwarding-remove|app-passwords|folders|identities`
|
|
130
|
+
- `inbox list|message|threads|thread|thread-state|draft|send-draft|reply-message|reply-thread|update|move`
|
|
131
|
+
- `reply-scans create|status|results`
|
|
123
132
|
- `messages send|list|get|reply` (test keys also support `--sandbox-outcome`)
|
|
124
133
|
- `mailboxes sandbox-inbound`
|
|
125
134
|
- `webhooks list|create|test|deliveries|replay-delivery`
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "shipmail";
|
|
14
14
|
|
|
15
15
|
// src/version.ts
|
|
16
|
-
var VERSION = "0.
|
|
16
|
+
var VERSION = "0.3.0";
|
|
17
17
|
|
|
18
18
|
// src/cli.ts
|
|
19
19
|
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
@@ -335,13 +335,17 @@ Usage:
|
|
|
335
335
|
shipmail mailboxes app-passwords revoke <id> <app-password-id>
|
|
336
336
|
shipmail mailboxes folders <id>
|
|
337
337
|
shipmail mailboxes identities <id>
|
|
338
|
-
shipmail mailboxes rules <id>
|
|
339
338
|
shipmail mailboxes forwarding <id>
|
|
340
339
|
shipmail mailboxes forwarding-add <id> --destination owner@example.com
|
|
341
340
|
shipmail mailboxes forwarding-remove <id> <forwarding-id>
|
|
342
341
|
shipmail mailboxes sandbox-inbound <id> --from sender@example.com --subject "Test" (--text "Hello" | --html "<p>Hello</p>") [--to support@example.com]
|
|
343
|
-
shipmail inbox list <mailbox-id> [--folder-role inbox] [--limit 25]
|
|
342
|
+
shipmail inbox list <mailbox-id> [--folder-role inbox] [--after ISO] [--before ISO] [--limit 25] [--cursor cur]
|
|
343
|
+
shipmail inbox message <mailbox-id> <message-id>
|
|
344
|
+
shipmail inbox threads <mailbox-id> [--reply-state needs_reply] [--after ISO] [--before ISO] [--limit 25] [--cursor cur]
|
|
344
345
|
shipmail inbox thread <mailbox-id> <thread-id>
|
|
346
|
+
shipmail inbox thread-state <mailbox-id> <thread-id> --reply-state resolved --expected-reply-version 3
|
|
347
|
+
shipmail inbox draft <mailbox-id> <thread-id> --expected-reply-version 3 (--text "Hello" | --html "<p>Hello</p>") [--reply-mode reply_all]
|
|
348
|
+
shipmail inbox send-draft <mailbox-id> <thread-id> <draft-id>
|
|
345
349
|
shipmail inbox reply-message <mailbox-id> <message-id> --to user@example.com (--text "Hello" | --html "<p>Hello</p>")
|
|
346
350
|
shipmail inbox reply-thread <mailbox-id> <thread-id> --to user@example.com (--text "Hello" | --html "<p>Hello</p>")
|
|
347
351
|
shipmail inbox update <mailbox-id> <message-id> [--read true] [--starred false]
|
|
@@ -350,6 +354,9 @@ Usage:
|
|
|
350
354
|
shipmail messages list (--mailbox-id mbx | --client-reference crm-123) [--limit 25] [--cursor cur]
|
|
351
355
|
shipmail messages get <message-id>
|
|
352
356
|
shipmail messages reply <message-id> --to user@example.com (--text "Hello" | --html "<p>Hello</p>") [--client-reference crm-reply-123]
|
|
357
|
+
shipmail reply-scans create --mailbox-id mbx --after ISO [--before ISO]
|
|
358
|
+
shipmail reply-scans status <scan-id>
|
|
359
|
+
shipmail reply-scans results <scan-id> [--limit 25] [--cursor cur]
|
|
353
360
|
shipmail webhooks list
|
|
354
361
|
shipmail webhooks create --url https://example.com/hook --events message.received,message.bounced
|
|
355
362
|
shipmail webhooks replay-delivery <webhook-id> <delivery-id> [--idempotency-key key]
|
|
@@ -434,14 +441,18 @@ function inboxListParams(options) {
|
|
|
434
441
|
const folderId = getString(options, "folder-id");
|
|
435
442
|
const folderRole = getString(options, "folder-role");
|
|
436
443
|
const searchText = getString(options, "search");
|
|
437
|
-
const
|
|
444
|
+
const cursor = getString(options, "cursor");
|
|
445
|
+
const after = getString(options, "after");
|
|
446
|
+
const before = getString(options, "before");
|
|
438
447
|
const limit = getNumber(options, "limit");
|
|
439
448
|
const hasKeyword = getString(options, "has-keyword");
|
|
440
449
|
const notKeyword = getString(options, "not-keyword");
|
|
441
450
|
if (folderId) params.folder_id = folderId;
|
|
442
451
|
if (folderRole) params.folder_role = folderRole;
|
|
443
452
|
if (searchText) params.search_text = searchText;
|
|
444
|
-
if (
|
|
453
|
+
if (cursor) params.cursor = cursor;
|
|
454
|
+
if (after) params.after = after;
|
|
455
|
+
if (before) params.before = before;
|
|
445
456
|
if (limit !== void 0) params.limit = limit;
|
|
446
457
|
if (hasKeyword) params.has_keyword = hasKeyword;
|
|
447
458
|
if (notKeyword) params.not_keyword = notKeyword;
|
|
@@ -724,13 +735,6 @@ async function runMailboxes(client, parsed, out) {
|
|
|
724
735
|
);
|
|
725
736
|
return;
|
|
726
737
|
}
|
|
727
|
-
if (subcommand === "rules") {
|
|
728
|
-
writeJson(
|
|
729
|
-
out,
|
|
730
|
-
await client.mailboxes.getRules(requirePositional(parsed.positional, 2, "mailbox id"))
|
|
731
|
-
);
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
738
|
if (subcommand === "forwarding") {
|
|
735
739
|
writeJson(
|
|
736
740
|
out,
|
|
@@ -807,6 +811,92 @@ async function runInbox(client, parsed, out) {
|
|
|
807
811
|
);
|
|
808
812
|
return;
|
|
809
813
|
}
|
|
814
|
+
if (subcommand === "message") {
|
|
815
|
+
writeJson(
|
|
816
|
+
out,
|
|
817
|
+
await client.mailboxes.getInboxMessage(
|
|
818
|
+
requirePositional(parsed.positional, 2, "mailbox id"),
|
|
819
|
+
requirePositional(parsed.positional, 3, "message id")
|
|
820
|
+
)
|
|
821
|
+
);
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
if (subcommand === "threads") {
|
|
825
|
+
const replyState = getString(parsed.options, "reply-state");
|
|
826
|
+
const sortBy = getString(parsed.options, "sort-by");
|
|
827
|
+
const order = getString(parsed.options, "order");
|
|
828
|
+
writeJson(
|
|
829
|
+
out,
|
|
830
|
+
await client.mailboxes.listInboxThreads(
|
|
831
|
+
requirePositional(parsed.positional, 2, "mailbox id"),
|
|
832
|
+
{
|
|
833
|
+
...replyState ? {
|
|
834
|
+
reply_state: replyState
|
|
835
|
+
} : {},
|
|
836
|
+
...sortBy ? { sort_by: sortBy } : {},
|
|
837
|
+
...order ? { order } : {},
|
|
838
|
+
...getString(parsed.options, "after") ? { after: getString(parsed.options, "after") } : {},
|
|
839
|
+
...getString(parsed.options, "before") ? { before: getString(parsed.options, "before") } : {},
|
|
840
|
+
...getString(parsed.options, "cursor") ? { cursor: getString(parsed.options, "cursor") } : {},
|
|
841
|
+
...getNumber(parsed.options, "limit") !== void 0 ? { limit: getNumber(parsed.options, "limit") } : {}
|
|
842
|
+
}
|
|
843
|
+
)
|
|
844
|
+
);
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
if (subcommand === "thread-state") {
|
|
848
|
+
const replyState = getString(parsed.options, "reply-state");
|
|
849
|
+
const expectedReplyVersion = getNumber(parsed.options, "expected-reply-version");
|
|
850
|
+
if (!replyState || expectedReplyVersion === void 0) {
|
|
851
|
+
throw new CliUsageError("Provide --reply-state and --expected-reply-version.");
|
|
852
|
+
}
|
|
853
|
+
writeJson(
|
|
854
|
+
out,
|
|
855
|
+
await client.mailboxes.updateInboxThreadReplyState(
|
|
856
|
+
requirePositional(parsed.positional, 2, "mailbox id"),
|
|
857
|
+
requirePositional(parsed.positional, 3, "thread id"),
|
|
858
|
+
{
|
|
859
|
+
reply_state: replyState,
|
|
860
|
+
expected_reply_version: expectedReplyVersion
|
|
861
|
+
}
|
|
862
|
+
)
|
|
863
|
+
);
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
if (subcommand === "draft") {
|
|
867
|
+
const expectedReplyVersion = getNumber(parsed.options, "expected-reply-version");
|
|
868
|
+
if (expectedReplyVersion === void 0) {
|
|
869
|
+
throw new CliUsageError("Provide --expected-reply-version.");
|
|
870
|
+
}
|
|
871
|
+
const text = await readTextInput(getString(parsed.options, "text"));
|
|
872
|
+
const html = await readTextInput(getString(parsed.options, "html"));
|
|
873
|
+
if (!text && !html) throw new CliUsageError("Provide --text or --html.");
|
|
874
|
+
writeJson(
|
|
875
|
+
out,
|
|
876
|
+
await client.mailboxes.createInboxReplyDraft(
|
|
877
|
+
requirePositional(parsed.positional, 2, "mailbox id"),
|
|
878
|
+
requirePositional(parsed.positional, 3, "thread id"),
|
|
879
|
+
{
|
|
880
|
+
expected_reply_version: expectedReplyVersion,
|
|
881
|
+
...text ? { text } : {},
|
|
882
|
+
...html ? { html } : {},
|
|
883
|
+
...getString(parsed.options, "reply-mode") ? { reply_mode: getString(parsed.options, "reply-mode") } : {}
|
|
884
|
+
}
|
|
885
|
+
)
|
|
886
|
+
);
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
if (subcommand === "send-draft") {
|
|
890
|
+
writeJson(
|
|
891
|
+
out,
|
|
892
|
+
await client.mailboxes.sendInboxReplyDraft(
|
|
893
|
+
requirePositional(parsed.positional, 2, "mailbox id"),
|
|
894
|
+
requirePositional(parsed.positional, 3, "thread id"),
|
|
895
|
+
requirePositional(parsed.positional, 4, "draft id")
|
|
896
|
+
)
|
|
897
|
+
);
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
810
900
|
if (subcommand === "reply-message") {
|
|
811
901
|
writeJson(
|
|
812
902
|
out,
|
|
@@ -870,6 +960,41 @@ async function runInbox(client, parsed, out) {
|
|
|
870
960
|
}
|
|
871
961
|
throw new CliUsageError("Unknown inbox command.");
|
|
872
962
|
}
|
|
963
|
+
async function runReplyScans(client, parsed, out) {
|
|
964
|
+
const subcommand = parsed.positional[1];
|
|
965
|
+
if (subcommand === "create") {
|
|
966
|
+
const mailboxIds = getStringList(parsed.options, "mailbox-id");
|
|
967
|
+
const after = getString(parsed.options, "after");
|
|
968
|
+
if (mailboxIds.length === 0 || !after) {
|
|
969
|
+
throw new CliUsageError("Provide --mailbox-id and --after.");
|
|
970
|
+
}
|
|
971
|
+
writeJson(
|
|
972
|
+
out,
|
|
973
|
+
await client.replyScans.create({
|
|
974
|
+
mailbox_ids: [...mailboxIds],
|
|
975
|
+
after,
|
|
976
|
+
...getString(parsed.options, "before") ? { before: getString(parsed.options, "before") } : {}
|
|
977
|
+
})
|
|
978
|
+
);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
const scanId = requirePositional(parsed.positional, 2, "scan id");
|
|
982
|
+
if (subcommand === "status") {
|
|
983
|
+
writeJson(out, await client.replyScans.get(scanId));
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
if (subcommand === "results") {
|
|
987
|
+
writeJson(
|
|
988
|
+
out,
|
|
989
|
+
await client.replyScans.listResults(scanId, {
|
|
990
|
+
...getString(parsed.options, "cursor") ? { cursor: getString(parsed.options, "cursor") } : {},
|
|
991
|
+
...getNumber(parsed.options, "limit") !== void 0 ? { limit: getNumber(parsed.options, "limit") } : {}
|
|
992
|
+
})
|
|
993
|
+
);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
throw new CliUsageError("Unknown reply-scans command.");
|
|
997
|
+
}
|
|
873
998
|
async function runMessages(client, parsed, out) {
|
|
874
999
|
const subcommand = parsed.positional[1];
|
|
875
1000
|
if (subcommand === "send") {
|
|
@@ -1667,6 +1792,7 @@ async function runCli(argv, options = {}) {
|
|
|
1667
1792
|
else if (command === "mailboxes") await runMailboxes(client, parsed, out);
|
|
1668
1793
|
else if (command === "inbox") await runInbox(client, parsed, out);
|
|
1669
1794
|
else if (command === "messages") await runMessages(client, parsed, out);
|
|
1795
|
+
else if (command === "reply-scans") await runReplyScans(client, parsed, out);
|
|
1670
1796
|
else if (command === "webhooks") await runWebhooks(client, parsed, out);
|
|
1671
1797
|
else if (command === "suppressions") await runSuppressions(client, parsed, out);
|
|
1672
1798
|
else if (command === "newsletters") await runNewsletters(client, parsed, out);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipmail-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Official CLI for the ShipMail API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"shipmail": "0.
|
|
44
|
+
"shipmail": "0.3.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"tsup": "^8.4.0",
|