@emailthing/cli 0.0.0-alpha.2 → 0.0.0-alpha.4
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/dist/agent.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
import {
|
|
4
4
|
EmailThingCLI,
|
|
5
5
|
syncData
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-6p9vvb4b.js";
|
|
7
7
|
import {
|
|
8
8
|
getDB,
|
|
9
9
|
loadAuth
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-3r08bcy6.js";
|
|
11
11
|
import"./index-3t2e65zf.js";
|
|
12
12
|
|
|
13
13
|
// src/agent.ts
|
|
@@ -22,7 +22,7 @@ async function main() {
|
|
|
22
22
|
strict: !1,
|
|
23
23
|
allowNegative: !0
|
|
24
24
|
}), agentIndex = rootPositionals.findIndex((arg) => arg === "--agent" || arg === "agent"), subcmd = rootPositionals[agentIndex + 1], subcmdArgs = rootPositionals.slice(agentIndex + 2);
|
|
25
|
-
if (globalValues.help || !subcmd || !["list", "email", "sync"].includes(subcmd)) {
|
|
25
|
+
if (globalValues.help || !subcmd || !["list", "email", "mailboxes", "send", "sync"].includes(subcmd)) {
|
|
26
26
|
let nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
27
27
|
console.log(`
|
|
28
28
|
EmailThing CLI - Agent Mode
|
|
@@ -35,6 +35,8 @@ Usage:
|
|
|
35
35
|
Subcommands:
|
|
36
36
|
list List recent emails (default: 25)
|
|
37
37
|
email <id> Show full email by ID (body, etc)
|
|
38
|
+
mailboxes List mailboxes with their aliases
|
|
39
|
+
send Send an email from an alias
|
|
38
40
|
sync Force fresh sync from server
|
|
39
41
|
|
|
40
42
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
@@ -61,6 +63,19 @@ agent email <id>:
|
|
|
61
63
|
--fields=a,b,c Show only those fields
|
|
62
64
|
--sync Force sync before showing email details
|
|
63
65
|
|
|
66
|
+
agent mailboxes:
|
|
67
|
+
Lists your available mailboxes and their aliases.
|
|
68
|
+
(No options)
|
|
69
|
+
|
|
70
|
+
agent send:
|
|
71
|
+
Send an email. Reads body from stdin (e.g. pipe from echo or file).
|
|
72
|
+
--from=<alias@domain.com> Alias email you control (see \`agent mailboxes\` for valid aliases)
|
|
73
|
+
--to=<email@domain.com>... Recipient email address (multiple supported)
|
|
74
|
+
--cc=<email@domain.com>... CC Recipient email address
|
|
75
|
+
--bcc=<email@domain.com>... BCC Recipient email address
|
|
76
|
+
--subject=<text> Subject line
|
|
77
|
+
--html Treat stdin as HTML
|
|
78
|
+
|
|
64
79
|
agent sync:
|
|
65
80
|
Triggers sync with server to update local cache
|
|
66
81
|
(No other options needed)
|
|
@@ -73,6 +88,7 @@ Examples:
|
|
|
73
88
|
bunx @emailthing/cli agent list --unread --limit=10 --sync
|
|
74
89
|
bunx @emailthing/cli agent email abc123xyz789example456id --json --sync
|
|
75
90
|
bunx @emailthing/cli agent sync
|
|
91
|
+
echo "The text/plain body" | bunx @emailthing/cli agent send --from=me@myalias.com --to=friend@site.com --to=another@friend.com --subject="Hello"
|
|
76
92
|
|
|
77
93
|
Output Format:
|
|
78
94
|
List mode:
|
|
@@ -97,6 +113,10 @@ Output Format:
|
|
|
97
113
|
Body:
|
|
98
114
|
Your verification code is: 123456
|
|
99
115
|
This code expires in 10 minutes.
|
|
116
|
+
Mailboxes mode:
|
|
117
|
+
Mailbox: abcd123
|
|
118
|
+
Alias: Someone@emailthing.xyz (default) Name: My Personal Email
|
|
119
|
+
Alias: Custom@domain.com
|
|
100
120
|
`), process.exit(0);
|
|
101
121
|
}
|
|
102
122
|
let db = getDB(), client = new EmailThingCLI, auth = loadAuth(db);
|
|
@@ -353,6 +373,87 @@ ${hasMore ? `Next page: --offset=${offset + limit} --limit=${limit}` : "No more
|
|
|
353
373
|
}), db2.close();
|
|
354
374
|
return;
|
|
355
375
|
}
|
|
376
|
+
if (subcmd === "send") {
|
|
377
|
+
let values = { ...parseArgs({
|
|
378
|
+
options: {
|
|
379
|
+
from: { type: "string" },
|
|
380
|
+
to: { type: "string", multiple: !0 },
|
|
381
|
+
cc: { type: "string", multiple: !0 },
|
|
382
|
+
bcc: { type: "string", multiple: !0 },
|
|
383
|
+
subject: { type: "string" },
|
|
384
|
+
html: { type: "boolean", default: !1 }
|
|
385
|
+
},
|
|
386
|
+
allowPositionals: !0,
|
|
387
|
+
strict: !0,
|
|
388
|
+
allowNegative: !0
|
|
389
|
+
}).values };
|
|
390
|
+
if (!values.from || typeof values.from !== "string" || !values.to || !Array.isArray(values.to) || values.to.length === 0)
|
|
391
|
+
console.error(`Error: --from and --to are required.
|
|
392
|
+
Run 'bunx @emailthing/cli agent mailboxes' to see available aliases.`), process.exit(1);
|
|
393
|
+
async function readStdin() {
|
|
394
|
+
if (process.stdin.isTTY)
|
|
395
|
+
return null;
|
|
396
|
+
try {
|
|
397
|
+
return (await Bun.stdin.text()).trim() || null;
|
|
398
|
+
} catch {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
let stdin = await readStdin();
|
|
403
|
+
if (!stdin || !stdin.trim())
|
|
404
|
+
console.error("Error: No message body detected from stdin. Pipe body or use echo."), process.exit(1);
|
|
405
|
+
let db2 = getDB(), aliasRow = db2.query("SELECT mailboxId, alias FROM mailbox_aliases WHERE alias = ? AND isDeleted = 0").get(values.from);
|
|
406
|
+
if (!aliasRow)
|
|
407
|
+
console.error(`Error: Alias '${values.from}' not found or not valid for sending.
|
|
408
|
+
Run 'bunx @emailthing/cli agent mailboxes' to see your aliases.`), db2.close(), process.exit(1);
|
|
409
|
+
let mailboxId = aliasRow.mailboxId, client2 = new EmailThingCLI, auth2 = loadAuth(db2);
|
|
410
|
+
if (!auth2)
|
|
411
|
+
console.error("Error: Not authenticated. Please run the CLI first to login."), db2.close(), process.exit(1);
|
|
412
|
+
client2.setAuth(auth2.token, auth2.refreshToken, auth2.tokenExpiresAt);
|
|
413
|
+
try {
|
|
414
|
+
let to = [
|
|
415
|
+
...values.to.map((address) => ({ address, type: "to" })),
|
|
416
|
+
...(values.cc || []).map((address) => ({ address, type: "cc" })),
|
|
417
|
+
...(values.bcc || []).map((address) => ({ address, type: "bcc" }))
|
|
418
|
+
], sendResult = await client2.sendDraft({
|
|
419
|
+
mailboxId,
|
|
420
|
+
body: values.html ? void 0 : stdin,
|
|
421
|
+
html: values.html ? stdin : void 0,
|
|
422
|
+
subject: values.subject || "(no subject)",
|
|
423
|
+
from: values.from,
|
|
424
|
+
to
|
|
425
|
+
});
|
|
426
|
+
if (console.log(`Send successful! Email sent from ${values.from} to ${to.map((t) => t.type === "cc" ? `${t.address} (cc)` : t.type === "bcc" ? `${t.address} (bcc)` : t.address).join(", ")}`), console.log(sendResult), sendResult && sendResult.sync.draftSync)
|
|
427
|
+
console.log(` Email id: ${sendResult.sync.emails[0].id} (should appear as sent email shortly)`);
|
|
428
|
+
} catch (err) {
|
|
429
|
+
console.error("Email sending failed:", err?.message || err);
|
|
430
|
+
}
|
|
431
|
+
db2.close();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
if (subcmd === "mailboxes") {
|
|
435
|
+
let db2 = getDB(), client2 = new EmailThingCLI, auth2 = loadAuth(db2);
|
|
436
|
+
if (!auth2)
|
|
437
|
+
console.error("Error: Not authenticated. Please run the CLI first to login."), process.exit(1);
|
|
438
|
+
client2.setAuth(auth2.token, auth2.refreshToken, auth2.tokenExpiresAt);
|
|
439
|
+
let mailboxes = db2.query("SELECT m.id, a.alias, a.name, a.`default` FROM mailboxes m\n INNER JOIN mailbox_aliases a ON m.id = a.mailboxId\n WHERE m.isDeleted = 0 AND a.isDeleted = 0\n ORDER BY m.id, a.`default` DESC, a.alias").all();
|
|
440
|
+
if (mailboxes.length === 0) {
|
|
441
|
+
console.log("No mailboxes found."), db2.close();
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
let grouped = {};
|
|
445
|
+
mailboxes.forEach((row) => {
|
|
446
|
+
if (!grouped[row.id])
|
|
447
|
+
grouped[row.id] = [];
|
|
448
|
+
grouped[row.id].push(row);
|
|
449
|
+
}), Object.entries(grouped).forEach(([mbId, aliases]) => {
|
|
450
|
+
let mbInfo = aliases[0];
|
|
451
|
+
console.log(`Mailbox: ${mbId}`), aliases.forEach((a) => {
|
|
452
|
+
console.log(` Alias: ${a.alias}${a.default ? " (default)" : ""}${a.name ? " Name: " + a.name : ""}`);
|
|
453
|
+
}), console.log("");
|
|
454
|
+
}), db2.close();
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
356
457
|
}
|
|
357
458
|
main().catch((error) => {
|
|
358
459
|
console.error("Error:", error.message, error instanceof Error ? error.stack : error), process.exit(1);
|
|
@@ -35,6 +35,7 @@ function initDB(dbPath) {
|
|
|
35
35
|
snippet TEXT,
|
|
36
36
|
isRead BOOLEAN DEFAULT FALSE,
|
|
37
37
|
isStarred BOOLEAN DEFAULT FALSE,
|
|
38
|
+
isSender BOOLEAN DEFAULT FALSE,
|
|
38
39
|
createdAt TEXT NOT NULL,
|
|
39
40
|
headers TEXT,
|
|
40
41
|
raw TEXT,
|
|
@@ -90,11 +91,14 @@ function initDB(dbPath) {
|
|
|
90
91
|
CREATE INDEX IF NOT EXISTS idx_emails_mailbox ON emails(mailboxId);
|
|
91
92
|
CREATE INDEX IF NOT EXISTS idx_emails_created ON emails(createdAt);
|
|
92
93
|
CREATE INDEX IF NOT EXISTS idx_categories_mailbox ON categories(mailboxId);
|
|
93
|
-
`), currentVersion <
|
|
94
|
+
`), currentVersion < 2) {
|
|
94
95
|
try {
|
|
95
96
|
db.run("ALTER TABLE emails ADD COLUMN categoryId TEXT");
|
|
96
97
|
} catch (e) {}
|
|
97
|
-
|
|
98
|
+
try {
|
|
99
|
+
db.run("ALTER TABLE emails ADD COLUMN isSender BOOLEAN DEFAULT FALSE");
|
|
100
|
+
} catch (e) {}
|
|
101
|
+
db.run("PRAGMA user_version = 2");
|
|
98
102
|
}
|
|
99
103
|
return db;
|
|
100
104
|
}
|
|
@@ -76,7 +76,7 @@ class EmailThingCLI {
|
|
|
76
76
|
return res.json();
|
|
77
77
|
}
|
|
78
78
|
async sendDraft(draft) {
|
|
79
|
-
await this.refreshTokenIfNeeded();
|
|
79
|
+
await this.refreshTokenIfNeeded(), draft.draftId ||= "new";
|
|
80
80
|
let res = await this.internalFetch("/send-draft", "POST", draft);
|
|
81
81
|
if (!res.ok)
|
|
82
82
|
throw Error(`Send failed: ${await res.text()}`);
|
|
@@ -132,12 +132,12 @@ async function syncData(client, db, silent = !1) {
|
|
|
132
132
|
if (db.run("BEGIN TRANSACTION"), !silent)
|
|
133
133
|
console.error("Inserting emails...");
|
|
134
134
|
let emailStmt = db.prepare(`
|
|
135
|
-
INSERT OR REPLACE INTO emails (id, mailboxId, subject, from_addr, to_addr, cc, bcc, replyTo, body, html, snippet, isRead, isStarred, createdAt, headers, categoryId, isDeleted)
|
|
136
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
135
|
+
INSERT OR REPLACE INTO emails (id, mailboxId, subject, from_addr, to_addr, cc, bcc, replyTo, body, html, snippet, isRead, isStarred, createdAt, headers, categoryId, isDeleted, isSender)
|
|
136
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
137
137
|
`);
|
|
138
138
|
for (let email of syncData2.emails) {
|
|
139
139
|
let from = email.sender?.address || "", to = email.recipients?.[0]?.address || "", cc = email.recipients?.filter((r) => r.cc).map((r) => r.address).join(", ") || null;
|
|
140
|
-
emailStmt.run(email.id, email.mailboxId, email.subject || null, from, to, cc, email.bcc || null, email.replyTo || null, email.body || null, email.html || null, email.snippet || null, email.isRead ? !0 : !1, email.isStarred ? !0 : !1, email.createdAt, email.headers ? JSON.stringify(email.headers) : null, email.categoryId || null, email.isDeleted ? !0 : !1);
|
|
140
|
+
emailStmt.run(email.id, email.mailboxId, email.subject || null, from, to, cc, email.bcc || null, email.replyTo || null, email.body || null, email.html || null, email.snippet || null, email.isRead ? !0 : !1, email.isStarred ? !0 : !1, email.createdAt, email.headers ? JSON.stringify(email.headers) : null, email.categoryId || null, email.isDeleted ? !0 : !1, email.isSender ? !0 : !1);
|
|
141
141
|
}
|
|
142
142
|
if (!silent)
|
|
143
143
|
console.error("Inserting mailboxes...");
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
if (process.argv.includes("logout")) {
|
|
9
|
-
let { getDB, clearAuth, resetDB } = await import("./config-
|
|
9
|
+
let { getDB, clearAuth, resetDB } = await import("./config-4f9b0snt.js"), db = getDB();
|
|
10
10
|
clearAuth(db), resetDB(db), console.log("Logged out successfully. Run again to login."), db.close();
|
|
11
11
|
} else if (process.argv.includes("agent") || (process.env.CLAUDECODE || process.env.OPENCODE || process.env.AGENT) === "1")
|
|
12
12
|
await import("./agent.js");
|
package/dist/main.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
import {
|
|
4
4
|
EmailThingCLI,
|
|
5
5
|
syncData
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-6p9vvb4b.js";
|
|
7
7
|
import {
|
|
8
8
|
getDB,
|
|
9
9
|
loadAuth,
|
|
10
10
|
saveAuth
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-3r08bcy6.js";
|
|
12
12
|
import {
|
|
13
13
|
__callDispose,
|
|
14
14
|
__require,
|
|
@@ -1017,7 +1017,7 @@ async function main() {
|
|
|
1017
1017
|
case "switch": {
|
|
1018
1018
|
let newMailboxId = await mailboxSwitcher(db, route.mailboxId);
|
|
1019
1019
|
if (newMailboxId === "switch-user") {
|
|
1020
|
-
let { clearAuth, resetDB } = await import("./config-
|
|
1020
|
+
let { clearAuth, resetDB } = await import("./config-4f9b0snt.js");
|
|
1021
1021
|
return clearAuth(db), resetDB(db), main();
|
|
1022
1022
|
} else if (newMailboxId)
|
|
1023
1023
|
route = { route: "list", mailboxId: newMailboxId };
|
|
@@ -1030,7 +1030,6 @@ async function main() {
|
|
|
1030
1030
|
if (composeData)
|
|
1031
1031
|
try {
|
|
1032
1032
|
console.log("Sending email..."), await client.sendDraft({
|
|
1033
|
-
draftId: crypto.randomUUID(),
|
|
1034
1033
|
mailboxId: route.mailboxId,
|
|
1035
1034
|
body: composeData.body,
|
|
1036
1035
|
subject: composeData.subject,
|