74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import {
|
|
defineMail,
|
|
defineMailTemplate,
|
|
defineSealedMailCredentials,
|
|
mailSandboxDecision,
|
|
sealedMailDriver,
|
|
} from "../src/index.ts";
|
|
|
|
test("mail templates render and sandbox blocks accidental recipients", async () => {
|
|
const sent: unknown[] = [];
|
|
const mail = defineMail({
|
|
from: "hello@example.com",
|
|
sandbox: { enabled: true, allowlist: ["dev@example.com"] },
|
|
driver: { send: async (message) => void sent.push(message) },
|
|
});
|
|
const welcome = defineMailTemplate<{ name: string }>({
|
|
subject: ({ name }) => `Hello ${name}`,
|
|
html: ({ name }) => `<b>${name}</b>`,
|
|
});
|
|
await mail.send(await mail.render(welcome, { name: "Ada" }, "dev@example.com"));
|
|
expect(sent).toHaveLength(1);
|
|
await expect(mail.send({ to: "real@example.com", subject: "no" })).rejects.toThrow("SANDBOX");
|
|
});
|
|
|
|
test("mail owns fail-closed sandbox decisions and sealed credential setup", async () => {
|
|
expect(
|
|
mailSandboxDecision({ enabled: 1, allowlist: '["Test@Example.com"]' }, "test@example.com"),
|
|
).toEqual({ allowed: true });
|
|
expect(
|
|
mailSandboxDecision({ enabled: true, allowlist: "not-json" }, "x@example.com").allowed,
|
|
).toBe(false);
|
|
const previous = process.env.TEST_MAIL_ENCRYPTION_KEY;
|
|
process.env.TEST_MAIL_ENCRYPTION_KEY = btoa(String.fromCharCode(...new Uint8Array(32).fill(7)));
|
|
try {
|
|
const credentials = defineSealedMailCredentials({ env: "TEST_MAIL_ENCRYPTION_KEY" });
|
|
const sealed = await credentials.seal("smtp-secret");
|
|
expect(sealed).not.toContain("smtp-secret");
|
|
expect(await credentials.open(sealed)).toBe("smtp-secret");
|
|
} finally {
|
|
if (previous === undefined) delete process.env.TEST_MAIL_ENCRYPTION_KEY;
|
|
else process.env.TEST_MAIL_ENCRYPTION_KEY = previous;
|
|
}
|
|
});
|
|
|
|
test("sealed drivers decrypt lazily once and delegate send/test", async () => {
|
|
let opens = 0;
|
|
const sent: string[] = [];
|
|
const driver = sealedMailDriver({
|
|
sealedCredential: "ciphertext",
|
|
async unseal(value) {
|
|
opens++;
|
|
expect(value).toBe("ciphertext");
|
|
return "plaintext-secret";
|
|
},
|
|
create(credential) {
|
|
expect(credential).toBe("plaintext-secret");
|
|
return {
|
|
async send(message) {
|
|
sent.push(message.subject);
|
|
},
|
|
async test() {
|
|
return { ok: true };
|
|
},
|
|
};
|
|
},
|
|
});
|
|
expect(opens).toBe(0);
|
|
await driver.send({ to: "safe@example.test", subject: "one" });
|
|
expect(await driver.test?.()).toEqual({ ok: true });
|
|
expect(opens).toBe(1);
|
|
expect(sent).toEqual(["one"]);
|
|
});
|