{"id":13393803,"url":"https://github.com/matcornic/hermes","last_synced_at":"2025-05-12T11:16:17.834Z","repository":{"id":41183225,"uuid":"86179273","full_name":"matcornic/hermes","owner":"matcornic","description":"Golang package that generates clean, responsive HTML e-mails for sending transactional mail","archived":false,"fork":false,"pushed_at":"2025-04-04T08:12:02.000Z","size":1349,"stargazers_count":2885,"open_issues_count":18,"forks_count":243,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-05-11T11:06:47.265Z","etag":null,"topics":["awesome-go","email","email-template","email-template-generator","emails","generator","golang","hermes","mailgen","smtp","template","templating"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matcornic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-25T18:25:36.000Z","updated_at":"2025-05-10T15:14:32.000Z","dependencies_parsed_at":"2025-04-10T13:09:36.154Z","dependency_job_id":"e28ef33c-d5ad-411f-a3f7-e4cf70d6cc4a","html_url":"https://github.com/matcornic/hermes","commit_stats":{"total_commits":77,"total_committers":15,"mean_commits":5.133333333333334,"dds":"0.38961038961038963","last_synced_commit":"b49681588c91ffdbdb768a09fcfb460e535baafe"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matcornic%2Fhermes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matcornic%2Fhermes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matcornic%2Fhermes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matcornic%2Fhermes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matcornic","download_url":"https://codeload.github.com/matcornic/hermes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253554082,"owners_count":21926612,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["awesome-go","email","email-template","email-template-generator","emails","generator","golang","hermes","mailgen","smtp","template","templating"],"created_at":"2024-07-30T17:01:00.477Z","updated_at":"2025-05-11T11:06:56.172Z","avatar_url":"https://github.com/matcornic.png","language":"Go","readme":"# Hermes\n\n[![Build Status](https://github.com/matcornic/hermes/actions/workflows/main.yml/badge.svg)](https://github.com/matcornic/hermes/actions/workflows/main.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/matcornic/hermes)](https://goreportcard.com/report/github.com/matcornic/hermes)\n[![Godoc](https://godoc.org/github.com/matcornic/hermes?status.svg)](https://godoc.org/github.com/matcornic/hermes)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmatcornic%2Fhermes.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fmatcornic%2Fhermes?ref=badge_shield)\n\nHermes is the Go port of the great [mailgen](https://github.com/eladnava/mailgen) engine for Node.js. Check their work, it's awesome!\nIt's a package that generates clean, responsive HTML e-mails for sending transactional e-mails (welcome e-mails, reset password e-mails, receipt e-mails and so on), and associated plain text fallback.\n\n# Demo\n\n\u003cimg src=\"screens/default/welcome.png\" height=\"400\" /\u003e \u003cimg src=\"screens/default/reset.png\" height=\"400\" /\u003e \u003cimg src=\"screens/default/receipt.png\" height=\"400\" /\u003e\n\n# Usage\n\nFirst install the package:\n\n```\ngo get github.com/matcornic/hermes@v1.3.0\n```\n\n## Migrate back from `v2` to `v1.3.0`\n\nAt the time of `v2` creation, Go modules logic and best practices were still unsure. v1 did not use modules.\nHaving a dedicated `v2` module is meant to be used for projects hosting and maintaining `v1` and `v2` at the same time, so people can use both versions at the same time. There is no need for that in this kind of project.\nNow that go modules usage is standard, in `v1`, starting from `v1.3.0` tags, we decided to migrate back to `github.com/matcornic/hermes` instead of `github.com/matcornic/hermes/v2`.\n`v2` tags will still use `github.com/matcornic/hermes/v2` as the import path, normal way will use `github.com/matcornic/hermes` as the import path.\n\nSo, just replace your import path from `github.com/matcornic/hermes/v2` to `github.com/matcornic/hermes` and run `go get github.com/matcornic/hermes@v1.3.0` (or newer) to update the dependency.\n\n## Use Hermes\n\nThen, start using the package by importing and configuring it:\n\n```go\n// Configure hermes by setting a theme and your product info\nh := hermes.Hermes{\n    // Optional Theme\n    // Theme: new(Default) \n    Product: hermes.Product{\n        // Appears in header \u0026 footer of e-mails\n        Name: \"Hermes\",\n        Link: \"https://example-hermes.com/\",\n        // Optional product logo\n        Logo: \"http://www.duchess-france.org/wp-content/uploads/2016/01/gopher.png\",\n    },\n}\n```\n\nNext, generate an e-mail using the following code:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        Name: \"Jon Snow\",\n        Intros: []string{\n            \"Welcome to Hermes! We're very excited to have you on board.\",\n        },\n        Actions: []hermes.Action{\n            {\n                Instructions: \"To get started with Hermes, please click here:\",\n                Button: hermes.Button{\n                    Color: \"#22BC66\", // Optional action button color\n                    Text:  \"Confirm your account\",\n                    Link:  \"https://hermes-example.com/confirm?token=d9729feb74992cc3482b350163a1a010\",\n                },\n            },\n        },\n        Outros: []string{\n            \"Need help, or have questions? Just reply to this email, we'd love to help.\",\n        },\n    },\n}\n\n// Generate an HTML email with the provided contents (for modern clients)\nemailBody, err := h.GenerateHTML(email)\nif err != nil {\n    panic(err) // Tip: Handle error with something else than a panic ;)\n}\n\n// Generate the plaintext version of the e-mail (for clients that do not support xHTML)\nemailText, err := h.GeneratePlainText(email)\nif err != nil {\n    panic(err) // Tip: Handle error with something else than a panic ;)\n}\n\n// Optionally, preview the generated HTML e-mail by writing it to a local file\nerr = os.WriteFile(\"preview.html\", []byte(emailBody), 0644)\nif err != nil {\n    panic(err) // Tip: Handle error with something else than a panic ;)\n}\n```\n\nThis code would output the following HTML template:\n\n\u003cimg src=\"screens/demo.png\" height=\"400\" /\u003e\n\nAnd the following plain text:\n\n```\n\n------------\nHi Jon Snow,\n------------\n\nWelcome to Hermes! We're very excited to have you on board.\n\nTo get started with Hermes, please click here: https://hermes-example.com/confirm?token=d9729feb74992cc3482b350163a1a010\n\nNeed help, or have questions? Just reply to this email, we'd love to help.\n\nYours truly,\nHermes - https://example-hermes.com/\n\nCopyright © 2025 Hermes. All rights reserved.\n```\n\n\u003e Theme templates will be embedded in your application binary. If you want to use external templates (for configuration), use your own theme by implementing `hermes.Theme` interface with code searching for your files.\n\n## More Examples\n\n* [Welcome with button](examples/welcome.go)\n* [Welcome with invite code](examples/invite_code.go)\n* [Receipt](examples/receipt.go)\n* [Password Reset](examples/reset.go)\n* [Maintenance](examples/maintenance.go)\n\nTo run the examples, go to `examples` folder, then run `go run -a *.go`. HTML and Plaintext example should be created in given theme folders.\n\nOptionaly you can set the following variables to send automatically the emails to one your mailbox. Nice for testing template in real email clients.\n\n* `HERMES_SEND_EMAILS=true`\n* `HERMES_SMTP_SERVER=\u003csmtp_server\u003e` : for Gmail it's `smtp.gmail.com`\n* `HERMES_SMTP_PORT=\u003csmtp_port\u003e` : for Gmail it's `465`\n* `HERMES_SENDER_EMAIL=\u003cyour_sender_email\u003e`\n* `HERMES_SENDER_IDENTITY=\u003cthe sender name\u003e`\n* `HERMES_SMTP_USER=\u003csmtp user\u003e` : usually the same than `HERMES_SENDER_EMAIL`\n* `HERMES_TO=\u003crecipients emails\u003e`: split by commas like `myadress@test.com,somethingelse@gmail.com`\n\nThe program will ask for your SMTP password. If needed, you can set it with `HERMES_SMTP_PASSWORD` variable (but be careful where you put this information !)\n\n## Plaintext E-mails\n\nTo generate a [plaintext version of the e-mail](https://litmus.com/blog/best-practices-for-plain-text-emails-a-look-at-why-theyre-important), simply call `GeneratePlainText` function:\n\n```go\n// Generate plaintext email using hermes\nemailText, err := h.GeneratePlainText(email)\nif err != nil {\n    panic(err) // Tip: Handle error with something else than a panic ;)\n}\n```\n\n## Supported Themes\n\nThe following open-source themes are bundled with this package:\n\n* `default` by [Postmark Transactional Email Templates](https://github.com/wildbit/postmark-templates)\n\n\u003cimg src=\"screens/default/welcome.png\" height=\"200\" /\u003e \u003cimg src=\"screens/default/reset.png\" height=\"200\" /\u003e \u003cimg src=\"screens/default/receipt.png\" height=\"200\" /\u003e\n\n* `flat`, slightly modified from [Postmark Transactional Email Templates](https://github.com/wildbit/postmark-templates)\n\n\u003cimg src=\"screens/flat/welcome.png\" height=\"200\" /\u003e \u003cimg src=\"screens/flat/reset.png\" height=\"200\" /\u003e \u003cimg src=\"screens/flat/receipt.png\" height=\"200\" /\u003e\n\n## RTL Support\n\nTo change the default text direction (left-to-right), simply override it as follows:\n\n```go\n// Configure hermes by setting a theme and your product info\nh := hermes.Hermes {\n    // Custom text direction\n    TextDirection: hermes.TDRightToLeft,\n}\n```\n\n## Language Customizations\n\nTo customize the e-mail's greeting (\"Hi\") or signature (\"Yours truly\"), supply custom strings within the e-mail's `Body`:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        Greeting: \"Dear\",\n        Signature: \"Sincerely\",\n    },\n}\n```\n\nTo use a custom title string rather than a greeting/name introduction, provide it instead of `Name`:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        // Title will override `Name`\n        Title: \"Welcome to Hermes\",\n    },\n}\n```\n\nTo customize the `Copyright`, override it when initializing `Hermes` within your `Product` as follows:\n\n```go\n// Configure hermes by setting a theme and your product info\nh := hermes.Hermes{\n    // Optional Theme\n    // Theme: new(Default)\n    Product: hermes.Product{\n        // Appears in header \u0026 footer of e-mails\n        Name: \"Hermes\",\n        Link: \"https://example-hermes.com/\",\n        // Custom copyright notice\n        Copyright: \"Copyright © 2025 Dharma Initiative. All rights reserved.\"\n    },\n}\n```\n\nTo use a custom fallback text at the end of the email, change the `TroubleText` field of the `hermes.Product` struct. The default value is `If you’re having trouble with the button '{ACTION}', copy and paste the URL below into your web browser.`. The `{ACTION}` placeholder will be replaced with the corresponding text of the supplied action button:\n\n```go\n// Configure hermes by setting a theme and your product info\nh := hermes.Hermes{\n    // Optional Theme\n    // Theme: new(Default)\n    Product: hermes.Product{\n        // Custom trouble text\n        TroubleText: \"If the {ACTION}-button is not working for you, just copy and paste the URL below into your web browser.\"\n    },\n}\n```\n\nSince `v2.1.0`, Hermes is automatically inlining all CSS to improve compatibility with email clients, thanks to [Premailer](https://github.com/vanng822/go-premailer/premailer).\nYou can disable this feature by setting `DisableCSSInlining` of `Hermes` struct to `true`.\n\n```go\nh := hermes.Hermes{\n    ...\n    DisableCSSInlining: true,\n}\n```\n\n## Elements\n\nHermes supports injecting custom elements such as dictionaries, tables and action buttons into e-mails.\n\n### Action\n\nTo inject an action button in to the e-mail, supply the `Actions` object as follows:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        Actions: []hermes.Action{\n            {\n                Instructions: \"To get started with Hermes, please click here:\",\n                Button: hermes.Button{\n                    Color: \"#22BC66\", // Optional action button color\n                    Text:  \"Confirm your account\",\n                    Link:  \"https://hermes-example.com/confirm?token=d9729feb74992cc3482b350163a1a010\",\n                },\n            },\n        },\n    },\n}\n```\n\nAlternatively, instead of having a button, an action can be an invite code as follows:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        Actions: []hermes.Action{\n            {\n                Instructions: \"To get started with Hermes, please use the invite code:\",\n                InviteCode: \"123456\",\n            },\n        },\n    },\n}\n```\n\nTo inject multiple action buttons in to the e-mail, supply another struct in Actions slice `Action`.\n\n### Table\n\nTo inject a table into the e-mail, supply the `Table` object as follows:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        Table: hermes.Table{\n            Data: [][]hermes.Entry{\n                // List of rows\n                {   \n                    // Key is the column name, Value is the cell value\n                    // First object defines what columns will be displayed\n                    {Key: \"Item\", Value: \"Golang\"},\n                    {Key: \"Description\", Value: \"Open source programming language that makes it easy to build simple, reliable, and efficient software\"},\n                    {Key: \"Price\", Value: \"$10.99\"},\n                },\n                {\n                    {Key: \"Item\", Value: \"Hermes\"},\n                    {Key: \"Description\", Value: \"Programmatically create beautiful e-mails using Golang.\"},\n                    {Key: \"Price\", Value: \"$1.99\"},\n                },\n            },\n            Columns: hermes.Columns{\n                // Custom style for each rows\n                CustomWidth: map[string]string{\n                    \"Item\":  \"20%\",\n                    \"Price\": \"15%\",\n                },\n                CustomAlignment: map[string]string{\n                    \"Price\": \"right\",\n                },\n            },\n        },\n    },\n}\n```\n\n### Dictionary\n\nTo inject key-value pairs of data into the e-mail, supply the `Dictionary` object as follows:\n\n```go\nemail := hermes.Email{\n    Body: hermes.Body{\n        Dictionary: []hermes.Entry{\n            {Key: \"Date\", Value: \"20 November 1887\"},\n            {Key: \"Address\", Value: \"221B Baker Street, London\"},\n        },\n    },\n}\n```\n\n### Free Markdown\n\nIf you need more flexibility in the content of your generated e-mail, while keeping the same format than any other e-mail, use Markdown content. Supply the `FreeMarkdown` object as follows:\n\n```go\nemail := hermes.Email{\n\t\tBody: hermes.Body{\n\t\t\tFreeMarkdown: `\n\u003e _Hermes_ service will shutdown the **1st August 2025** for maintenance operations. \n\nServices will be unavailable based on the following schedule:\n\n| Services | Downtime |\n| :------:| :-----------: |\n| Service A | 2AM to 3AM |\n| Service B | 4AM to 5AM |\n| Service C | 5AM to 6AM |\n\n---\n\nFeel free to contact us for any question regarding this matter at [support@hermes-example.com](mailto:support@hermes-example.com) or in our [Gitter](https://gitter.im/)\n\n`,\n\t\t},\n\t}\n}\n```\n\nThis code would output the following HTML template:\n\n\u003cimg src=\"screens/free-markdown.png\" height=\"400\" /\u003e\n\nAnd the following plaintext:\n\n```\n------------\nHi Jon Snow,\n------------\n\n\u003e \n\u003e \n\u003e \n\u003e Hermes service will shutdown the *1st August 2025* for maintenance\n\u003e operations.\n\u003e \n\u003e \n\nServices will be unavailable based on the following schedule:\n\n+-----------+------------+\n| SERVICES  |  DOWNTIME  |\n+-----------+------------+\n| Service A | 2AM to 3AM |\n| Service B | 4AM to 5AM |\n| Service C | 5AM to 6AM |\n+-----------+------------+\n\nFeel free to contact us for any question regarding this matter at support@hermes-example.com ( support@hermes-example.com ) or in our Gitter ( https://gitter.im/ )\n\nYours truly,\nHermes - https://example-hermes.com/\n\nCopyright © 2025 Hermes. All rights reserved.\n```\n\nBe aware that this content will replace existing tables, dictionary and actions. Only intros, outros, header and footer will be kept.\n\nThis is helpful when your application needs sending e-mails, wrote on-the-fly by adminstrators.\n\n\u003e Markdown is rendered with [Blackfriday](https://github.com/russross/blackfriday), so every thing Blackfriday can do, Hermes can do it as well.\n\n## Troubleshooting\n\n1. After sending multiple e-mails to the same Gmail / Inbox address, they become grouped and truncated since they contain similar text, breaking the responsive e-mail layout.\n\n\u003e Simply sending the `X-Entity-Ref-ID` header with your e-mails will prevent grouping / truncation.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## License\n\nApache 2.0\n\n\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmatcornic%2Fhermes.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fmatcornic%2Fhermes?ref=badge_large)\n","funding_links":[],"categories":["Go","开源类库","Email","Email utilities","Open source library","Code","邮件库`邮件管理和发送的go语言库`","Relational Databases","电子邮件","Libraries","電子郵件","\u003cspan id=\"电子邮件-email\"\u003e电子邮件 Email\u003c/span\u003e","邮件","邮件库"],"sub_categories":["邮件","Advanced Console UIs","Search and Analytic Databases","Post Office","Templating","SQL 查询语句构建库","检索及分析资料库","高級控制台界面","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","高级控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatcornic%2Fhermes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatcornic%2Fhermes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatcornic%2Fhermes/lists"}