mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-05-11 18:10:01 +08:00
refactor: modularize IMAP server with fixes and E2E tests - Modularize IMAP server into imap_server, imap_mailbox, imap_message, imap_http_client, parse_email, config, models - Support dual login: JWT token and address+password via backend - Add STARTTLS support with configurable TLS cert/key - Fix FETCH/STORE returning UID instead of sequence number (RFC 3501) - Implement IMessageFile.open() for correct BODY[] raw MIME delivery - Add UIDNEXT to SELECT response via _cbSelectWork override - Use per-restart UIDVALIDITY to force client resync - Pass raw MIME to SimpleMessage for accurate RFC822.SIZE - Fix SENT mailbox returning empty source - Handle CREATE command gracefully for Thunderbird compatibility - Add IMAP E2E tests: auth, LIST, SELECT, STATUS, FETCH, SEARCH, STORE, UID FETCH, BODY[] integrity, size, seq numbers, SENT mailbox - Add SMTP E2E tests using nodemailer: send plain/HTML, auth failure, sendbox verification - Add sendTestMail helper using admin/send_mail Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
3.3 KiB
TypeScript
113 lines
3.3 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import nodemailer from 'nodemailer';
|
|
import {
|
|
createTestAddress,
|
|
deleteAddress,
|
|
deleteAllMailpitMessages,
|
|
requestSendAccess,
|
|
onMailpitMessage,
|
|
WORKER_URL,
|
|
} from '../../fixtures/test-helpers';
|
|
|
|
const SMTP_HOST = process.env.SMTP_PROXY_HOST || 'smtp-proxy';
|
|
const SMTP_PORT = parseInt(process.env.SMTP_PROXY_SMTP_PORT || '8025', 10);
|
|
|
|
function createTransport(user: string, pass: string) {
|
|
return nodemailer.createTransport({
|
|
host: SMTP_HOST,
|
|
port: SMTP_PORT,
|
|
secure: false,
|
|
auth: { user, pass },
|
|
tls: { rejectUnauthorized: false },
|
|
});
|
|
}
|
|
|
|
test.describe('SMTP Proxy', () => {
|
|
let jwt: string;
|
|
let address: string;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await deleteAllMailpitMessages(request);
|
|
({ jwt, address } = await createTestAddress(request, 'smtp-e2e'));
|
|
await requestSendAccess(request, jwt);
|
|
});
|
|
|
|
test.afterAll(async ({ request }) => {
|
|
await deleteAddress(request, jwt);
|
|
});
|
|
|
|
test('send plain text email via SMTP', async ({ request }) => {
|
|
const subject = `SMTP Plain ${Date.now()}`;
|
|
const listener = onMailpitMessage((m) => m.Subject === subject);
|
|
await listener.ready;
|
|
|
|
const transport = createTransport(address, jwt);
|
|
const info = await transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject,
|
|
text: 'Hello from SMTP E2E test',
|
|
});
|
|
expect(info.accepted).toContain('recipient@test.example.com');
|
|
|
|
const delivered = await listener.message;
|
|
expect(delivered.Subject).toBe(subject);
|
|
});
|
|
|
|
test('send HTML email via SMTP', async ({ request }) => {
|
|
const subject = `SMTP HTML ${Date.now()}`;
|
|
const listener = onMailpitMessage((m) => m.Subject === subject);
|
|
await listener.ready;
|
|
|
|
const transport = createTransport(address, jwt);
|
|
const info = await transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject,
|
|
html: '<h1>Hello</h1><p>HTML E2E test</p>',
|
|
});
|
|
expect(info.accepted).toContain('recipient@test.example.com');
|
|
|
|
const delivered = await listener.message;
|
|
expect(delivered.Subject).toBe(subject);
|
|
});
|
|
|
|
test('auth with wrong password fails', async () => {
|
|
const transport = createTransport(address, 'wrong-password');
|
|
await expect(
|
|
transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject: 'Should fail',
|
|
text: 'This should not be sent',
|
|
})
|
|
).rejects.toThrow();
|
|
});
|
|
|
|
test('sent mail appears in sendbox API', async ({ request }) => {
|
|
const subject = `SMTP Sendbox ${Date.now()}`;
|
|
const listener = onMailpitMessage((m) => m.Subject === subject);
|
|
await listener.ready;
|
|
|
|
const transport = createTransport(address, jwt);
|
|
await transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject,
|
|
text: 'Check sendbox',
|
|
});
|
|
await listener.message;
|
|
|
|
const res = await request.get(`${WORKER_URL}/api/sendbox?limit=10&offset=0`, {
|
|
headers: { Authorization: `Bearer ${jwt}` },
|
|
});
|
|
expect(res.ok()).toBe(true);
|
|
const { results } = await res.json();
|
|
const found = results.some((r: any) => {
|
|
const raw = JSON.parse(r.raw);
|
|
return raw.subject === subject;
|
|
});
|
|
expect(found).toBe(true);
|
|
});
|
|
});
|