Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | 30x 28x 25x 24x 29x 30x 30x 30x 1x 29x 29x 29x 30x 30x 29x 29x 28x 28x 29x 7x 6x 3x 2x 1x 1x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 26x 30x 3x 3x | import type {
AdapterResult,
CommunicationQueueMessage,
EmailContent,
} from "../types";
function getProviderName(env: CloudflareBindings): string {
if (env.MAILTRAP_API_TOKEN) return "mailtrap";
if (env.RESEND_API_KEY) return "resend";
if (env.MAILPIT_HOST) return "mailpit";
return "mock";
}
function shouldStorePreview(env: CloudflareBindings): boolean {
return (env.ENVIRONMENT ?? "local") !== "production";
}
export class EmailAdapter {
async send(
message: CommunicationQueueMessage,
env: CloudflareBindings,
): Promise<AdapterResult> {
const provider = getProviderName(env);
const { recipient, content } = message;
// Skip delivery for phone-signup placeholder emails (not real addresses)
if (recipient.endsWith("@phone.interioring.com")) {
return {
status: "sent",
actualRecipient: recipient,
provider: "skipped_placeholder",
};
}
const emailContent = content as EmailContent;
const { template, props, recipientName } = emailContent;
const recipientName_ = recipientName ?? "";
let previewHtml: string | undefined;
try {
// Loaded lazily: ../../email pulls @react-email/render (prettier,
// html-to-text, entities, react). Evaluating that at module scope costs
// startup CPU on every cold isolate, and this adapter only runs when the
// communication queue delivers an email.
const { createEmailService, renderEmailTemplate } = await import(
"../../email"
);
const emailService = createEmailService(env);
let result: { id: string | null; count?: number } | undefined;
if (shouldStorePreview(env)) {
const preview = await renderEmailTemplate({
template,
props,
recipientName: recipientName_,
});
previewHtml = preview.html;
}
switch (template) {
case "new-inquiry":
result = await emailService.sendNewInquiry(
[{ email: recipient, name: recipientName_ }],
props as Parameters<typeof emailService.sendNewInquiry>[1],
);
break;
case "password-reset":
result = await emailService.sendPasswordReset(
recipient,
props.resetLink as string,
props.userName as string | undefined,
);
break;
case "email-verification":
result = await emailService.sendEmailVerification(
recipient,
props.verificationLink as string,
props.userName as string | undefined,
);
break;
case "welcome":
result = await emailService.sendWelcome(
recipient,
props.userName as string,
props.loginUrl as string | undefined,
);
break;
case "team-invitation":
result = await emailService.sendTeamInvitation(
recipient,
props as Parameters<typeof emailService.sendTeamInvitation>[1],
);
break;
case "blog-approval-request":
result = await emailService.sendBlogApprovalRequest(
recipient,
props as Parameters<typeof emailService.sendBlogApprovalRequest>[1],
);
break;
case "blog-approval-reminder":
result = await emailService.sendBlogApprovalReminder(
recipient,
props as Parameters<
typeof emailService.sendBlogApprovalReminder
>[1],
);
break;
case "blog-published":
result = await emailService.sendBlogPublished(
[{ email: recipient, name: recipientName_ }],
props as Parameters<typeof emailService.sendBlogPublished>[1],
);
break;
case "email-verified":
result = await emailService.sendEmailVerified(
message.recipient,
emailContent.props as Parameters<
typeof emailService.sendEmailVerified
>[1],
);
break;
case "pro-account-status":
result = await emailService.sendProAccountStatus(
[
{
email: message.recipient,
name: emailContent.recipientName ?? "",
},
],
emailContent.props as Parameters<
typeof emailService.sendProAccountStatus
>[1],
);
break;
case "website-build-result":
result = await emailService.sendWebsiteBuildResult(
[
{
email: message.recipient,
name: emailContent.recipientName ?? "",
},
],
emailContent.props as Parameters<
typeof emailService.sendWebsiteBuildResult
>[1],
);
break;
case "import-result":
result = await emailService.sendImportResult(
[
{
email: message.recipient,
name: emailContent.recipientName ?? "",
},
],
emailContent.props as Parameters<
typeof emailService.sendImportResult
>[1],
);
break;
case "reminder-due":
result = await emailService.sendReminderDue(
recipient,
props as Parameters<typeof emailService.sendReminderDue>[1],
);
break;
case "magic-link":
result = await emailService.sendMagicLink(
recipient,
props as { magicLinkUrl: string },
);
break;
case "email-otp":
result = await emailService.sendOtpCode(
recipient,
props.code as string,
props.userName as string | undefined,
);
break;
default:
throw new Error(`Unknown email template: ${template}`);
}
const externalId = result?.id ?? undefined;
return {
status: "sent",
actualRecipient: recipient,
provider,
externalId: externalId ?? undefined,
previewHtml,
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
return {
status: "failed",
actualRecipient: recipient,
provider,
previewHtml,
errorMessage,
};
}
}
}
|