import type { Endpoint, PayloadRequest } from 'payload' import { addDataAndFileToRequest } from 'payload' /** * Custom endpoint: send a test email to a given address through whatever * transport is currently active (SMTP or Graph — mailAdapter reads the panel * setting per send, so the test exercises the REAL path a form email would * take). Mounted at POST /api/ipal/test-email. * * Admin-only: uses payload.sendEmail (server-side), and requires an * authenticated admin user — a test-send button must never be open to the * public (it would be an open relay / spam vector). * * Returns the adapter's own result so the panel can show exactly what happened, * including the transport-specific error (SMTP auth failure, Graph 401, etc.). */ export const testEmailEndpoint: Endpoint = { handler: async (req: PayloadRequest) => { // Auth: only signed-in admins may trigger a send. if (!req.user) { return Response.json({ error: 'Unauthorized', ok: false }, { status: 401 }) } await addDataAndFileToRequest(req) const to = (req.data?.to as string | undefined)?.trim() if (!to || !/^[^@\s]+@[^\s@][^\s.@]*\.[^\s@]+$/.test(to)) { return Response.json( { error: 'Provide a valid recipient address.', ok: false }, { status: 400 }, ) } try { const info = await req.payload.sendEmail({ html: '
This is a test message from ipal-kit. If you received it, outbound email is configured correctly.
', subject: 'ipal-kit — test email', text: 'This is a test message from ipal-kit. If you received it, outbound email is configured correctly.', to, }) // Payload's sendEmail resolves with the adapter's result. Our adapters // return { sent: boolean, error?: string }; nodemailer returns info with // messageId. Normalize to a simple ok/message for the panel. const sent = info && typeof info === 'object' && 'sent' in info ? (info as { sent?: boolean }).sent !== false : true if (!sent) { const error = (info as { error?: string })?.error ?? 'Send failed (see server logs).' return Response.json({ error, ok: false }, { status: 502 }) } return Response.json({ message: `Test email sent to ${to}.`, ok: true }) } catch (err) { const message = err instanceof Error ? err.message : String(err) req.payload.logger.error(`[ipal] Test email failed: ${message}`) return Response.json( { error: 'Send failed. Check transport settings and server logs.', ok: false }, { status: 502 }, ) } }, method: 'post', path: '/ipal/test-email', }