Skip to content

lib-x/mailingo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mailingo

A powerful and flexible Go library for generating beautiful, multi-language email templates with built-in internationalization (i18n) support. Inspired by Hermes, Mailingo makes it easy to create professional HTML and plain text emails.

Features

  • Multi-language Support: Built-in i18n using go-i18n
  • Beautiful Themes: Pre-built themes (Default, Flat) with custom theme support
  • HTML & Plain Text: Generate both HTML and plain text versions of emails
  • Rich Content: Support for tables, dictionaries, action buttons, and more
  • Embedded Resources: Works seamlessly with Go's embed package
  • Easy to Use: Simple, intuitive API for creating professional emails
  • Customizable: Full control over colors, styling, and content
  • Type-Safe: Strong typing with comprehensive documentation

Installation

go get github.com/lib-x/mailingo

Quick Start

package main

import (
    "fmt"
    "log"

    "github.com/lib-x/mailingo"
)

func main() {
    // Define your product information
    product := mailingo.Product{
        Name:      "Acme Corporation",
        Link:      "https://acme.com",
        Logo:      "https://acme.com/logo.png",
        Copyright: "© 2025 Acme Corporation. All rights reserved.",
    }

    // Create a new mailer with a theme
    mailer := mailingo.New(product, mailingo.DefaultTheme)

    // Create an email
    email := mailingo.Email{
        Body: mailingo.Body{
            Name:     "John Doe",
            Greeting: "Hello",
            Title:    "Welcome to Acme!",
            Intros: []string{
                "Thank you for signing up!",
                "We're excited to have you on board.",
            },
            Actions: []mailingo.Action{
                {
                    Instructions: "Click the button below to get started:",
                    Button: mailingo.Button{
                        Text: "Get Started",
                        Link: "https://acme.com/get-started",
                    },
                },
            },
            Outros: []string{
                "Need help? Just reply to this email.",
            },
            Signature: "Best regards",
        },
    }

    // Generate HTML email
    html, err := mailer.GenerateHTML(email, "en")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(html)
}

Internationalization (i18n)

Mailingo has powerful built-in support for multiple languages:

1. Create Translation Files

Create JSON files for each language (e.g., locales/en.json, locales/zh.json):

en.json:

{
  "greeting": "Hello",
  "signature": "Best regards",
  "email.welcome.title": "Welcome!",
  "email.welcome.intro": "Thank you for signing up!"
}

zh.json:

{
  "greeting": "您好",
  "signature": "此致敬礼",
  "email.welcome.title": "欢迎!",
  "email.welcome.intro": "感谢您的注册!"
}

2. Load Translations

// Load from files
mailer.LoadMessageFile("locales/en.json")
mailer.LoadMessageFile("locales/zh.json")

// Or use embedded files
//go:embed locales/*.json
var localesFS embed.FS

mailer.LoadMessageFileFS(localesFS, "locales/en.json")
mailer.LoadMessageFileFS(localesFS, "locales/zh.json")

3. Use Translation Keys in Emails

email := mailingo.Email{
    Body: mailingo.Body{
        Name:     "Alice",
        Greeting: "greeting",           // Will be translated
        Title:    "email.welcome.title", // Will be translated
        Intros: []string{
            "email.welcome.intro",       // Will be translated
        },
        Signature: "signature",          // Will be translated
    },
}

// Generate in different languages
htmlEN, _ := mailer.GenerateHTML(email, "en")
htmlZH, _ := mailer.GenerateHTML(email, "zh")

Themes

Mailingo comes with two pre-built themes:

Default Theme

mailer := mailingo.New(product, mailingo.DefaultTheme)

Flat Theme

mailer := mailingo.New(product, mailingo.FlatTheme)

Custom Theme

customTheme := mailingo.Theme{
    PrimaryColor:    "#FF6B35",
    BackgroundColor: "#F7F7F7",
    TextColor:       "#333333",
    ButtonColor:     "#FF6B35",
    ButtonTextColor: "#FFFFFF",
}

mailer := mailingo.New(product, customTheme)

Template Customization

Mailingo provides three ways to customize the email template to match your brand and requirements.

1. Custom CSS

