Files
CapaKraken/packages/api/src/__tests__/email-runtime-config-hardening.test.ts
T

118 lines
2.9 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import nodemailer from "nodemailer";
import { logger } from "../lib/logger.js";
import { testSmtpConnection } from "../lib/email.js";
const { findUnique, verify, createTransport } = vi.hoisted(() => {
const verify = vi.fn();
return {
findUnique: vi.fn(),
verify,
createTransport: vi.fn(() => ({
verify,
sendMail: vi.fn(),
})),
};
});
vi.mock("@capakraken/db", () => ({
prisma: {
systemSettings: {
findUnique,
},
},
}));
vi.mock("nodemailer", () => ({
default: {
createTransport,
},
}));
vi.mock("../lib/logger.js", () => ({
logger: {
error: vi.fn(),
warn: vi.fn(),
info: vi.fn(),
debug: vi.fn(),
},
}));
describe("email runtime config hardening", () => {
beforeEach(() => {
vi.clearAllMocks();
findUnique.mockResolvedValue({
smtpHost: "smtp.secret.internal",
smtpPort: 587,
smtpUser: "alice@example.com",
smtpPassword: "super-secret",
smtpTls: true,
});
});
afterEach(() => {
vi.unstubAllEnvs();
});
it("returns a classified SMTP auth error without leaking diagnostics", async () => {
verify.mockRejectedValueOnce(
new Error("Invalid login for alice@example.com against smtp.secret.internal"),
);
const result = await testSmtpConnection();
expect(result).toEqual({
ok: false,
error: "SMTP authentication failed — check username and password.",
});
expect(nodemailer.createTransport).toHaveBeenCalledWith({
host: "smtp.secret.internal",
port: 587,
secure: true,
auth: {
user: "alice@example.com",
pass: "super-secret",
},
});
expect(logger.warn).toHaveBeenCalledWith(
expect.objectContaining({
diagnostic: expect.any(String),
}),
"SMTP connection test failed",
);
const diagnostic = vi.mocked(logger.warn).mock.calls[0]?.[0];
expect(JSON.stringify(diagnostic)).toContain("<redacted-email>");
expect(JSON.stringify(diagnostic)).toContain("<redacted-host>");
expect(JSON.stringify(diagnostic)).not.toContain("alice@example.com");
expect(JSON.stringify(diagnostic)).not.toContain("smtp.secret.internal");
});
it("prefers SMTP_PASSWORD from the environment at runtime", async () => {
vi.stubEnv("SMTP_PASSWORD", "env-smtp-password");
findUnique.mockResolvedValue({
smtpHost: "smtp.secret.internal",
smtpPort: 587,
smtpUser: "alice@example.com",
smtpPassword: "db-password",
smtpTls: true,
});
verify.mockResolvedValueOnce(true);
const result = await testSmtpConnection();
expect(result).toEqual({ ok: true });
expect(nodemailer.createTransport).toHaveBeenCalledWith({
host: "smtp.secret.internal",
port: 587,
secure: true,
auth: {
user: "alice@example.com",
pass: "env-smtp-password",
},
});
});
});