Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/cli/commands/inbox.remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,10 @@ export function registerInboxCommands(program: Command, output: (data: unknown,
try {
const ds = resolveMailDataSource();
const msg = opts.download ? await ds.getMessage(emailId) : await requireMessage(ds, emailId);
if (!msg || (opts.download && msg.id !== emailId)) {
if (!msg) {
throw new Error("attachment message not found in the active inbox store");
}
if (opts.download && msg.id !== emailId) {
throw new Error("attachment download requires the exact full message id");
}
const fullId = msg.id;
Expand Down
29 changes: 29 additions & 0 deletions src/cli/commands/inbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,35 @@ describe("inbox attachments", () => {
// ─── inbox attachment ────────────────────────────────────────────────────────

describe("inbox attachment", () => {
it("reports an exact full message id missing from the active store as not found", async () => {
const id = crypto.randomUUID();
const dir = mkdtempSync(join(tmpdir(), "emails-cli-missing-attachment-"));
try {
const failed = await runInboxSubprocessExpectingExit([
"--json",
"inbox",
"attachment",
id,
"--download",
"--index",
"0",
"--output-dir",
dir,
]);

expect(failed.exitCode).toBe(1);
expect(failed.stdout).toBe("");
const payload = JSON.parse(failed.stderr) as {
error: { code: string; message: string };
};
expect(payload.error.code).toBe("not_found");
expect(payload.error.message).toBe("attachment message not found in the active inbox store");
expect(readdirSync(dir)).toEqual([]);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});

it("lists attachment metadata (no local paths in self-hosted mode)", async () => {
const email = seedEmail({
subject: "Has attachments",
Expand Down
Loading