The story about using Azure Functions to render and send emails via React Email and Resend.
The need: At Domainly.shop, our Next.js front-end was originally responsible for handling tasks like sending emails (e.g., for user sign-ups). However, to avoid burdening the web app with email rendering and delivery, we decided to offload this functionality to an Azure function.
Step-by-step:
- Create a new Azure Function.
- Add React, React Email and Resend requirements
- Create an email, render it with some props and send it on its way!
Introduction
Sending emails is a critical part of many modern web applications, whether it’s for user sign-ups, password resets, or transactional notifications. However, handling email rendering and delivery directly within your front-end application can lead to performance bottlenecks and unnecessary complexity. Us at Domainly.shop, we faced this challenge with our Next.js front-end, which was initially responsible for sending emails. To improve scalability and offload this workload, we turned to Azure Functions, a serverless compute service, combined with React Email for building dynamic email templates and Resend for reliable email delivery.
This guide walks you through the process of setting up an Azure Function to render and send emails using React Email and Resend. By the end, you’ll have a scalable, maintainable solution for handling email workflows without burdening your front-end application.
Step 1: Setting Up an Azure Function.
Create your Typescript Azure Function from the default template. For this, the easiest if you follow this Microsoft official guide. For simplicity’s sake I will use an HttpTrigger . But you may use any trigger which best fits your needs.
The initial state of our project.
Step 2: Installing Dependencies for React Email and Resend.
Now that we have our Azure Function it is time to add our dependencies for React Email and Resend by running the following commands:
npm install react-email @react-email/components resend
npm install --save-dev @types/react
Add the following scripts to your package.json
:
// These scripts will allow you to run and test your emails in dev mode.
"scripts": {
...
// Once we add our first email, npm run email will let us view our emails.
"email": "email dev -p 4001",
"export": "email export"
...
},
And finally, update your tsconfig.json
to handle .jsx
and .tsx
files.
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "node",
"esModuleInterop": true,
"resolveJsonModule": true,
"lib": ["dom", "DOM.Iterable", "esnext"],
"target": "ESNext",
"outDir": "dist",
"baseUrl": ".",
"allowJs": true,
"sourceMap": true,
"strict": true,
"jsx": "react-jsx",
"skipLibCheck": true
},
"exclude": ["node_modules", "dist"],
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"emails/**/*.ts",
"emails/**/*.tsx"
]
}
Step 3: Adding your first Email and delivering it!
3.1 Create your first email
In your project’s root folder create and emails
folder. This is where we will place our [email_name].tsx
files. For this guide, we will use a very simple email, however, feel free to bling it out after!
// From the Koala tempalte https://demo.react.email/preview/welcome/koala-welcome?view=desktop&lang=jsx
// Import necessary components from React Email
import {
Body,
Button,
Container,
Head,
Hr,
Html,
Img,
Preview,
Section,
Text,
} from "@react-email/components";
// We define some external prop our email will need to display its content
interface KoalaWelcomeEmailProps {
userFirstname: string;
}
const baseUrl = "https://yoursite.example";
export const KoalaWelcomeEmail = ({
userFirstname,
}: KoalaWelcomeEmailProps) => (
<Html>
<Head />
<Preview>
The sales intelligence platform that helps you uncover qualified leads.
</Preview>
<Body style={main}>
<Container style={container}>
<Img
src={`${baseUrl}/static/koala-logo.png`}
width="170"
height="50"
alt="Koala"
style={logo}
/>
<Text style={paragraph}>Hi {userFirstname},</Text>
<Text style={paragraph}>
Welcome to Koala, the sales intelligence platform that helps you
uncover qualified leads and close deals faster.
</Text>
<Section style={btnContainer}>
<Button style={button} href="https://getkoala.com">
Get started
</Button>
</Section>
<Text style={paragraph}>
Best,
<br />
The Koala team
</Text>
<Hr style={hr} />
<Text style={footer}>
470 Noor Ave STE B #1148, South San Francisco, CA 94080
</Text>
</Container>
</Body>
</Html>
);
KoalaWelcomeEmail.PreviewProps = {
userFirstname: "Alan",
} as KoalaWelcomeEmailProps;
export default KoalaWelcomeEmail;
const main = {
backgroundColor: "#ffffff",
fontFamily:
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
};
const container = {
margin: "0 auto",
padding: "20px 0 48px",
};
const logo = {
margin: "0 auto",
};
const paragraph = {
fontSize: "16px",
lineHeight: "26px",
};
const btnContainer = {
textAlign: "center" as const,
};
const button = {
backgroundColor: "#5F51E8",
borderRadius: "3px",
color: "#fff",
fontSize: "16px",
textDecoration: "none",
textAlign: "center" as const,
display: "block",
padding: "12px",
};
const hr = {
borderColor: "#cccccc",
margin: "20px 0",
};
const footer = {
color: "#8898aa",
fontSize: "12px",
};
3.2 Render the email
Normally, we would move our email handling into separate files so they can be nicely separated. However, for this guide’s purposes we will just put it into our function file.
Make sure to update the src/functions/httpTrigger1.ts
to src/function/httpTrigger1.tsx
since we will be dealing with React components.
First we will create the CreateEmailOptions
constant which will contain our email’s information:
import type { CreateEmailOptions } from "resend";
...
export async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
context.log(`Http function processed request for url "${request.url}"`);
const createEmailOptions: CreateEmailOptions = {
to: ['some-recipient@email.com'],
from: 'YourFrom <your-from@address.email',
subject: 'Some Test Subject',
react: <KoalaWelcomeEmail userFirstname="John" />
}
}
....
It is the react
property which will let us provide a React Component with props so that we can send that as our email.
3.3 Set up Resend
In order to be able to send an email via Resend we will need to set up the RESEND_API_KEY
environment variable in our local.settings.json
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"RESEND_API_KEY": "YOUR_KEY_HERE"
}
}
With this we can expand our code by instanciating the Resend client and sending our email!
...
const resendInstance = new Resend(process.env.RESEND_API_KEY);
try {
context.log("sending_email_via_resend", {
to: createEmailOptions.to,
});
const response = await resendInstance.emails.send(createEmailOptions);
if (response.error) {
context.error("resend_email_error", {
error: response.error.name,
message: response.error.message,
});
throw new Error(response.error.message);
}
if (response.data) {
context.log("resend_email_data", {
data: response.data,
});
return { body: `Email success with id: ${response.data.id}!` };
}
context.warn("resend_no_error_no_data");
return { body: "No error or data received" };
} catch (error) {
if (error instanceof Error) {
context.error("failed_to_send_email", {
message: error.message,
error,
});
throw error;
}
context.error("failed_to_send_email_unknown_reason", {
error,
});
throw new Error(`Unknown error: Failed to send email, ${error}`);
}
...
With this code we set up a safe email sending procedure so that we can handle and log all errors if any occurs but more importantly we can send our email!
All is left now is testing the function locally by running it (e.g., using tools like Postman or curl) and deploying it to Azure (e.g., using the Azure CLI or Visual Studio Code).
Conclusion
By leveraging React Email, Resend, and Azure Functions, this guide demonstrates how to efficiently offload email rendering and sending from your front-end application to a serverless architecture. This approach not only improves the scalability and performance of your web app but also simplifies the process of creating dynamic, reusable email templates using React.
The combination of React Email for building templates, Resend for email delivery, and Azure Functions for serverless execution offers several key benefits:
- Scalability: Offloading email tasks to Azure Functions ensures your front-end remains responsive, even during high traffic.
- Maintainability: Using React components for email templates allows for better organization, reusability, and consistency in your email designs.
- Error Handling: The guide provides a robust error-handling mechanism, ensuring that issues are logged and managed effectively.
- Flexibility: The serverless nature of Azure Functions allows you to trigger email workflows from various sources, such as HTTP requests, timers, or other Azure services.
To take this further, you can expand the solution by adding more email templates, integrating with other triggers (e.g., database changes or event queues), or optimizing the deployment process for production environments. Testing locally and deploying to Azure are critical steps to ensure the solution works seamlessly in real-world scenarios.
By following this guide, you can build a scalable, maintainable, and efficient email-sending workflow that enhances your application’s overall performance and user experience.
Top comments (0)