DEV Community

Cover image for Receive Emails in Next.js with Hisend (the painless way)
Thore
Thore

Posted on • Originally published at hisend.app

Receive Emails in Next.js with Hisend (the painless way)

Let’s be honest: Sending emails via API is a solved problem. But receiving them? That’s usually an absolute nightmare.

Most email providers give you a webhook that forces you to parse raw multipart/alternative data, or they make you chain three separate API requests just to get the email body, the sender's name, and a download link for the attachments.

I got so frustrated with this terrible Developer Experience that I built Hisend (@hisend/sdk). It’s an EU-hosted email relay that gives you the entire parsed email—including sender details and attachments—in one clean webhook payload (or a single API fetch).

Here is how you can set up incoming emails in a Next.js App Router project in less than 5 minutes.


Step 1: Set up the Domain & Routing in the Hisend Panel

Before our Next.js app can receive anything, we need to tell Hisend to listen for incoming emails and where to forward them.

  1. Register & Add Domain: Go to hisend.app, create a project, and add your domain (e.g., yourdomain.com).
  2. Configure DNS (MX Records): To receive emails, Hisend needs to be your mail server. Copy the generated MX records from the Hisend dashboard and add them to your DNS provider.
  3. Create an Endpoint: In the Hisend panel, go to Webhooks/Endpoints. Create a new endpoint pointing to your Next.js app (e.g., https://yourdomain.com/api/webhooks/hisend).
  4. Create a Routing Rule: Now, tell Hisend which emails should be sent to this endpoint. Create a rule like: Catch-all (*@yourdomain.com) -> Route to your newly created endpoint.

Step 2: Install the Hisend SDK

We need the SDK not just for sending, but because it provides the exact TypeScript definitions for the incoming webhook payload. This gives you full autocomplete in your editor.

Open your terminal and run:

npm install @hisend/sdk
# or yarn add @hisend/sdk
# or pnpm add @hisend/sdk
# or bun add @hisend/sdk
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Next.js Webhook Route

Now, let's create the route that receives the POST request from Hisend whenever an email arrives.

Create a new file under app/api/webhooks/hisend/route.ts:

import { NextResponse } from 'next/server';
import { HisendEmailEvent } from '@hisend/sdk'; // Import the specific type!

export async function POST(request: Request) {
  try {
    // 1. Get the payload from the incoming POST request
    const body = await request.json();

    // 2. Cast it directly to the Hisend Email Type for full TypeScript support
    // Since this endpoint only receives emails, no type checking is needed!
    const emailData = body as HisendEmailEvent;

    // 🎉 Look at this DX! Everything is already parsed and ready to use.
    console.log(`New email from: ${emailData.sender.name} (${emailData.sender.email})`);
    console.log(`Subject: ${emailData.subject}`);
    console.log(`Text Body: ${emailData.textBody}`); // Or emailData.htmlBody

    // Attachments are already an array, no extra API calls needed!
    if (emailData.attachments && emailData.attachments.length > 0) {
      emailData.attachments.forEach(attachment => {
        console.log(`Found attachment: ${attachment.filename} (${attachment.size} bytes)`);
        // The file data/URL is right here depending on your Hisend setup
      });
    }

    // Do whatever you want with the data: save to DB, trigger a Slack alert, etc.
    // await db.messages.insert({ ... })

    // 3. Always return a 200 OK so Hisend knows you received the webhook
    return NextResponse.json({ success: true }, { status: 200 });

  } catch (error) {
    console.error('Webhook processing failed:', error);
    // Return 500 so Hisend can retry sending the webhook later
    return NextResponse.json(
      { success: false, error: 'Internal Server Error' },
      { status: 500 }
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

Why this is better than the standard approach

If you've built incoming email parsing before, you know how much code we just skipped.

With Hisend:

  1. No Chaining Requests: You don't have to extract an ID from the webhook, authenticate against the API, fetch the email body, and then make a third request to fetch the attachment URLs. It's all right there in the event.data payload.
  2. Native Threading: The payload automatically includes clean thread IDs, so you can group replies into conversations (like a helpdesk ticket) without manually parsing the messy References or In-Reply-To headers.
  3. EU Data Privacy (GDPR): All emails are received, processed, and temporarily stored on bare metal servers in Germany (Hetzner) and AWS Frankfurt. We don't ship your users' emails to the US.

Ready to fix your email DX? Check out the docs and create your free account at hisend.app.

Top comments (0)