Add your own CSS to override or extend the default template styles:

import "github.com/lib-x/mailingo/options"

customCSS := `
    /* Override default styles */
    .email-title {
        font-size: 32px;
        font-weight: 900;
        text-transform: uppercase;
    }

    /* Add rounded buttons */
    .email-button {
        border-radius: 25px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }

    /* Custom gradient for dictionary section */
    .email-dictionary {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
    }
`

mailer := mailingo.New(
    product,
    mailingo.DefaultTheme,
    options.WithCustomCSS(customCSS),
)

2. Custom Template String

Provide your own complete HTML template:

minimalistTemplate := `
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        body {
            font-family: 'Helvetica Neue', Arial, sans-serif;
            background-color: #f5f5f5;
            padding: 40px;
        }
        .container {
            max-width: 500px;
            margin: 0 auto;
            background: white;
            padding: 40px;
            border-radius: 8px;
        }
        h1 {
            color: #333;
            border-bottom: 2px solid {{.Theme.PrimaryColor}};
        }
        .button {
            background: {{.Theme.ButtonColor}};
            color: white;
            padding: 12px 30px;
            text-decoration: none;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>{{.Body.Title}}</h1>
        <p>Hi {{.Body.Name}},</p>
        {{range .Body.Intros}}
        <p>{{.}}</p>
        {{end}}
        {{range .Body.Actions}}
        <a href="{{.Button.Link}}" class="button">{{.Button.Text}}</a>
        {{end}}
        <div class="footer">
            {{.Product.Copyright}}
        </div>
    </div>
</body>
</html>
`

mailer := mailingo.New(
    product,
    mailingo.DefaultTheme,
    options.WithCustomTemplateString(minimalistTemplate),
)

3. Custom Template from Embedded FS

Use a template file from your embedded filesystem:

//go:embed templates/custom.html
var templatesFS embed.FS

mailer := mailingo.New(
    product,
    mailingo.DefaultTheme,
    options.WithCustomTemplateFS(templatesFS, "templates/custom.html"),
)

Template Variables

When creating custom templates, you have access to these template variables:

{{.Product.Name}}      // Product name
{{.Product.Link}}      // Product URL
{{.Product.Logo}}      // Logo URL
{{.Product.Copyright}} // Copyright text

{{.Theme.PrimaryColor}}    // Primary color
{{.Theme.BackgroundColor}} // Background color
{{.Theme.TextColor}}       // Text color
{{.Theme.ButtonColor}}     // Button color
{{.Theme.ButtonTextColor}} // Button text color

{{.CustomCSS}}             // Custom CSS (if provided)

{{.Body.Name}}             // Recipient name
{{.Body.Greeting}}         // Greeting text
{{.Body.Title}}            // Email title
{{.Body.Signature}}        // Signature text
{{.Body.Intros}}           // Array of intro paragraphs
{{.Body.Outros}}           // Array of outro paragraphs
{{.Body.Dictionary}}       // Array of Entry (Key/Value pairs)
{{.Body.Table.Data}}       // 2D array of table data
{{.Body.Actions}}          // Array of actions (Instructions, Button, InvertedButton)
{{.Body.Attachments}}      // Array of attachments (Name, URL, Size, Type)

Combining Customizations

You can combine custom CSS with custom themes for maximum flexibility:

customTheme := mailingo.Theme{
    PrimaryColor:    "#FF6B6B",
    BackgroundColor: "#FFF5F5",
    TextColor:       "#2C3E50",
    ButtonColor:     "#FF6B6B",
    ButtonTextColor: "#FFFFFF",
}

customCSS := `
    .email-body {
        background: linear-gradient(to bottom, #ffffff 0%, #f8f9fa 100%);
    }
    .email-greeting {
        font-size: 20px;
        font-style: italic;
    }
`

mailer := mailingo.New(
    product,
    customTheme,
    options.WithCustomCSS(customCSS),
)

See examples/custom-template for complete working examples of all customization approaches.

Email Components

Basic Structure

