mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-06-07 08:30:51 +08:00
* feat: add STARTTLS support for SMTP proxy server Add smtp_tls_cert and smtp_tls_key environment variables to enable STARTTLS on the SMTP proxy server, matching existing IMAP TLS support. Closes #249 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add E2E tests for SMTP/IMAP STARTTLS - Add smtp-proxy-tls service with self-signed certs in docker-compose - Add smtp-tls.spec.ts: SMTP STARTTLS send plain/HTML/auth tests - Add imap-tls.spec.ts: IMAP STARTTLS login/list/select/fetch tests - Register smtp-proxy project in playwright.config.ts - Wait for TLS proxy readiness in docker-entrypoint.sh Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: enforce auth over TLS when STARTTLS is configured - Set auth_require_tls conditionally based on tls_context presence - Disable insecure SSLv2/SSLv3 protocols in TLS context Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace cert-gen service with inline cert generation The cert-gen one-shot container was exiting immediately after generating certificates, triggering --abort-on-container-exit and stopping all services before tests could run. Replace with an entrypoint script in smtp-proxy-tls that generates the self-signed cert before starting the proxy server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import nodemailer from 'nodemailer';
|
|
import {
|
|
createTestAddress,
|
|
deleteAddress,
|
|
deleteAllMailpitMessages,
|
|
requestSendAccess,
|
|
onMailpitMessage,
|
|
} from '../../fixtures/test-helpers';
|
|
|
|
const TLS_HOST = process.env.SMTP_PROXY_TLS_HOST || 'smtp-proxy-tls';
|
|
const TLS_SMTP_PORT = parseInt(process.env.SMTP_PROXY_TLS_SMTP_PORT || '8026', 10);
|
|
|
|
function createTlsTransport(user: string, pass: string) {
|
|
return nodemailer.createTransport({
|
|
host: TLS_HOST,
|
|
port: TLS_SMTP_PORT,
|
|
secure: false,
|
|
auth: { user, pass },
|
|
tls: { rejectUnauthorized: false },
|
|
requireTLS: true,
|
|
});
|
|
}
|
|
|
|
function createNoTlsTransport(user: string, pass: string) {
|
|
return nodemailer.createTransport({
|
|
host: TLS_HOST,
|
|
port: TLS_SMTP_PORT,
|
|
secure: false,
|
|
auth: { user, pass },
|
|
tls: { rejectUnauthorized: false },
|
|
});
|
|
}
|
|
|
|
test.describe('SMTP Proxy — STARTTLS', () => {
|
|
let jwt: string;
|
|
let address: string;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await deleteAllMailpitMessages(request);
|
|
({ jwt, address } = await createTestAddress(request, 'smtp-tls'));
|
|
await requestSendAccess(request, jwt);
|
|
});
|
|
|
|
test.afterAll(async ({ request }) => {
|
|
await deleteAddress(request, jwt);
|
|
});
|
|
|
|
test('send plain text email via STARTTLS', async () => {
|
|
const subject = `SMTP TLS Plain ${Date.now()}`;
|
|
const listener = onMailpitMessage((m) => m.Subject === subject);
|
|
await listener.ready;
|
|
|
|
const transport = createTlsTransport(address, jwt);
|
|
const info = await transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject,
|
|
text: 'Hello from SMTP STARTTLS 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 STARTTLS', async () => {
|
|
const subject = `SMTP TLS HTML ${Date.now()}`;
|
|
const listener = onMailpitMessage((m) => m.Subject === subject);
|
|
await listener.ready;
|
|
|
|
const transport = createTlsTransport(address, jwt);
|
|
const info = await transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject,
|
|
html: '<h1>Hello</h1><p>STARTTLS HTML E2E test</p>',
|
|
});
|
|
expect(info.accepted).toContain('recipient@test.example.com');
|
|
|
|
const delivered = await listener.message;
|
|
expect(delivered.Subject).toBe(subject);
|
|
});
|
|
|
|
test('connection without STARTTLS still works', async () => {
|
|
const subject = `SMTP TLS NoForce ${Date.now()}`;
|
|
const listener = onMailpitMessage((m) => m.Subject === subject);
|
|
await listener.ready;
|
|
|
|
const transport = createNoTlsTransport(address, jwt);
|
|
const info = await transport.sendMail({
|
|
from: address,
|
|
to: 'recipient@test.example.com',
|
|
subject,
|
|
text: 'Hello without forced STARTTLS',
|
|
});
|
|
expect(info.accepted).toContain('recipient@test.example.com');
|
|
|
|
const delivered = await listener.message;
|
|
expect(delivered.Subject).toBe(subject);
|
|
});
|
|
|
|
test('auth with wrong password fails over STARTTLS', async () => {
|
|
const transport = createTlsTransport(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();
|
|
});
|
|
});
|