# mailgen: transactional HTML email assembled from a JavaScript object

> A Node package that turns a plain data structure into responsive table based email HTML, with a plaintext fallback and four contributed themes, but no transport of its own.

**eladnava/mailgen** — A Node.js package that generates clean, responsive HTML e-mails for sending transactional mail.

- Repository: https://github.com/eladnava/mailgen
- Stars: 2,540 · Forks: 120
- Language: HTML
- License: Apache-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/eladnava-mailgen

## Installing the package and naming your product

mailgen installs as an ordinary npm dependency and takes about a minute to reach a first render. The README's first step is a single install command, and the package is published to the public registry as `mailgen` at version 2.0.36 under an Apache 2.0 licence.

```bash
npm install mailgen --save
```

The second step configures the generator once, at module load, with a theme name and the product details that appear in the header and footer of every message:

```javascript
var Mailgen = require('mailgen');

// Configure mailgen by setting a theme and your product info
var mailGenerator = new Mailgen({
    theme: 'default',
    product: {
        // Appears in header & footer of e-mails
        name: 'Mailgen',
        link: 'https://mailgen.js/'
        // Optional product logo
        // logo: 'https://mailgen.js/img/logo.png'
    }
});
```

Two details in that snippet matter more than they look. The theme is chosen per instance rather than per message, so an application that sends two visually different kinds of email constructs two generators and keeps both around. And the product block is the only place your company name, link and logo live, which means changing the footer in one place changes it for every template. The logo is commented out in the README, so an unconfigured instance renders the text name and link instead of an image.

## Writing an email as data instead of a template string

The design decision that separates mailgen from a folder of hand written HTML is that a message is an object. Nothing is concatenated, no placeholder tokens are substituted, and the shape of a welcome email is the same shape as the shape of a password reset email. You build the object, hand it to `generate`, and get HTML back as a string.

```javascript
var email = {
    body: {
        name: 'John Appleseed',
        intro: 'Welcome to Mailgen! We\'re very excited to have you on board.',
        action: {
            instructions: 'To get started with Mailgen, please click here:',
            button: {
                color: '#22BC66', // Optional action button color
                text: 'Confirm your account',
                link: 'https://mailgen.js/confirm?s=d9729feb74992cc3482b350163a1a010'
            }
        }
    }
};
```

Because the input is data, the same call works for content that came out of a database. A receipt can be built with a table element, a password reset with a single action button, and both go through the same generator. The README also points at three worked examples in `examples/`: a welcome message, a receipt and a password reset. Those files are the fastest way to see which element belongs in which kind of transactional mail, and they are worth reading before you write your first object from scratch.

The elements the templates understand include action buttons, tables and dictionaries, which covers the three recurring shapes of transactional mail: do something, here is a list of rows, here is a set of key and value pairs.

## Generating a plaintext sibling next to the HTML

Every HTML email has a second obligation that most hand rolled templates skip. mailgen addresses it with a second method on the same object, and it costs one line:

```javascript
var emailBody = mailGenerator.generate(email);

// Generate the plaintext version of the e-mail (for clients that do not support HTML)
var emailText = mailGenerator.generatePlaintext(email);

// Optionally, preview the generated HTML e-mail by writing it to a local file
require('fs').writeFileSync('preview.html', emailBody, 'utf8');
```

The plaintext output is not a strip tags version of the HTML. It is generated from the same object by a separate path, which is why the button text and link survive in a client that ignores styling entirely. Sending both parts from the same object is the reason the README calls this package a generator rather than a template tool.

The `writeFileSync` line is a development convenience and worth keeping in a scratch script. Rendering a message to `preview.html` and opening it in a browser is the fastest review loop available, and it is what the example scripts are set up for. What the package does not do is send anything. The README is explicit that delivery is your problem and points at Nodemailer for it, which is the arrangement most teams end up with anyway: mailgen for the body, a transport for the envelope, SMTP credentials and bounce handling somewhere in your own infrastructure.

## Four themes contributed from other projects

Themes are directories under `themes/`, selected by string name, and the bundled set is credited to other template projects rather than written for mailgen: `default` comes from the Postmark Transactional Email Templates, `neopolitan` from Send With Us, `salted` from Jason Rodriguez, and `cerberus` from Ted Goas. Each one ships with screenshots of a welcome, a reset and a receipt message in `screenshots/`, so you can compare the same three email types across all four before choosing.

This is a real strength and it is also the thing to understand about the project's shape. mailgen does not try to be the best looking transactional template. It is a rendering layer over templates that other people maintain, which means you are choosing a look, not building one. Switching themes is a one word change in the constructor, and the README's own screenshots were produced with `salted`.

