import { describe, expect, it, vi } from "vitest";
import type { Logger } from "../src/logger.js";
import { handleSendMessage } from "../src/tools/send_message.js";
vi.mock("nodemailer", () => ({
default: {
createTransport: vi.fn(() => ({
sendMail: vi.fn().mockResolvedValue({
messageId: "test-id",
accepted: ["user@example.com"],
rejected: [],
}),
})),
},
}));
const testLogger: Logger = {
debug: () => undefined,
info: () => undefined,
warn: () => undefined,
error: () => undefined,
audit: () => undefined,
};
const baseEnv = {
MAIL_SMTP_DEFAULT_HOST: "smtp.example.com",
MAIL_SMTP_DEFAULT_USER: "user",
MAIL_SMTP_DEFAULT_PASS: "pass",
MAIL_SMTP_DEFAULT_FROM: "sender@example.com",
};
const parseResponse = (result: { content: Array<{ text: string }> }) => {
const first = result.content[0];
if (!first) {
throw new Error("Missing response content.");
}
return JSON.parse(first.text) as { summary: string };
};
describe("mail_smtp_send_message", () => {
it("permits dry_run when send gate is disabled", async () => {
const result = await handleSendMessage(
{
account_id: "default",
to: ["user@example.com"],
subject: "Hello",
text_body: "Hi",
dry_run: true,
},
baseEnv,
testLogger,
);
expect(result.isError).toBeUndefined();
});
it("rejects send when gate is disabled", async () => {
const result = await handleSendMessage(
{
account_id: "default",
to: ["user@example.com"],
subject: "Hello",
text_body: "Hi",
dry_run: false,
},
baseEnv,
testLogger,
);
const payload = parseResponse(result);
expect(result.isError).toBe(true);
expect(payload.summary).toContain("Sending is disabled");
});
it("enforces recipient allowlists", async () => {
const env = {
...baseEnv,
MAIL_SMTP_ALLOWLIST_DOMAINS: "allowed.com",
};
const result = await handleSendMessage(
{
account_id: "default",
to: ["user@blocked.com"],
subject: "Hello",
text_body: "Hi",
dry_run: true,
},
env,
testLogger,
);
const payload = parseResponse(result);
expect(result.isError).toBe(true);
expect(payload.summary).toContain("Recipient blocked");
});
it("rejects invalid base64 attachments", async () => {
const result = await handleSendMessage(
{
account_id: "default",
to: ["user@example.com"],
subject: "Hello",
text_body: "Hi",
attachments: [
{
filename: "note.txt",
content_base64: "not-base64",
},
],
dry_run: true,
},
baseEnv,
testLogger,
);
const payload = parseResponse(result);
expect(result.isError).toBe(true);
expect(payload.summary).toContain("Invalid base64");
});
});