Sending Emails with the Makerkit Prisma stack

The Prisma stack ships with a mailer system that allows you to send emails from your application. Learn how to use it to send emails.

Send emails in the Makerkit Prisma stack using getMailer() from @kit/mailers. The function returns a configured mailer instance based on your MAILER_PROVIDER environment variable. Call mailer.sendEmail({ to, from, subject, text }) for plain text or use the html property for HTML emails. Combine with React Email templates from @kit/email-templates for styled transactional emails.

This guide is part of the Email Configuration documentation.

The getMailer() function is a factory that returns the configured mailer instance (Nodemailer or Resend) based on your environment variable, abstracting away provider-specific implementation details.

  • Use text when: sending simple notifications or system alerts.
  • Use html when: sending branded transactional emails (invitations, receipts, password resets).
  • Use React Email templates when: you need maintainable, type-safe email templates with consistent styling.
  • If unsure: use React Email templates - the extra setup pays off quickly.

Understanding the Mailer class

The Mailer class is intentionally minimal:

import { z } from 'zod';
import { MailerSchema } from './schema/mailer.schema';
export abstract class Mailer<Res = unknown> {
abstract sendEmail(data: z.input<typeof MailerSchema>): Promise<Res>;
}

The sendEmail method is an abstract method that receives Zod-validated input with the following properties: to, from, subject, and either text or html.

Sending an email using the default mailer

Once you have configured the mailer provider, you can start sending emails using the sendEmail method. Here is an example of how to send an email using the default mailer:

import { getMailer } from '@kit/mailers';
async function sendEmail(params: {
from: string;
to: string;
}) {
const mailer = await getMailer();
return mailer.sendEmail({
to: params.to,
from: params.from,
subject: 'Hello',
text: 'Hello, World!'
});
}

The sendEmail method returns a promise that resolves when the email is sent successfully. If there is an error, the promise will be rejected with an error message.

Sending an HTML email

If you want to send HTML emails, you can use the html property instead of the text property:

import { getMailer } from '@kit/mailers';
async function sendEmail(params: {
from: string;
to: string;
}) {
const mailer = await getMailer();
return mailer.sendEmail({
to: params.to,
from: params.from,
subject: 'Hello',
html: '<h1>Hello, World!</h1>'
});
}

In MakerKit, we wrap all email sending in Server Actions or API routes - never call getMailer() from client components since it requires server-side environment variables.

Common Pitfalls

  • Calling getMailer on the client: The mailer requires MAILER_PROVIDER and credentials only available server-side. Always call from Server Actions, API routes, or server components.
  • Missing await on getMailer: getMailer() returns a Promise. Forgetting await causes sendEmail is not a function errors.
  • Sending both text and html: Most providers pick one. If both are provided, html takes precedence and text is ignored.
  • Hard-coding the from address: Use process.env.EMAIL_SENDER or pass it dynamically. Hard-coded addresses break when changing providers.
  • Not handling errors: sendEmail can throw. Wrap in try/catch and log failures - silent email failures are hard to debug.
  • Large HTML payloads: Some providers limit email size. Keep HTML under 100KB and use external image URLs instead of inline base64.

Frequently Asked Questions

What does the sendEmail method return?
The return type depends on the provider. Nodemailer returns message info with messageId. Resend returns { id, from, to, created_at }. The Mailer interface uses unknown to stay provider-agnostic.
Can I send attachments?
Not with the base Mailer interface. For attachments, extend the mailer or use the provider SDK directly. Both Nodemailer and Resend support attachments in their native APIs.
How do I send to multiple recipients?
Pass an array to the 'to' field: to: ['user1@example.com', 'user2@example.com']. For BCC, use the 'bcc' field which most providers support.
Why is my email not arriving?
Check: (1) Mailpit at localhost:8025 for local dev, (2) provider dashboard for send status, (3) spam folder, (4) correct EMAIL_SENDER format for your provider.
Can I use React Email with plain text emails?
Yes. React Email's render() function supports plainText option. Call render(component, { plainText: true }) to get text output instead of HTML.

Next: Email Templates →