Quick Guide: Using MailAPI.dev in Next.js
Use the official mailapidev NPM package to send emails, use templates, and manage contacts with Next.js Server Actions.
Setup & Configuration
Follow these two steps to get started in your Next.js 14 project.
Step 1: Install the Package
Install the official Node.js package from NPM.
npm install mailapidevStep 2: Set Your Environment Variable
Get your API key from your MailAPI dashboard and add it to your .env.local file.
MAILAPI_KEY=mapi_your_api_key_hereCreate Your Server Actions
Create a file at src/actions/emailAction.js. This file will securely handle all communication with the MailAPI server.
// src/actions/emailAction.js
"use server";
import { MailApiDev } from "mailapidev";
// Initialize the client once. It automatically reads process.env.MAILAPI_KEY.
const mailapi = new MailApiDev(process.env.MAILAPI_KEY);
/**
* Sends an email using the mailapidev package.
*/
export const sendEmailWithMailAPI = async (emailData) => {
try {
// Pass the payload directly. The API and package will handle validation.
const { data, error } = await mailapi.emails.send(emailData);
if (error) {
console.error("MailAPI error:", error);
return { success: false, error: error.message, code: error.code };
}
console.log("MailAPI success:", data);
return { success: true, data: data };
} catch (error) {
console.error("Email sending error:", error);
return {
success: false,
error: error.message || "Failed to send email",
};
}
};
/**
* Updates a contact using the mailapidev package.
*/
export const updateMailApiList = async (userData) => {
try {
// Pass the payload directly. The API and package will handle validation.
const { data, error } = await mailapi.emails.update(userData);
if (error) {
console.error("MailAPI update error:", error);
return {
success: false,
error: error.message || "Failed to update contact",
code: error.code || "update_failed",
};
}
console.log("MailAPI update success:", data);
return {
success: true,
message: data.message || "Contact updated successfully",
data: data.data,
action: data.action,
};
} catch (error) {
console.error("Update contact error:", error);
return {
success: false,
error: error.message || "Failed to update contact",
code: "update_failed",
};
}
};Usage Examples
Now you can import these actions into any "use client" component to send emails.
Example 1: Basic Contact Form
This component sends a basic email. It also displays the success or error message returned from the API.
// app/components/Contact.jsx
"use client";
import { useState } from "react";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { sendEmailWithMailAPI } from "@/actions/emailActions";
export default function Contact() {
const [email, setEmail] = useState("");
const [subject, setSubject] = useState("");
const [message, setMessage] = useState("");
const [status, setStatus] = useState("");
const [apiMessage, setApiMessage] = useState("");
const handleInputFocus = () => {
setStatus("");
setApiMessage("");
};
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("sending");
setApiMessage("");
const res = await sendEmailWithMailAPI({
from: "Contact Form <noreply@mail.mailapi.dev>", // Remember to verify this 'from' email
to: email,
subject,
message,
});
if (res.success) {
setStatus("success");
setApiMessage(res.data?.message || "Email sent successfully!");
setEmail("");
setSubject("");
setMessage("");
} else {
setStatus("error");
setApiMessage(res.error || "Failed to send email.");
}
};
return (
<div className="w-full max-w-md bg-white shadow-lg rounded-2xl p-6">
<h3 className="text-xl font-semibold text-gray-900 mb-4 text-center">
Contact Us
</h3>
<form onSubmit={handleSubmit} className="space-y-4">
<Input
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
onFocus={handleInputFocus}
required
/>
<Input
type="text"
placeholder="Subject"
value={subject}
onChange={(e) => setSubject(e.target.value)}
onFocus={handleInputFocus}
required
/>
<Textarea
placeholder="Type your message..."
value={message}
onChange={(e) => setMessage(e.target.value)}
onFocus={handleInputFocus}
required
/>
<Button type="submit" disabled={status === "sending"} className="w-full">
{status === "sending" ? "Sending..." : "Send Message"}
</Button>
{apiMessage && (
<p className={`text-sm text-center mt-2 ${status === "success" ? "text-green-600" : "text-red-600"}`}>
{status === "success" ? "✅" : "❌"} {apiMessage}
</p>
)}
</form>
</div>
);
}Example 2: Send from a Template
This example sends an email using a template ID (e.g., "welcome") and passes `templateData`.
First go to your mailapi dashboard to create a template. Then get the template id and template data variables.
// app/components/EmailTemplate.jsx
"use client";
import { useState } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { sendEmailWithMailAPI } from "@/actions/emailActions";
export default function EmailTemplate() {
const [email, setEmail] = useState("");
const [subject, setSubject] = useState("Welcome!");
const [status, setStatus] = useState("");
const [apiMessage, setApiMessage] = useState("");
const handleInputFocus = () => {
setStatus("");
setApiMessage("");
};
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("sending");
setApiMessage("");
const res = await sendEmailWithMailAPI({
from: "MailAPI <noreply@mail.mailapi.dev>",
to: email,
subject: subject,
template_id: "welcome", // Your template ID from the dashboard
template_data: {
url: "https://app.mailapi.dev/login",
name: "John Doe",
},
verify_and_save: true, // Automatically add to contact list
});
if (res.success) {
setStatus("success");
setApiMessage(res.data?.message || "Welcome email sent!");
setEmail("");
setSubject("Welcome!");
} else {
setStatus("error");
setApiMessage(res.error || "Failed to send email.");
}
};
return (
<div className="w-full max-w-md bg-white shadow-lg rounded-2xl p-6">
<h3 className="text-xl font-semibold text-gray-900 mb-4 text-center">
Send Template Email
</h3>
<form onSubmit={handleSubmit} className="space-y-4">
<Input
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
onFocus={handleInputFocus}
required
/>
<Input
type="text"
placeholder="Subject"
value={subject}
onChange={(e) => setSubject(e.target.value)}
onFocus={handleInputFocus}
required
/>
<Button type="submit" disabled={status === "sending"} className="w-full">
{status === "sending" ? "Sending..." : "Send Welcome Email"}
</Button>
{apiMessage && (
<p className={`text-sm text-center mt-2 ${status === "success" ? "text-green-600" : "text-red-600"}`}>
{status === "success" ? "✅" : "❌"} {apiMessage}
</p>
)}
</form>
</div>
);
}How to Update a Contact
You can call the updateMailApiList action from any server-side function, such as a Stripe webhook, a user login handler, or another Server Action.
Update User Session
import { updateMailApiList } from "@/actions/emailActions";
// Example: Use the function to update an email list data
const updateUserSession = async (userEmail) => {
const res = await updateMailApiList({
email: userEmail,
lastSeenAt: new Date().toISOString()
});
if (res.error) {
console.error("Failed to update contact:", res.error);
// Handle failure (e.g., log to your own monitoring)
} else {
console.log("Contact updated!", res.data);
}
}Update User Subscription - Created
import { updateMailApiList } from "@/actions/emailActions";
// Example: Use the function to update an email list data
const updateUserSubscription = async (userEmail) => {
const res = await updateMailApiList({
email: userEmail,
subscriptionStatus: "active",
plan: {
id: "price_1234567890",
name: "Pro",
amount: 20,
interval: "month"
},
convertedAt: new Date().toISOString()
});
if (res.error) {
console.error("Failed to update contact:", res.error);
// Handle failure (e.g., log to your own monitoring)
} else {
console.log("Contact updated!", res.data);
}
}Update User Subscription - Churn
import { updateMailApiList } from "@/actions/emailActions";
// Example: Use the function to update an email list data
const updateUserSubscription = async (userEmail) => {
const res = await updateMailApiList({
email: userEmail,
subscriptionStatus: "canceled",
lastSeenAt: new Date().toISOString(),
churnedAt: new Date().toISOString(),
"churnReason": "Too expensive"
});
if (res.error) {
console.error("Failed to update contact:", res.error);
// Handle failure (e.g., log to your own monitoring)
} else {
console.log("Contact updated!", res.data);
}
}Conclusion
That's it! You have successfully integrated the mailapidev package into your Next.js application. You can now send powerful transactional emails and manage your contact list with just a few lines of code.
For more advanced features like email verification and automation, check out the full MailAPI.dev Documentation.