email := mailingo.Email{
    Body: mailingo.Body{
        Name:       "Recipient Name",    // Required
        Greeting:   "Hello",             // Optional (default: "greeting" i18n key)
        Title:      "Email Title",       // Optional
        Intros:     []string{},          // Introduction paragraphs
        Dictionary: []mailingo.Entry{},  // Key-value pairs
        Table:      mailingo.Table{},    // Tabular data
        Actions:    []mailingo.Action{}, // Call-to-action buttons
        Outros:     []string{},          // Closing paragraphs
        Signature:  "Best regards",      // Optional (default: "signature" i18n key)
    },
}

Dictionary (Key-Value Pairs)

Display structured information:

Dictionary: []mailingo.Entry{
    {Key: "Username", Value: "johndoe"},
    {Key: "Email", Value: "john@example.com"},
    {Key: "Account Type", Value: "Premium"},
}

Tables

Perfect for order details, invoices, etc.:

Table: mailingo.Table{
    Data: [][]mailingo.Entry{
        // Header row
        {
            {Key: "Product"},
            {Key: "Quantity"},
            {Key: "Price"},
        },
        // Data rows
        {
            {Value: "Widget A"},
            {Value: "2"},
            {Value: "$19.99"},
        },
        {
            {Value: "Widget B"},
            {Value: "1"},
            {Value: "$29.99"},
        },
    },
}

Action Buttons

Add call-to-action buttons:

Actions: []mailingo.Action{
    {
        Instructions: "Click the button below to confirm:",
        Button: mailingo.Button{
            Text: "Confirm Email",
            Link: "https://example.com/confirm",
        },
    },
}

Custom Button Colors

Button: mailingo.Button{
    Text:  "Custom Button",
    Link:  "https://example.com",
    Color: "#FF5733", // Custom color
}

Inverted Buttons (Outlined)

Action{
    Instructions:   "Or view your account:",
    InvertedButton: true, // Outlined style
    Button: mailingo.Button{
        Text: "View Account",
        Link: "https://example.com/account",
    },
}

Attachments

Mailingo supports two types of attachments:

1. Download Link Attachments (Displayed in Email Body)

Perfect for cloud file sharing and large files. Shows attachment cards in the email with download links.

Body: mailingo.Body{
    Name: "John Doe",
    Intros: []string{
        "Your documents are ready for download:",
    },
    Attachments: []mailingo.Attachment{
        {
            Name: "invoice.pdf",
            URL:  "https://yourserver.com/download?id=123",
            Size: "2.5 MB",
            Type: "PDF Document",
        },
        {
            Name: "report.xlsx",
            URL:  "https://yourserver.com/download?id=456",
            Size: "1.8 MB",
            Type: "Excel Spreadsheet",
        },
    },
}