If none of the four fit, `THEME.md` is the file to read next. It holds the instructions for supplying a custom theme or contributing a new built in one, and it is the only documentation in the repository beyond the README. That is also the honest boundary of what this project is: the README teaches you to configure and call the generator, and `THEME.md` teaches you how the templates are organised. Anything more elaborate than that, such as a plain HTML template of your own design, means reading the theme directory structure directly.

## Direction, logo sizing and the strings you can replace

The localisation surface is small and concrete, which suits an email package. Text direction is a constructor option, so a Hebrew or Arabic deployment gets right to left markup without a fork:

```javascript
var mailGenerator = new Mailgen({
    theme: 'salted',
    // Custom text direction
    textDirection: 'rtl',
});
```

Logo height is likewise a numeric option next to the logo URL, which is useful because the default size rarely suits every brand:

```javascript
var mailGenerator = new Mailgen({
    product: {
        // Custom product logo URL
        logo: 'https://mailgen.js/img/logo.png',
        // Custom logo height
        logoHeight: '30px'
    }
});
```

Greeting, signature and copyright are all overridable, and the README shows three separate mechanisms for the greeting alone: supply `greeting` with a custom word, pass `title` when you would rather not greet by name, or pass `false` to drop both the greeting and the signature entirely. Long `intro` and `outro` fields accept an array of strings when one sentence is not enough. Copyright lives in the `product` block at construction time, and because it is built from `new Date().getFullYear()` there, it stays current without anyone editing a template.

## What the dependency list tells you about the output

There are no published releases to read and no test suite to read either, since the `test` script in `package.json` exits immediately with an error placeholder. The dependency list is more informative than either. mailgen at 2.0.36 depends on `ejs` for templating, `he` for HTML entity encoding, and `juice` for inlining CSS into the style attributes email clients will actually honour.

That last one explains the library's whole reason to exist. Email clients strip external stylesheets, so a stylesheet based design has to be processed at render time into per element inline styles, and `juice` is the library that does that job. It is also why output from mailgen is heavy: a responsive table layout with inlined styles produces a document far larger than the source object, and that size is a factor when you are sending to large lists or strict mobile clients.

TypeScript users get declarations from the same package. `package.json` points `types` at `index.d.ts`, and the entry points are `index.js` for the runtime and that declaration file for the compiler, with `jsconfig.json` sitting alongside them. The repository is not archived and its default branch is `master`, with 2540 stars, 120 forks and 2 open issues, and the last push landed on 2026-08-04.

## Conclusion

mailgen is at its best when a product sends the same handful of transactional messages over and over and somebody on the team is willing to own the visual result. It gives you responsive markup, a plaintext sibling you can hand to any transport, four themes you can switch between, and enough documented hooks to cover right to left languages, custom logos and replacement greeting text. It sends nothing itself, so you still pick a transport and still test in real clients. The project sits at version 2.0.36 on the master branch with a last push on 2026-08-04 and an Apache 2.0 licence, so the surface you depend on is not likely to move under you. Start with the default theme and one welcome message, then read THEME.md before you try to fork the templates.

## FAQ

### What is mailgen?

mailgen is a Node.js package that generates clean, responsive HTML emails for transactional mail. You describe a message as a JavaScript object, pick a theme, and the package returns an HTML body plus a plaintext version for clients that cannot render HTML. It does not send anything: the README points at Nodemailer for delivery.

### Does mailgen send emails, or only build them?

Only builds them. The two useful calls are `generate(email)` for the HTML body and `generatePlaintext(email)` for the text alternative, and both hand you a string. Sending is left to a transport such as Nodemailer, which is what the README suggests after showing the output of a first render.

### Which themes ship with mailgen and can I add my own?

Four are bundled: `default` from the Postmark templates, `neopolitan` from Send With Us, `salted` and `cerberus`. You choose one by name in the constructor, and for anything else the repository points at THEME.md, which documents supplying a custom theme or contributing a new built in one.

### How do I make mailgen output plain text instead of HTML?

Call `generatePlaintext()` on the same generator with the same email object. It is a separate rendering path rather than a tag stripped version of the HTML, so button text and links survive for clients that ignore styling. Send it as the text part alongside the generated HTML body.

## Sources

- [eladnava/mailgen on GitHub](https://github.com/eladnava/mailgen)
- [Issues](https://github.com/eladnava/mailgen/issues)
- [License: Apache-2.0](https://github.com/eladnava/mailgen/blob/master/LICENSE)
- [README](https://github.com/eladnava/mailgen/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/eladnava-mailgen
