shipmail-cli 0.2.1 → 0.2.2

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 (3) hide show
  1. package/README.md +17 -5
  2. package/dist/cli.js +138 -4
  3. 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 mbx_123 --folder-role inbox --limit 25
60
- shipmail inbox thread mbx_123 thr_123
61
- shipmail inbox reply-message mbx_123 eml_123 --to user@example.com --text "Thanks"
62
- shipmail inbox reply-thread mbx_123 thr_123 --to user@example.com --text "Following up"
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
@@ -119,7 +130,8 @@ Use repeatable `--header "Name: value"` flags for request headers. Use `--output
119
130
  - `api <METHOD> <PATH>`
120
131
  - `domains list|search|create|get|verify|delete`
121
132
  - `mailboxes list|create|get|suspend|resume|forwarding|forwarding-add|forwarding-remove|app-passwords|folders|identities|rules`
122
- - `inbox list|thread|reply-message|reply-thread|update|move`
133
+ - `inbox list|message|threads|thread|thread-state|draft|send-draft|reply-message|reply-thread|update|move`
134
+ - `reply-scans create|status|results`
123
135
  - `messages send|list|get|reply` (test keys also support `--sandbox-outcome`)
124
136
  - `mailboxes sandbox-inbound`
125
137
  - `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.2.1";
16
+ var VERSION = "0.2.2";
17
17
 
18
18
  // src/cli.ts
19
19
  var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
@@ -340,8 +340,13 @@ Usage:
340
340
  shipmail mailboxes forwarding-add <id> --destination owner@example.com
341
341
  shipmail mailboxes forwarding-remove <id> <forwarding-id>
342
342
  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]
343
+ shipmail inbox list <mailbox-id> [--folder-role inbox] [--after ISO] [--before ISO] [--limit 25] [--cursor cur]
344
+ shipmail inbox message <mailbox-id> <message-id>
345
+ shipmail inbox threads <mailbox-id> [--reply-state needs_reply] [--after ISO] [--before ISO] [--limit 25] [--cursor cur]
344
346
  shipmail inbox thread <mailbox-id> <thread-id>
347
+ shipmail inbox thread-state <mailbox-id> <thread-id> --reply-state resolved --expected-reply-version 3
348
+ shipmail inbox draft <mailbox-id> <thread-id> --expected-reply-version 3 (--text "Hello" | --html "<p>Hello</p>") [--reply-mode reply_all]
349
+ shipmail inbox send-draft <mailbox-id> <thread-id> <draft-id>
345
350
  shipmail inbox reply-message <mailbox-id> <message-id> --to user@example.com (--text "Hello" | --html "<p>Hello</p>")
346
351
  shipmail inbox reply-thread <mailbox-id> <thread-id> --to user@example.com (--text "Hello" | --html "<p>Hello</p>")
347
352
  shipmail inbox update <mailbox-id> <message-id> [--read true] [--starred false]
@@ -350,6 +355,9 @@ Usage:
350
355
  shipmail messages list (--mailbox-id mbx | --client-reference crm-123) [--limit 25] [--cursor cur]
351
356
  shipmail messages get <message-id>
352
357
  shipmail messages reply <message-id> --to user@example.com (--text "Hello" | --html "<p>Hello</p>") [--client-reference crm-reply-123]
358
+ shipmail reply-scans create --mailbox-id mbx --after ISO [--before ISO]
359
+ shipmail reply-scans status <scan-id>
360
+ shipmail reply-scans results <scan-id> [--limit 25] [--cursor cur]
353
361
  shipmail webhooks list
354
362
  shipmail webhooks create --url https://example.com/hook --events message.received,message.bounced
355
363
  shipmail webhooks replay-delivery <webhook-id> <delivery-id> [--idempotency-key key]
