Repository navigation
Conversation
Upstream hardcodes dub.co sender addresses which Resend rejects for non-dub.co deployments. Read from EMAIL_FROM_PRIMARY, EMAIL_FROM_NOTIFICATIONS, EMAIL_FROM_MARKETING, and EMAIL_REPLY_TO env vars with dub.co values as fallbacks.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Ok @VinneyJ ..this is better and this fixes the sender configuration, but please also address the existing false-success bug. Its actually this bug that made figuring out this issue a bit hard becoz it showed success in the UI Currently, return await sendEmail({
subject: "You've been invited to join a workspace on Dub",
to: email,
react: WorkspaceInvite({
email,
url,
workspaceName: workspace.name,
workspaceUser: session?.user.name || null,
workspaceUserEmail: session?.user.email || null,
}),
});The [endpoint only checks whether promises were rejected]( dub/apps/web/app/api/workspaces/[idOrSlug]/invites/route.ts Lines 155 to 166 in dec1dca if (results.some((result) => result.status === "rejected")) {Resend can instead resolve with return NextResponse.json({ message: "Invite(s) sent" });Suggested change: capture the const response = await sendEmail({
// Keep the existing email options above.
});
if (!response || ("error" in response && response.error)) {
return {
success: false as const,
email,
message: "Invitation saved, but its email could not be sent.",
};
}
return { success: true as const, email };Then have the endpoint check both rejected promises and returned failures: const failedEmails = results.flatMap((result, index) => {
if (result.status === "rejected") return [teammates[index].email];
if (!result.value.success) return [result.value.email];
return [];
});
if (failedEmails.length > 0) {
return NextResponse.json(
{
error: {
code: "internal_server_error",
message:
`Could not send invitations to: ${failedEmails.join(", ")}. ` +
"Check pending invitations before retrying.",
},
},
{ status: 500 },
);
}
return NextResponse.json({ message: "Invite(s) sent" });Please add tests for Resend returning an error, a rejected send, and a mixed batch. These should never return “Invite(s) sent” for the whole batch. |
Resend resolves with { data: null, error: {...} } on failure rather
than rejecting. The endpoint only checked for rejected promises so it
returned success even when email delivery failed. Now checks both
rejected promises and resolved error responses, returning 500 with
the affected addresses when any invite email fails.
|
Minimum tests to add:
|
|
@VinneyJ Seen the tests but they are still missing the crucial parts Coverage is still incomplete:
|
Summary
Email sending was broken because upstream hardcodes
system@dub.coas the sender address, which Resend rejects for non-dub.co deployments.fromaddresses (primary,notifications,marketing) configurable via env vars, falling back to the upstream dub.co valuesreplyTofallback configurable viaEMAIL_REPLY_TOenv varEnv vars to set in Vercel
EMAIL_FROM_PRIMARYCode for Africa <system@mail.codeforafrica.org>EMAIL_FROM_NOTIFICATIONSCode for Africa <notifications@mail.codeforafrica.org>EMAIL_FROM_MARKETINGCode for Africa <hello@mail.codeforafrica.org>EMAIL_REPLY_TOsupport@codeforafrica.orgValues must use a domain verified in your Resend account.
Files changed
packages/email/src/resend/constants.tspackages/email/src/send-via-resend.tsCloses CodeForAfrica/infrastructure-as-code#133
Supersedes #97