Files
ipal-kit/src/modules/email/test/testEmailEndpoint.ts
T

69 lines
2.6 KiB
TypeScript

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: '<p>This is a test message from <strong>ipal-kit</strong>. If you received it, outbound email is configured correctly.</p>',
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',
}