@@ -434,14 +442,18 @@ function inboxListParams(options) {
434
442
  const folderId = getString(options, "folder-id");
435
443
  const folderRole = getString(options, "folder-role");
436
444
  const searchText = getString(options, "search");
437
- const position = getNumber(options, "position");
445
+ const cursor = getString(options, "cursor");
446
+ const after = getString(options, "after");
447
+ const before = getString(options, "before");
438
448
  const limit = getNumber(options, "limit");
439
449
  const hasKeyword = getString(options, "has-keyword");
440
450
  const notKeyword = getString(options, "not-keyword");
441
451
  if (folderId) params.folder_id = folderId;
442
452
  if (folderRole) params.folder_role = folderRole;
443
453
  if (searchText) params.search_text = searchText;
444
- if (position !== void 0) params.position = position;
454
+ if (cursor) params.cursor = cursor;
455
+ if (after) params.after = after;
456
+ if (before) params.before = before;
445
457
  if (limit !== void 0) params.limit = limit;
446
458
  if (hasKeyword) params.has_keyword = hasKeyword;
447
459
  if (notKeyword) params.not_keyword = notKeyword;
@@ -807,6 +819,92 @@ async function runInbox(client, parsed, out) {
807
819
  );
808
820
  return;
809
821
  }
822
+ if (subcommand === "message") {
823
+ writeJson(
824
+ out,
825
+ await client.mailboxes.getInboxMessage(
826
+ requirePositional(parsed.positional, 2, "mailbox id"),
827
+ requirePositional(parsed.positional, 3, "message id")
828
+ )
829
+ );
830
+ return;
831
+ }
832
+ if (subcommand === "threads") {
833
+ const replyState = getString(parsed.options, "reply-state");
834
+ const sortBy = getString(parsed.options, "sort-by");
835
+ const order = getString(parsed.options, "order");
836
+ writeJson(
837
+ out,
838
+ await client.mailboxes.listInboxThreads(
839
+ requirePositional(parsed.positional, 2, "mailbox id"),
840
+ {
841
+ ...replyState ? {
842
+ reply_state: replyState
843
+ } : {},
844
+ ...sortBy ? { sort_by: sortBy } : {},
845
+ ...order ? { order } : {},
846
+ ...getString(parsed.options, "after") ? { after: getString(parsed.options, "after") } : {},
847
+ ...getString(parsed.options, "before") ? { before: getString(parsed.options, "before") } : {},
848
+ ...getString(parsed.options, "cursor") ? { cursor: getString(parsed.options, "cursor") } : {},
849
+ ...getNumber(parsed.options, "limit") !== void 0 ? { limit: getNumber(parsed.options, "limit") } : {}
850
+ }
851
+ )
852
+ );
853
+ return;
854
+ }
855
+ if (subcommand === "thread-state") {
856
+ const replyState = getString(parsed.options, "reply-state");
857
+ const expectedReplyVersion = getNumber(parsed.options, "expected-reply-version");
858
+ if (!replyState || expectedReplyVersion === void 0) {
859
+ throw new CliUsageError("Provide --reply-state and --expected-reply-version.");
860
+ }
861
+ writeJson(
862
+ out,
863
+ await client.mailboxes.updateInboxThreadReplyState(
864
+ requirePositional(parsed.positional, 2, "mailbox id"),
865
+ requirePositional(parsed.positional, 3, "thread id"),
866
+ {
867
+ reply_state: replyState,
868
+ expected_reply_version: expectedReplyVersion
869
+ }
870
+ )
871
+ );
872
+ return;
873
+ }
874
+ if (subcommand === "draft") {
875
+ const expectedReplyVersion = getNumber(parsed.options, "expected-reply-version");
876
+ if (expectedReplyVersion === void 0) {
877
+ throw new CliUsageError("Provide --expected-reply-version.");
878
+ }
879
+ const text = await readTextInput(getString(parsed.options, "text"));
880
+ const html = await readTextInput(getString(parsed.options, "html"));
881
+ if (!text && !html) throw new CliUsageError("Provide --text or --html.");
882
+ writeJson(
883
+ out,
884
+ await client.mailboxes.createInboxReplyDraft(
885
+ requirePositional(parsed.positional, 2, "mailbox id"),
886
+ requirePositional(parsed.positional, 3, "thread id"),
887
+ {
888
+ expected_reply_version: expectedReplyVersion,
889
+ ...text ? { text } : {},
890
+ ...html ? { html } : {},
891
+ ...getString(parsed.options, "reply-mode") ? { reply_mode: getString(parsed.options, "reply-mode") } : {}
892
+ }
893
+ )
894
+ );
895
+ return;
896
+ }
897
+ if (subcommand === "send-draft") {
898
+ writeJson(
899
+ out,
900
+ await client.mailboxes.sendInboxReplyDraft(
901
+ requirePositional(parsed.positional, 2, "mailbox id"),
902
+ requirePositional(parsed.positional, 3, "thread id"),
903
+ requirePositional(parsed.positional, 4, "draft id")
904
+ )
905
+ );
906
+ return;
907
+ }
810
908
  if (subcommand === "reply-message") {
811
909
  writeJson(
812
910
  out,
@@ -870,6 +968,41 @@ async function runInbox(client, parsed, out) {
870
968
  }
871
969
  throw new CliUsageError("Unknown inbox command.");
872
970
  }
971
+ async function runReplyScans(client, parsed, out) {
972
+ const subcommand = parsed.positional[1];
973
+ if (subcommand === "create") {
974
+ const mailboxIds = getStringList(parsed.options, "mailbox-id");
975
+ const after = getString(parsed.options, "after");
976
+ if (mailboxIds.length === 0 || !after) {
977
+ throw new CliUsageError("Provide --mailbox-id and --after.");
978
+ }
979
+ writeJson(
980
+ out,
981
+ await client.replyScans.create({
982
+ mailbox_ids: [...mailboxIds],
983
+ after,
984
+ ...getString(parsed.options, "before") ? { before: getString(parsed.options, "before") } : {}
985
+ })
986
+ );
987
+ return;
988
+ }
989
+ const scanId = requirePositional(parsed.positional, 2, "scan id");
990
+ if (subcommand === "status") {
991
+ writeJson(out, await client.replyScans.get(scanId));
992
+ return;
993
+ }
994
+ if (subcommand === "results") {
995
+ writeJson(
996
+ out,
997
+ await client.replyScans.listResults(scanId, {
998
+ ...getString(parsed.options, "cursor") ? { cursor: getString(parsed.options, "cursor") } : {},
999
+ ...getNumber(parsed.options, "limit") !== void 0 ? { limit: getNumber(parsed.options, "limit") } : {}
1000
+ })
1001
+ );
1002
+ return;
1003
+ }
1004
+ throw new CliUsageError("Unknown reply-scans command.");
1005
+ }
873
1006
  async function runMessages(client, parsed, out) {
874
1007
  const subcommand = parsed.positional[1];
875
1008
  if (subcommand === "send") {
@@ -1667,6 +1800,7 @@ async function runCli(argv, options = {}) {
1667
1800
  else if (command === "mailboxes") await runMailboxes(client, parsed, out);
1668
1801
  else if (command === "inbox") await runInbox(client, parsed, out);
1669
1802
  else if (command === "messages") await runMessages(client, parsed, out);
1803
+ else if (command === "reply-scans") await runReplyScans(client, parsed, out);
1670
1804
  else if (command === "webhooks") await runWebhooks(client, parsed, out);
1671
1805
  else if (command === "suppressions") await runSuppressions(client, parsed, out);
1672
1806
  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.2.1",
3
+ "version": "0.2.2",
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.2.2"
44
+ "shipmail": "0.2.3"
45
45
  },
46
46
  "devDependencies": {
47
47
  "tsup": "^8.4.0",