matcornic/hermes
⭐ 2,994 · Go · GitHub Repo
Golang package that generates clean, responsive HTML e-mails for sending transactional mail
awesome-go email email-template email-template-generator emails generator golang hermes
1-Sentence Summary
Go package that generates clean, responsive HTML emails from structured data, with automatic CSS inlining and plain text fallbacks.
🔥 Key Capabilities & USP
- Dual Output Generation from a Single Model: Define your email content once using a structured
Emailstruct, and Hermes produces both responsive HTML (with CSS inlined for email client compatibility) and a plain text fallback. This eliminates the need to maintain two separate templates and ensures accessibility. - Built-in Professional Themes: Ships with two polished, open-source themes ("default" and "flat") based on Postmark's Transactional Email Templates. This solves the "blank canvas" problem for developers who want beautiful, responsive emails without hiring a designer or wrestling with arcane HTML email quirks.
- Automatic CSS Inlining via Premailer: Automatically inlines all CSS styles into HTML elements, a critical step for ensuring consistent rendering across Gmail, Outlook, and Apple Mail. This removes a major pain point in email development, where external stylesheets are often stripped.
- Customizable Components with Declarative API: Supports action buttons, data tables, dictionaries (key-value lists), custom intros/outros, and RTL text direction via a simple, Go-idiomatic struct configuration. This makes complex transactional emails (receipts, password resets) trivial to generate programmatically.
- Embedded Templates for Simplified Deployment: Theme templates are compiled directly into your Go binary, meaning no external template files to manage, copy, or version in production deployments.
Technical Architecture
| Component | Details |
|---|---|
| Language | Go (Golang) |
| Core Package | Single hermes package with two primary structs: Hermes (config) and Email (content) |
| Key Methods | GenerateHTML(Email) and GeneratePlainText(Email) |
| CSS Inlining | Uses Premailer (Go port) to inline CSS for email client compatibility |
| Theming | Implements a Theme interface; ships with "default" and "flat" themes embedded via embed |
| Email Sending | Not included – generates HTML/plain text strings only; requires external SMTP client (e.g., net/smtp) |
| Import Path | github.com/matcornic/hermes (v1.3.0+) or github.com/matcornic/hermes/v2 |
Quick Start Guide
- Install the package:
go get github.com/matcornic/hermes@v1.3.0- Configure Hermes and generate an email:
package main
import (
"fmt"
"github.com/matcornic/hermes"
)
func main() {
// Configure the product/company branding
h := hermes.Hermes{
Product: hermes.Product{
Name: "Hermes",
Link: "https://example-hermes.com/",
Logo: "http://www.duchess-france.org/wp-content/uploads/2016/01/gopher.png",
},
}
// Define email content
email := hermes.Email{
Body: hermes.Body{
Name: "Jon Snow",
Intros: []string{
"Welcome to Hermes! We're very excited to have you on board.",
},
Actions: []hermes.Action{
{
Instructions: "To get started with Hermes, please click here:",
Button: hermes.Button{
Color: "#22BC66",
Text: "Confirm your account",
Link: "https://hermes-example.com/confirm?token=d9729feb74992cc3482b350163a1a010",
},
},
},
Outros: []string{
"Need help, or have questions? Just reply to this email, we'd love to help.",
},
},
}
// Generate both HTML and plain text versions
emailBody, err := h.GenerateHTML(email)
if err != nil {
panic(err)
}
emailText, err := h.GeneratePlainText(email)
if err != nil {
panic(err)
}
fmt.Println("HTML:", emailBody)
fmt.Println("Plain Text:", emailText)
}Pros, Cons & Use Cases
Pros
- Extremely simple, declarative API – no HTML/CSS knowledge needed to generate professional emails.
- One data model, two outputs – eliminates template duplication and ensures consistency.
- Automatic CSS inlining – solves the #1 compatibility issue with email clients out of the box.
- Embedded themes – zero runtime dependencies on external template files; simplifies CI/CD and containerization.
- Lightweight and focused – does one thing (email generation) and does it well, without feature bloat.
Cons
- Limited to two built-in themes – custom themes require implementing the
Themeinterface, which is more involved than simply editing an HTML file. - No built-in email sending – you must integrate with
net/smtpor an external email service (SendGrid, AWS SES) separately. - Template customization is code-driven – non-developers (e.g., marketing teams) cannot easily modify email designs without Go knowledge.
- Project appears less actively maintained – last update was May 2026, but the core functionality is stable and mature.
Who should NOT use this?
- Teams needing highly custom, brand-specific email designs – if you require pixel-perfect, unique layouts beyond the two provided themes, you'll likely need a custom solution or a more flexible templating engine.
- Non-Go projects – this is a Go-only package; Node.js users should use the original Mailgen library directly.
- Users who need built-in sending, analytics, or delivery tracking – Hermes is purely a generation tool; you'll need to layer on an email service provider.
Ideal Use Cases
- SaaS platforms & web applications needing standard transactional emails (welcome, password reset, invoice, receipt).
- Authentication systems (OAuth, SSO) that require clean, reliable email verification and notification flows.
- E-commerce backends generating order confirmations, shipping updates, and purchase receipts.
- Go microservices where you need to programmatically generate emails without managing HTML templates or CSS files.
Community & Activity
With nearly 3,000 stars on GitHub, Hermes has clearly struck a chord with the Go community. It's listed under awesome-go and is the go-to recommendation for transactional email generation in the Go ecosystem. The project is mature and stable – v1.3.0 and v2 are both available, and the core API is well-documented with examples. While the commit frequency has slowed (last update May 2026), this is a sign of a stable, feature-complete project rather than an abandoned one. For a focused utility library, that's exactly what you want: it works, it's reliable, and it doesn't need constant churn.