Best for:

  • Large files (doesn't impact email size)
  • Cloud-hosted files
  • Better email deliverability
  • Tracking downloads
  • Expiring links

2. SMTP Attachments (Real Email Attachments)

Real file attachments that are embedded in the email when sent via SMTP.

email := mailingo.Email{
    Body: mailingo.Body{
        Name: "Jane Smith",
        Intros: []string{
            "Your report is attached.",
        },
    },
    // These files will be attached to the email
    SMTPAttachments: []mailingo.SMTPAttachment{
        {
            Filename:    "monthly_report.pdf",
            Content:     fileBytes, // File content as []byte
            ContentType: "application/pdf",
        },
    },
}

// Send with your SMTP library (see examples/smtp-integration)

Best for:

  • Small files
  • Important documents that should be immediately accessible
  • Better user experience (no extra clicks)

3. Combined Approach (Recommended)

Use both types together for optimal experience:

email := mailingo.Email{
    Body: mailingo.Body{
        Name: "User Name",
        Intros: []string{
            "Summary attached, supporting docs available below:",
        },
        // Large files as download links
        Attachments: []mailingo.Attachment{
            {
                Name: "full_report.zip",
                URL:  "https://app.com/download/report-123",
                Size: "25 MB",
                Type: "ZIP Archive",
            },
        },
    },
    // Small important file as real attachment
    SMTPAttachments: []mailingo.SMTPAttachment{
        {
            Filename:    "summary.pdf",
            Content:     summaryBytes,
            ContentType: "application/pdf",
        },
    },
}

See examples/attachments and examples/smtp-integration for complete examples.

Common Use Cases

Mailingo supports all common email scenarios out of the box:

  • Email Verification Codes - Use Dictionary to display verification codes
  • Magic Links / One-Time Login - Use Actions for secure login buttons
  • Team Invitations - Use Dictionary + Actions (accept/decline buttons)
  • Billing Statements - Use Table for itemized billing + Dictionary for summary
  • File Sharing - Use Attachments (download links) or SMTPAttachments (real files)

See SCENARIOS.md for detailed examples of each scenario.

Examples

Check out the examples directory for complete, runnable examples:

  • basic: Simple email with basic features
  • common-scenarios: Verification codes, magic links, team invites, billing
  • multilingual: Multi-language email with i18n (English, Chinese, Spanish)
  • invoice: Order confirmation with table and custom theme
  • attachments: File sharing with download links
  • smtp-integration: How to use SMTP attachments with go-mail/gomail
  • custom-template: Custom CSS, custom templates, and combined customizations

API Reference

Types

Mailer

type Mailer struct {
    // Internal fields
}

Product

type Product struct {
    Name      string // Product or company name
    Link      string // Product or company website URL
    Logo      string // URL to the logo image
    Copyright string // Copyright text (supports i18n key)
}

Theme

type Theme struct {
    PrimaryColor    string // Primary brand color
    BackgroundColor string // Email background color
    TextColor       string // Main text color
    ButtonColor     string // Button background color
    ButtonTextColor string // Button text color
}

Email

type Email struct {
    Body            Body             // Email body content
    SMTPAttachments []SMTPAttachment // Files to be attached when sending via SMTP
}

Body

type Body struct {
    Name        string       // Recipient's name
    Intros      []string     // Introduction paragraphs
    Dictionary  []Entry      // Key-value pairs
    Table       Table        // Table data
    Actions     []Action     // Action buttons
    Outros      []string     // Closing paragraphs
    Attachments []Attachment // Download link attachments (displayed in email body)
    Greeting    string       // Greeting text
    Signature   string       // Signature text
    Title       string       // Email title
}

Attachment

type Attachment struct {
    Name string // File name (e.g., "invoice.pdf")
    URL  string // Download URL
    Size string // Human-readable size (e.g., "2.5 MB")
    Type string // File type (e.g., "PDF Document")
}

SMTPAttachment

type SMTPAttachment struct {
    Filename    string // Name as it appears in email
    Content     []byte // File content bytes
    ContentType string // MIME type (e.g., "application/pdf")
}

Methods

New

func New(product Product, theme Theme, opts ...options.Option) *Mailer

Creates a new Mailer instance with the specified product info and theme. Optionally accepts customization options:

  • options.WithCustomCSS(css string): Add custom CSS to the default template
  • options.WithCustomTemplateString(template string): Use a custom template string
  • options.WithCustomTemplateFS(fs fs.FS, path string): Use a custom template from embedded filesystem

Example:

mailer := mailingo.New(
    product,
    theme,
    options.WithCustomCSS("/* custom styles */"),
)

LoadMessageFile

func (m *Mailer) LoadMessageFile(path string) error

Loads translation messages from a file.

LoadMessageFileFS

func (m *Mailer) LoadMessageFileFS(fs fs.FS, path string) error

Loads translation messages from an embedded filesystem.

GenerateHTML

func (m *Mailer) GenerateHTML(email Email, lang string) (string, error)

Generates an HTML email. The lang parameter should be a BCP 47 language tag (e.g., "en", "zh-CN").

GeneratePlainText

func (m *Mailer) GeneratePlainText(email Email, lang string) (string, error)

Generates a plain text email. The lang parameter should be a BCP 47 language tag (e.g., "en", "zh-CN").

Testing

Run the test suite:

go test -v

Run tests with coverage:

go test -v -cover

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by Hermes
  • Uses go-i18n for internationalization
  • Built with Go's standard library and minimal dependencies

Support

If you have questions or need help, please:

  • Open an issue on GitHub
  • Check the examples directory
  • Review the test files for usage patterns

About

hermes inspired mail template for go with i18n support

Resources

License

Stars

Watchers

Forks

Packages

No packages published