1// Async (non-Effect) Worker that exercises a native `send_email` binding
2// against the local simulator. Referenced by path only (never value-imported
3// by the test) so the top-level `cloudflare:email` import is evaluated
4// exclusively inside workerd.
5import { EmailMessage } from "cloudflare:email";
6
7interface SendEmailLike {
8 send(message: unknown): Promise<{ messageId: string }>;
9}
10
11type Env = { EMAIL: SendEmailLike };
12
13export default {
14 fetch: async (request: Request, env: Env) => {
15 const url = new URL(request.url);
16 try {
17 if (url.pathname === "/send-raw") {
18 // EmailMessage API: raw MIME message carrying a per-run marker the
19 // test greps for in the persisted `.eml`.
20 const marker = url.searchParams.get("marker") ?? "no-marker";
21 const raw = [
22 "From: sender <sender@example.com>",
23 "To: recipient <allowed@example.com>",
24 `Message-ID: <${marker}@example.com>`,
25 "MIME-Version: 1.0",
26 "Content-Type: text/plain",
27 "",
28 `marker:${marker}`,
29 ].join("\r\n");
30 const result = await env.EMAIL.send(
31 new EmailMessage("sender@example.com", "allowed@example.com", raw),
32 );
33 return Response.json({ ok: true, messageId: result.messageId });
34 }
35 if (url.pathname === "/send-builder") {
36 // MessageBuilder API: destination from the query string so the test
37 // can exercise both the allowed and the disallowed address.
38 const to = url.searchParams.get("to") ?? "allowed@example.com";
39 const result = await env.EMAIL.send({
40 from: "sender@example.com",
41 to,
42 subject: "local send_email test",
43 text: "hello from the local simulator",
44 });
45 return Response.json({ ok: true, messageId: result.messageId });
46 }
47 return new Response("ok");
48 } catch (e) {
49 return Response.json(
50 { ok: false, message: e instanceof Error ? e.message : String(e) },
51 { status: 500 },
52 );
53 }
54 },
55};