• Blog
  • Documentation
  • Courses
  • Changelog
  • AI Starters
  • UI Kit
  • FAQ
  • Supamode
    New
  • Pricing

Launch your next SaaS in record time with Makerkit, a React SaaS Boilerplate for Next.js and Supabase.

Makerkit is a product of Makerkit Pte Ltd (registered in the Republic of Singapore)Company Registration No: 202407149CFor support or inquiries, please contact us

About
  • FAQ
  • Contact
  • Verify your Discord
  • Consultation
  • Open Source
  • Become an Affiliate
Product
  • Documentation
  • Blog
  • Changelog
  • UI Blocks
  • Figma UI Kit
  • AI SaaS Starters
License
  • Activate License
  • Upgrade License
  • Invite Member
Legal
  • Terms of License
    • Email Configuration
    • Sending Emails
    • Email Templates
    • Authentication Emails
    • Local Development
    • Custom Mailer

Creating a Custom Mailer in the Next.js Supabase Starter Kit

Learn how to create a custom mailer in the Next.js Supabase Starter Kit, so you can send emails using your own email provider.

Steps to create a custom mailer

Learn how to create a custom mailer in the Next.js Supabase Starter Kit, so you can send emails using your own email provider.

1

Implementing the sendEmail method

2

Registering the Mailer

3

Setting a new Mailer Provider

4

Moving Megamailer to a separate package

Makerkit implements both Nodemailer (which can potentially support any SMTP provider) and Resend, using its HTTP API, which allows Makerkit to be compatible with edge runtimes (such as Cloudflare Workers).

However, if you want to use your own email provider, you can create a custom mailer using the packages/mailers package.

The mailer class is very simple:

tsx
export abstract class Mailer<Res = unknown> {
abstract sendEmail(data: z.infer<typeof MailerSchema>): Promise<Res>;
}

As such, you can create your own mailer by extending the Mailer class and implementing the sendEmail method.

Implementing the sendEmail method

The sendEmail method takes in a z.infer<typeof MailerSchema> object, which is a Zod schema that defines the shape of the email data. This allows you to validate the email data before sending it.

Here's an example of how to implement the sendEmail method. For simplicity, we will call our custom mailer megamailer in the following examples.

packages/mailers/core/src/megamailer.ts
import { z } from 'zod';
import { MailerSchema } from '../../shared/src/schema/mailer.schema';
export function createMegaMailer() {
return new MegaMailer();
}
class MegaMailer implements Mailer<unknown> {
async sendEmail(data: z.infer<typeof MailerSchema>) {
// Implement your email sending logic here
// For example, you can use Nodemailer to send emails
// or use a third-party email provider like SendGrid
return {};
}
}

NB: for simplicity, we've placed the megamailer.ts file in the core package. However, if you have 5 minutes, you can move it to a separate package and import it in the index.ts file, just like we do for Nodemailer and Resend.

Registering the Mailer

Now that we have our custom mailer, we need to register it in the packages/mailers/core/src/registry.ts file:

packages/mailers/core/src/registry.ts
import { Mailer } from '@kit/mailers-shared';
import { createRegistry } from '@kit/shared/registry';
import { MailerProvider } from './provider-enum';
const mailerRegistry = createRegistry<Mailer, MailerProvider>();
// here we add our custom mailer to the registry
mailerRegistry.register('megamailer', async () => {
const { createMegaMailer } = await import('@kit/megamailer');
return createMegaMailer();
});
mailerRegistry.register('nodemailer', async () => {
if (process.env.NEXT_RUNTIME === 'nodejs') {
const { createNodemailerService } = await import('@kit/nodemailer');
return createNodemailerService();
} else {
throw new Error(
'Nodemailer is not available on the edge runtime. Please use another mailer.',
);
}
});
mailerRegistry.register('resend', async () => {
const { createResendMailer } = await import('@kit/resend');
return createResendMailer();
});
export { mailerRegistry };

Setting a new Mailer Provider

By setting the MAILER_PROVIDER environment variable to megamailer, you can use the Megamailer mailer in your application.

text
MAILER_PROVIDER=megamailer

Moving Megamailer to a separate package

Let's move the Megamailer to a separate package. To do so, we create a new package called @kit/megamailer and move the megamailer.ts file to the new package.

Let's create a package at packages/mailers/megamailer.

  1. Copy both the package.json and tsconfig.json files from the resend package to the new package and rename the package to @kit/megamailer
  2. Copy the megamailer.ts file to the new package
  3. Update the index.ts file to export the new package and use the Megamailer

Install the Megamailer package

To install the new package, run the following command:

text
pnpm i "@kit/megamailer:workspace:*" --filter "@kit/mailers"

Update the Mailer Registry

Now that we have the new package, we need to update the registry.ts file to export the new package and use the Megamailer.

packages/mailers/core/src/registry.ts
// here we add our custom mailer to the registry
mailerRegistry.register('megamailer', async () => {
const { createMegaMailer } = await import('@kit/megamailer');
return createMegaMailer();
});
On this page
  1. Implementing the sendEmail method
    1. Registering the Mailer
      1. Setting a new Mailer Provider
        1. Moving Megamailer to a separate package