AskHandle Blog

How Do I Send HTML Emails with Attachments Using Mailgun in Node.js?

December 8, 2025Ben Larson3 min read

How Do I Send HTML Emails with Attachments Using Mailgun in Node.js?

Sending HTML emails with attachments through Mailgun in Node.js is a common task that many developers need to handle in their applications. This article shows you the steps and best practices to send rich HTML content emails along with file attachments using the Mailgun SDK.

Setting Up Your Project

First, you need to install the required packages. The official Mailgun SDK for Node.js is the recommended way to interact with the Mailgun API. Open your terminal and run:

bash
1npm install mailgun.js form-data

The form-data package is needed because Mailgun SDK depends on it for handling multipart form data, which is used when sending attachments.

Basic Configuration

Create a new file in your project and import the required modules. You'll need your Mailgun API key and domain name from your Mailgun dashboard:

javascript
1const formData = require('form-data');
2const Mailgun = require('mailgun.js');
3const mailgun = new Mailgun(formData);
4
5const mg = mailgun.client({
6    username: 'api',
7    key: 'your-api-key-here'
8});

Creating HTML Email Content

When sending HTML emails, it's good practice to include both HTML and plain text versions. This ensures your email is readable even if the recipient's email client doesn't support HTML:

javascript
1const htmlContent = `
2    <html>
3        <body>
4            <h1>Welcome to Our Newsletter</h1>
5            <p>This is a sample HTML email with <strong>formatted text</strong>.</p>
6        </body>
7    </html>
8`;
9
10const plainText = 'Welcome to Our Newsletter. This is a sample email with formatted text.';

Adding Attachments

You can attach files to your email using the attachment parameter. Here's how to attach files from your local system:

javascript
1const fs = require('fs');
2
3const attachmentData = {
4    data: fs.readFileSync('/path/to/file.pdf'),
5    filename: 'document.pdf'
6};

Sending the Email

Now you can combine all elements to send your HTML email with attachments:

javascript
1async function sendEmailWithAttachment() {
2    try {
3        const messageData = {
4            from: 'Your Name <sender@yourdomain.com>',
5            to: 'recipient@example.com',
6            subject: 'HTML Email with Attachment',
7            html: htmlContent,
8            text: plainText,
9            attachment: attachmentData
10        };
11
12        const response = await mg.messages.create('your-domain.com', messageData);
13        console.log('Email sent successfully:', response);
14    } catch (error) {
15        console.error('Error sending email:', error);
16    }
17}

Error Handling and Best Practices

Always implement proper error handling when sending emails. Some key points to consider:

  1. Check file sizes before attaching them. Mailgun has limits on attachment sizes.
  2. Validate email addresses before sending.
  3. Use try-catch blocks to handle potential errors gracefully.
  4. Monitor your sending rates to stay within Mailgun's limits.

Here's an example with enhanced error handling:

javascript
1function validateEmailAddress(email) {
2    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
3    return regex.test(email);
4}
5
6async function sendEmailWithValidation(recipientEmail) {
7    if (!validateEmailAddress(recipientEmail)) {
8        throw new Error('Invalid email address');
9    }
10
11    const fileStats = fs.statSync('/path/to/file.pdf');
12    const fileSizeInMB = fileStats.size / (1024 * 1024);
13    
14    if (fileSizeInMB > 25) {
15        throw new Error('File size exceeds 25MB limit');
16    }
17
18    // Proceed with sending email...
19}

Testing Your Implementation

Before sending emails to real users, test your implementation thoroughly. Mailgun provides a sandbox domain for testing purposes. Use this domain to verify that your HTML renders correctly and attachments are working as expected.

You can also set up event webhooks in your Mailgun dashboard to track email delivery status, opens, clicks, and other metrics