Arawa Mail Arawa MailDocs

Next.js Quickstart

Send email through the Arawa Mail HTTP API with the sdp-email-nextjs npm package. It is a zero-dependency, TypeScript-first client for Next.js server components, route handlers, and server actions — and any Node.js 18+ app.

Server-side only Your API key must never reach the browser. Use the package in server components, route handlers, server actions, or API routes — never in client components.

Before You Begin

  1. Add and verify your sending domain in Arawa Mail.
  2. Enable outbound sending for the domain.
  3. Create an API key with the sending scope.

The from address must use that enabled domain. A domain-restricted API key must also allow the sender's domain.

1. Install the Package

npm install sdp-email-nextjs

2. Configure the API Key

Add your Arawa Mail API key to .env.local:

SDP_EMAIL_KEY=your_api_key

3. Send an Email

import { SdpEmail } from 'sdp-email-nextjs';

const sdp = new SdpEmail(); // reads SDP_EMAIL_KEY from the environment

const { data, error } = await sdp.emails.send({
    from: 'Acme <[email protected]>',
    to: '[email protected]',
    subject: 'Hello from Next.js',
    html: '<p>Sent through Arawa Mail.</p>',
});

if (error) {
    console.error(error.name, error.message);
} else {
    console.log('Sent:', data.id);
}

In a Server Action

'use server';

import { SdpEmail } from 'sdp-email-nextjs';

const sdp = new SdpEmail();

export async function sendContactMessage(formData: FormData) {
    const { error } = await sdp.emails.send({
        from: 'Website <[email protected]>',
        to: '[email protected]',
        reply_to: String(formData.get('email')),
        subject: 'New contact message',
        text: String(formData.get('message')),
    });

    return { ok: !error };
}

In a Route Handler

// app/api/send/route.ts
import { NextResponse } from 'next/server';
import { SdpEmail } from 'sdp-email-nextjs';

const sdp = new SdpEmail();

export async function POST(request: Request) {
    const body = await request.json();

    const { data, error } = await sdp.emails.send({
        from: 'Acme <[email protected]>',
        to: body.to,
        subject: body.subject,
        html: body.html,
    });

    if (error) {
        return NextResponse.json(error, { status: error.statusCode || 500 });
    }

    return NextResponse.json(data);
}

Attachments

Attachment contents are base64-encoded:

import { readFile } from 'node:fs/promises';

await sdp.emails.send({
    from: 'Acme <[email protected]>',
    to: '[email protected]',
    subject: 'Your invoice',
    text: 'Invoice attached.',
    attachments: [
        {
            filename: 'invoice.pdf',
            content: (await readFile('invoice.pdf')).toString('base64'),
            content_type: 'application/pdf',
        },
    ],
});

Error Handling

Methods never throw on API errors. They return { data, error }:

const { data, error } = await sdp.emails.send(payload);

if (error) {
    // { statusCode: 401, message: 'Invalid API key', name: 'invalid_api_key' }
}

Network failures and timeouts return an error with statusCode: 0 and name: 'application_error'.

Optional Connection Settings

The package uses the production endpoint and a 10-second timeout by default:

const sdp = new SdpEmail('your_api_key', {
    baseUrl: 'https://app.arawamail.com', // or SDP_EMAIL_ENDPOINT env var
    timeout: 10_000, // milliseconds
});

Troubleshooting

Sending is rejected when the sender's domain is not registered, outbound sending is inactive, the API key lacks the sending scope, or a restricted key does not allow the sender's domain.