Emails

Send transactional emails with Mailgun integration.

shipsaas includes a ready-to-use email sender powered by Mailgun via lib/email.ts. Email settings are configured in lib/config.ts.

Setup

1. Create Mailgun Account

  1. Sign up at app.mailgun.com
  2. Verify your domain or use the sandbox domain for testing
  3. Go to Settings → API Security
  4. Copy your API key

2. Install Dependencies

npm install mailgun.js form-data

3. Configure Environment

.env.local
MAILGUN_API_KEY=your-mailgun-api-key

4. Configure Email Settings

Update the mailgun section in lib/config.ts:

lib/config.ts
// lib/config.ts → mailgun section
mailgun: {
  subdomain: "mg",
  fromNoReply: "YourApp <noreply@mg.yourapp.com>",
  fromAdmin: "YourApp <admin@mg.yourapp.com>",
  supportEmail: "support@yourapp.com",
  forwardRepliesTo: "support@yourapp.com",
},

Email Sender

The email sender is in lib/email.ts. It lazily loads the Mailgun client and reads configuration from config:

lib/email.ts

Mailgun email sender with sendEmail function and lazy client initialization.

View Source

sendEmail Function

import { sendEmail } from "@/lib/email";

// Send a simple email
await sendEmail({
  to: "user@example.com",
  subject: "Welcome!",
  html: "<h1>Hello!</h1><p>Welcome to our app.</p>",
});

// With plain text fallback and reply-to
await sendEmail({
  to: "user@example.com",
  subject: "Your receipt",
  html: "<h1>Payment received</h1>",
  text: "Payment received — thank you!",
  replyTo: "support@yourapp.com",
});

Email Templates

Welcome Email

lib/email-templates.ts
export function getWelcomeEmail(userName: string) {
  return `
    <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
      <div style="background: linear-gradient(135deg, #667eea, #764ba2); padding: 30px; border-radius: 10px 10px 0 0; text-align: center;">
        <h1 style="color: white; margin: 0;">Welcome!</h1>
      </div>
      <div style="background: #f9fafb; padding: 30px; border-radius: 0 0 10px 10px;">
        <p>Hi <strong>${userName}</strong>,</p>
        <p>Thanks for joining! Get started by exploring your dashboard.</p>
        <a href="https://yourapp.com/dashboard"
           style="background: #667eea; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block;">
          Get Started
        </a>
      </div>
    </div>
  `;
}

Payment Confirmation

export function getPaymentEmail(amount: number, planName: string) {
  return `
    <h2>Payment Successful!</h2>
    <p>Thank you for your payment of <strong>$${amount}</strong>.</p>
    <p>Your <strong>${planName}</strong> plan is now active.</p>
  `;
}

Best Practices

  • Use descriptive subject lines — Clear and actionable
  • Include plain text fallback — Pass both html and text to sendEmail
  • Test with sandbox domain — Mailgun provides a free sandbox for development
  • Handle errors gracefully — The sender logs warnings if Mailgun is not configured

Development tip: If MAILGUN_API_KEY is missing, the app will log a warning but won't crash — emails simply won't be sent.

Ready to send emails! Start engaging with your users through transactional emails and notifications.