feat: add custom email address for verification emails

This commit is contained in:
Marc Seitz
2025-05-03 19:23:43 +02:00
parent 21f3f8c54a
commit 2d79f00e81
5 changed files with 66 additions and 7 deletions

View File

@@ -362,7 +362,7 @@ export async function POST(request: NextRequest) {
},
});
waitUntil(sendOtpVerificationEmail(email, otpCode, true));
waitUntil(sendOtpVerificationEmail(email, otpCode, true, link.teamId!));
return NextResponse.json(
{
type: "email-verification",

View File

@@ -249,7 +249,7 @@ export async function POST(request: NextRequest) {
},
});
waitUntil(sendOtpVerificationEmail(email, otpCode));
waitUntil(sendOtpVerificationEmail(email, otpCode, false, link.teamId!));
return NextResponse.json({
type: "email-verification",
message: "Verification email sent.",

View File

@@ -7,6 +7,7 @@ import {
Heading,
Hr,
Html,
Img,
Preview,
Section,
Tailwind,
@@ -17,10 +18,12 @@ export default function OtpEmailVerification({
email = "test@example.co",
code = "123456",
isDataroom = false,
logo,
}: {
email: string;
code: string;
isDataroom: boolean;
logo?: string;
}) {
return (
<Html>
@@ -29,9 +32,21 @@ export default function OtpEmailVerification({
<Tailwind>
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Text className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Text>
<div className="mx-0 mb-8 mt-4 p-0 text-center">
{logo ? (
<Img
src={logo}
alt="Logo"
width="120"
height="36"
className="mx-auto"
/>
) : (
<Text className="text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Text>
)}
</div>
<Heading className="mx-0 my-7 p-0 text-center text-xl font-semibold text-black">
Please confirm your email address
</Heading>

View File

@@ -0,0 +1,23 @@
import { get } from "@vercel/edge-config";
export const getCustomEmail = async (teamId?: string) => {
if (!process.env.EDGE_CONFIG || !teamId) {
return null;
}
let customEmails: Record<string, string | null> = {};
try {
const result = await get("customEmail");
// Make sure we get a valid object
customEmails =
typeof result === "object" && result !== null
? (result as Record<string, string | null>)
: {};
} catch (e) {
// Error getting custom emails, return null
return null;
}
// Return the custom email for the team if it exists
return customEmails[teamId] || null;
};

View File

@@ -1,19 +1,40 @@
import OtpEmailVerification from "@/components/emails/otp-verification";
import { getCustomEmail } from "@/lib/edge-config/custom-email";
import prisma from "@/lib/prisma";
import { sendEmail } from "@/lib/resend";
import OtpEmailVerification from "@/components/emails/otp-verification";
export const sendOtpVerificationEmail = async (
email: string,
code: string,
isDataroom: boolean = false,
teamId: string,
) => {
let brand: { logo: string | null } | null = null;
let from: string | undefined;
const customEmail = await getCustomEmail(teamId);
if (customEmail && teamId) {
from = customEmail;
// Get brand logo if we have a custom email
brand = await prisma.brand.findUnique({
where: { id: teamId },
select: { logo: true },
});
}
const emailTemplate = OtpEmailVerification({
email,
code,
isDataroom,
logo: brand?.logo ?? undefined,
});
try {
await sendEmail({
from,
to: email,
subject: `One-time passcode to access the ${isDataroom ? "dataroom" : "document"}`,
react: emailTemplate,