Git Product home page Git Product logo

hermes's Introduction

Hermes

Build Status Go Report Card Go Coverage Godoc FOSSA Status

Hermes is the Go port of the great mailgen engine for Node.js. Check their work, it's awesome! It'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.

Demo

Usage

First install the package:

go get -u github.com/matcornic/hermes/v2

Starting from release v2.0.0, Hermes uses Go modules. The latest version of Hermes requires at least Go 1.11 with gomodules enabled. You can still use an Hermes release compatible with prior Go versions by using v1.2.0 release

Then, start using the package by importing and configuring it:

// Configure hermes by setting a theme and your product info
h := hermes.Hermes{
    // Optional Theme
    // Theme: new(Default) 
    Product: hermes.Product{
        // Appears in header & footer of e-mails
        Name: "Hermes",
        Link: "https://example-hermes.com/",
        // Optional product logo
        Logo: "http://www.duchess-france.org/wp-content/uploads/2016/01/gopher.png",
    },
}

Next, generate an e-mail using the following code:

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", // Optional action button color
                    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 an HTML email with the provided contents (for modern clients)
emailBody, err := h.GenerateHTML(email)
if err != nil {
    panic(err) // Tip: Handle error with something else than a panic ;)
}

// Generate the plaintext version of the e-mail (for clients that do not support xHTML)
emailText, err := h.GeneratePlainText(email)
if err != nil {
    panic(err) // Tip: Handle error with something else than a panic ;)
}

// Optionally, preview the generated HTML e-mail by writing it to a local file
err = ioutil.WriteFile("preview.html", []byte(emailBody), 0644)
if err != nil {
    panic(err) // Tip: Handle error with something else than a panic ;)
}

This code would output the following HTML template:

And the following plain text:


------------
Hi Jon Snow,
------------

Welcome to Hermes! We're very excited to have you on board.

To get started with Hermes, please click here: https://hermes-example.com/confirm?token=d9729feb74992cc3482b350163a1a010

Need help, or have questions? Just reply to this email, we'd love to help.

Yours truly,
Hermes - https://example-hermes.com/

Copyright © 2017 Hermes. All rights reserved.

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.

More Examples

To run the examples, go to examples folder, then run go run -a *.go. HTML and Plaintext example should be created in given theme folders.

Optionaly you can set the following variables to send automatically the emails to one your mailbox. Nice for testing template in real email clients.

  • HERMES_SEND_EMAILS=true
  • HERMES_SMTP_SERVER=<smtp_server> : for Gmail it's smtp.gmail.com
  • HERMES_SMTP_PORT=<smtp_port> : for Gmail it's 465
  • HERMES_SENDER_EMAIL=<your_sender_email>
  • HERMES_SENDER_IDENTITY=<the sender name>
  • HERMES_SMTP_USER=<smtp user> : usually the same than HERMES_SENDER_EMAIL
  • HERMES_TO=<recipients emails>: split by commas like [email protected],[email protected]

The 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 !)

Plaintext E-mails

To generate a plaintext version of the e-mail, simply call GeneratePlainText function:

// Generate plaintext email using hermes
emailText, err := h.GeneratePlainText(email)
if err != nil {
    panic(err) // Tip: Handle error with something else than a panic ;)
}

Supported Themes

The following open-source themes are bundled with this package:

RTL Support

To change the default text direction (left-to-right), simply override it as follows:

// Configure hermes by setting a theme and your product info
h := hermes.Hermes {
    // Custom text direction
    TextDirection: hermes.TDRightToLeft,
}

Language Customizations

To customize the e-mail's greeting ("Hi") or signature ("Yours truly"), supply custom strings within the e-mail's Body:

email := hermes.Email{
    Body: hermes.Body{
        Greeting: "Dear",
        Signature: "Sincerely",
    },
}

To use a custom title string rather than a greeting/name introduction, provide it instead of Name:

email := hermes.Email{
    Body: hermes.Body{
        // Title will override `Name`
        Title: "Welcome to Hermes",
    },
}

To customize the Copyright, override it when initializing Hermes within your Product as follows:

// Configure hermes by setting a theme and your product info
h := hermes.Hermes{
    // Optional Theme
    // Theme: new(Default)
    Product: hermes.Product{
        // Appears in header & footer of e-mails
        Name: "Hermes",
        Link: "https://example-hermes.com/",
        // Custom copyright notice
        Copyright: "Copyright © 2017 Dharma Initiative. All rights reserved."
    },
}

To 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:

// Configure hermes by setting a theme and your product info
h := hermes.Hermes{
    // Optional Theme
    // Theme: new(Default)
    Product: hermes.Product{
        // Custom trouble text
        TroubleText: "If the {ACTION}-button is not working for you, just copy and paste the URL below into your web browser."
    },
}

Since v2.1.0, Hermes is automatically inlining all CSS to improve compatibility with email clients, thanks to Premailer. You can disable this feature by setting DisableCSSInlining of Hermes struct to true.

h := hermes.Hermes{
    ...
    DisableCSSInlining: true,
}

Elements

Hermes supports injecting custom elements such as dictionaries, tables and action buttons into e-mails.

Action

To inject an action button in to the e-mail, supply the Actions object as follows:

email := hermes.Email{
    Body: hermes.Body{
        Actions: []hermes.Action{
            {
                Instructions: "To get started with Hermes, please click here:",
                Button: hermes.Button{
                    Color: "#22BC66", // Optional action button color
                    Text:  "Confirm your account",
                    Link:  "https://hermes-example.com/confirm?token=d9729feb74992cc3482b350163a1a010",
                },
            },
        },
    },
}

Alternatively, instead of having a button, an action can be an invite code as follows:

email := hermes.Email{
    Body: hermes.Body{
        Actions: []hermes.Action{
            {
                Instructions: "To get started with Hermes, please use the invite code:",
                InviteCode: "123456",
            },
        },
    },
}

To inject multiple action buttons in to the e-mail, supply another struct in Actions slice Action.

Table

To inject a table into the e-mail, supply the Table object as follows:

email := hermes.Email{
    Body: hermes.Body{
        Table: hermes.Table{
            Data: [][]hermes.Entry{
                // List of rows
                {   
                    // Key is the column name, Value is the cell value
                    // First object defines what columns will be displayed
                    {Key: "Item", Value: "Golang"},
                    {Key: "Description", Value: "Open source programming language that makes it easy to build simple, reliable, and efficient software"},
                    {Key: "Price", Value: "$10.99"},
                },
                {
                    {Key: "Item", Value: "Hermes"},
                    {Key: "Description", Value: "Programmatically create beautiful e-mails using Golang."},
                    {Key: "Price", Value: "$1.99"},
                },
            },
            Columns: hermes.Columns{
                // Custom style for each rows
                CustomWidth: map[string]string{
                    "Item":  "20%",
                    "Price": "15%",
                },
                CustomAlignment: map[string]string{
                    "Price": "right",
                },
            },
        },
    },
}

Dictionary

To inject key-value pairs of data into the e-mail, supply the Dictionary object as follows:

email := hermes.Email{
    Body: hermes.Body{
        Dictionary: []hermes.Entry{
            {Key: "Date", Value: "20 November 1887"},
            {Key: "Address", Value: "221B Baker Street, London"},
        },
    },
}

Free Markdown

If 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:

email := hermes.Email{
		Body: hermes.Body{
			FreeMarkdown: `
> _Hermes_ service will shutdown the **1st August 2017** for maintenance operations. 

Services will be unavailable based on the following schedule:

| Services | Downtime |
| :------:| :-----------: |
| Service A | 2AM to 3AM |
| Service B | 4AM to 5AM |
| Service C | 5AM to 6AM |

---

Feel free to contact us for any question regarding this matter at [[email protected]](mailto:[email protected]) or in our [Gitter](https://gitter.im/)

`,
		},
	}
}

This code would output the following HTML template:

And the following plaintext:

------------
Hi Jon Snow,
------------

> 
> 
> 
> Hermes service will shutdown the *1st August 2017* for maintenance
> operations.
> 
> 

Services will be unavailable based on the following schedule:

+-----------+------------+
| SERVICES  |  DOWNTIME  |
+-----------+------------+
| Service A | 2AM to 3AM |
| Service B | 4AM to 5AM |
| Service C | 5AM to 6AM |
+-----------+------------+

Feel free to contact us for any question regarding this matter at [email protected] ( [email protected] ) or in our Gitter ( https://gitter.im/ )

Yours truly,
Hermes - https://example-hermes.com/

Copyright © 2017 Hermes. All rights reserved.

Be aware that this content will replace existing tables, dictionary and actions. Only intros, outros, header and footer will be kept.

This is helpful when your application needs sending e-mails, wrote on-the-fly by adminstrators.

Markdown is rendered with Blackfriday, so every thing Blackfriday can do, Hermes can do it as well.

Troubleshooting

  1. 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.

Simply sending the X-Entity-Ref-ID header with your e-mails will prevent grouping / truncation.

Contributing

See CONTRIBUTING.md

License

Apache 2.0

FOSSA Status

hermes's People

Contributors

akamensky avatar atrox avatar btcdanny avatar crazy-max avatar ernsheong avatar fossabot avatar fridolin-koch avatar mack avatar matcornic avatar mlgd avatar sckelemen avatar thiht avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hermes's Issues

Problem installing

Hello,

I try to install Hermes but there seems to be a problem with blackfriday

[nalkema@prdexp1 src]$ go get -u -v github.com/matcornic/hermes
github.com/matcornic/hermes (download)
github.com/Masterminds/sprig (download)
github.com/Masterminds/goutils (download)
github.com/Masterminds/semver (download)
github.com/google/uuid (download)
github.com/huandu/xstrings (download)
github.com/imdario/mergo (download)
github.com/mitchellh/copystructure (download)
github.com/mitchellh/reflectwalk (download)
github.com/spf13/cast (download)
get "golang.org/x/crypto/bcrypt": found meta tag get.metaImport{Prefix:"golang.org/x/crypto", VCS:"git", RepoRoot:"https://go.googlesource.com/crypto"} at //golang.org/x/crypto/bcrypt?go-get=1
get "golang.org/x/crypto/bcrypt": verifying non-authoritative meta tag
golang.org/x/crypto (download)
get "golang.org/x/crypto/blowfish": found meta tag get.metaImport{Prefix:"golang.org/x/crypto", VCS:"git", RepoRoot:"https://go.googlesource.com/crypto"} at //golang.org/x/crypto/blowfish?go-get=1
get "golang.org/x/crypto/blowfish": verifying non-authoritative meta tag
get "golang.org/x/crypto/scrypt": found meta tag get.metaImport{Prefix:"golang.org/x/crypto", VCS:"git", RepoRoot:"https://go.googlesource.com/crypto"} at //golang.org/x/crypto/scrypt?go-get=1
get "golang.org/x/crypto/scrypt": verifying non-authoritative meta tag
get "golang.org/x/crypto/pbkdf2": found meta tag get.metaImport{Prefix:"golang.org/x/crypto", VCS:"git", RepoRoot:"https://go.googlesource.com/crypto"} at //golang.org/x/crypto/pbkdf2?go-get=1
get "golang.org/x/crypto/pbkdf2": verifying non-authoritative meta tag
github.com/jaytaylor/html2text (download)
github.com/olekukonko/tablewriter (download)
github.com/mattn/go-runewidth (download)
github.com/ssor/bom (download)
get "golang.org/x/net/html": found meta tag get.metaImport{Prefix:"golang.org/x/net", VCS:"git", RepoRoot:"https://go.googlesource.com/net"} at //golang.org/x/net/html?go-get=1
get "golang.org/x/net/html": verifying non-authoritative meta tag
golang.org/x/net (download)
get "golang.org/x/net/html/atom": found meta tag get.metaImport{Prefix:"golang.org/x/net", VCS:"git", RepoRoot:"https://go.googlesource.com/net"} at //golang.org/x/net/html/atom?go-get=1
get "golang.org/x/net/html/atom": verifying non-authoritative meta tag
github.com/russross/blackfriday (download)
package github.com/russross/blackfriday/v2: cannot find package "github.com/russross/blackfriday/v2" in any of:
        /usr/local/go/src/github.com/russross/blackfriday/v2 (from $GOROOT)
        /users/nalkema/go/src/github.com/russross/blackfriday/v2 (from $GOPATH)
github.com/vanng822/go-premailer (download)
github.com/PuerkitoBio/goquery (download)
github.com/andybalholm/cascadia (download)
github.com/vanng822/css (download)
github.com/gorilla/css (download)

When I try to install 1.2 version it returns an error

go get -u github.com/matcornic/hermes

../github.com/matcornic/hermes/hermes.go:8:2: cannot find package "github.com/russross/blackfriday/v2" in any of: /usr/local/go/src/github.com/russross/blackfriday/v2 (from $GOROOT) /go/src/github.com/russross/blackfriday/v2 (from $GOPATH)

App Deep Links and #ZgotmplZ

Hi, I'm sure this is a quick solution but I thought I'd post until I figured it out.

When I pass in an app deep link such as mycoolapp-app://someInAppRoute?data=123456 as my .Hermes.Product.Link, it gets converted to #ZgotmplZ.

How can I make the scheme mycoolapp-app:// allowed in Hermes?

Add "safe/unescape HTML" to templateFuncs

Reason

There are times where we want to style Intros, Outros or other elements in hermes.Body. Adding a html func (like url) to render HTML elements will be helpful for these scenarios.

hermes.go 

var templateFuncs = template.FuncMap{
	"url": func(s string) template.URL {
		return template.URL(s)
	},
+	"html": func(s string) template.HTML {
+		return template.HTML(s)
+	},
}

the theme renders two invitecode block

image

this was coused by b496815

there are two if statements to render the InviteCode . i think the first one should be deleted

                              {{ if $action.InviteCode }}
                                <div style="margin-top:30px;margin-bottom:30px">
                                  <table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                      <td align="center">
                                        <table align="center" cellpadding="0" cellspacing="0" style="padding:0;text-align:center">
                                          <tr>
                                            <td style="display:inline-block;border-radius:3px;font-family:Consolas, monaco, monospace;font-size:28px;text-align:center;letter-spacing:8px;color:#555;background-color:#eee;padding:20px">
                                              {{ $action.InviteCode }}
                                            </td>
                                          </tr>
                                        </table>
                                      </td>
                                    </tr>
                                  </table>
                                </div>
                              {{ end }}   
                              {{safe "<![endif]-->" }}
                                    <div>
                                      {{ if $action.Button.Text }}
                                        <a href="{{ $action.Button.Link }}" class="button" style="{{ with $action.Button.Color }}background-color: {{ . }};{{ end }} {{ with $action.Button.TextColor }}color: {{ . }};{{ end }} width: {{$width}}px;" target="_blank">
                                          {{ $action.Button.Text }}
                                        </a>
                                      {{end}}
                                      {{ if $action.InviteCode }}
                                        <span class="invite-code">{{ $action.InviteCode }}</span>
                                      {{end}}
                                    </div>

for any one looking for a temporary solution , just copy the flat.go or default.go , and delete the codes in first code block.

Additional actions

When adding a second action/button, the alternative text displays in a table with uneven column widths depending on the url content.

I have tested with adding a new row for each action and the result is much clearer.

Change Table to []Table

Hello

Could you consider using a slice of type Table, so it is easier to show multiple tables ?

Regards,

William

Customisation of 'Action Trouble Text'

Currently I can't find any possibility to change the 'action trouble text' inside the footer:

If you’re having trouble with the button 'Hier Anmelden', copy and paste the URL below into your web browser.

This makes it impossible to fully customise the email template (e.g. i18n).

I would propose the following changes: fridolin-koch@44be377

I've you are happy with the proposed solution, I can sent a PR.

Best Regards,
Frido

On Oct 29, 2018 started getting problems deployment with blackfriday.v2

During deployments I started getting this error:

../github.com/matcornic/hermes/hermes.go:8:2: cannot find package "github.com/russross/blackfriday/v2" in any of:
/usr/local/go/src/github.com/russross/blackfriday/v2 (from $GOROOT)
/go/src/github.com/russross/blackfriday/v2 (from $GOPATH)

I have worked around the problem by forking hermes and changing blackfriday references from github.com to gopkg.in.

Add "TextColor" or similar option for button

New Gmail web client seems to differ from before in how it handles button shown in email.

In previous version the button text was shown colored in accordance with theme, but now it shows as:

screen shot 2018-09-02 at 7 23 04 pm

From what it looks new Gmail web client adds its own style that overrides the embedded CSS from hermes theme:

screen shot 2018-09-02 at 7 25 37 pm

This is fixable by adding inline CSS to the button color: white; (for example) to make it look as below:

screen shot 2018-09-02 at 7 25 03 pm

Or I think this could be fixed by doing what #3 suggests and inlining all CSS.

HTML Email Body not working

HTML message body generated using the example given was not rendered by gmail properly. Code I have tried so far:

h:=hermes.Hermes{
			//Theme: hermes.Theme,
			Product:            hermes.Product{
				Name:"XYZ",
				Link:"https://xyz.com",
				Copyright: fmt.Sprintf("Copyright © %d XYZ All rights reserved.",time.Now().Year()),
				TroubleText: "",
			},
		}

		emailBody,_:=h.GenerateHTML(hermes.Email{
			Body:hermes.Body{
				Name:         "bhusal.anish12",
				Intros:       []string{"Don't worry we have got you covered"},
				Dictionary:   nil,
				Table:        hermes.Table{},
				Actions: []hermes.Action{
					{
						Instructions: "To reset your account, please click here:",
						Button: hermes.Button{
							Color: "#22BC66", // Optional action button color
							Text:  "Reset Password",
							Link:  "https://xyz.com",
						},
					},
				},
				Outros: []string{
					"Need help, or have questions? Just reply to this email, we'd love to help.",
				},
				Greeting:     "",
				Signature:    "",
				Title:        "",
				FreeMarkdown: "",
			},
		})

This when sent via gmail client for go is not rendering the template.

Adding newline to Instructions: element

Hi,
First of all thank you for the package and community.

I just started exploring hermes. I am looking to add multiline message to email. In below code I tried using \n, \r,
\r\n between two sentences in the Instructions element. It does not add separate my two lines. Is there a way to do so?

		Actions: []hermes.Action{
			{
				Instructions: "Google Groups automation just completed SUCCESSFULLY.\rTo view the logs, please click the View Log button.",

-Kamlesh

Image integration ?

Hey there !
First of all thanks for the awesome project 😃

I'm wondering if there's a clean way of inserting an image in the generated mail ?
It's possible to use the FreeMarkdown field (using the ![...](https://...) notation), but I don't know if it's currently possible to insert pictures without that technique.

hermes.Theme has no support for exported fields

Given a Theme like this:

type Theme struct {
    Color string
    Logo  string
}

func (t *Theme) Name() string { ... }
func (t *Theme) HTMLTemplate() string { ... }
func (t *Theme) PlainTextTemplate() string { ... }

And calling hermes like this:

h := hermes.Hermes{
    Theme: new(Theme),
    // ...
}
email := hermes.Email{
    //  ...
}
html, err = h.GenerateHTML(email)
if err != nil {
	...
}

Will result int

panic: reflect: Field index out of range [recovered]
	panic: reflect: Field index out of range

The reason for this is the exported fields, which are tried to be merged into hermes.Default theme which is of type struct{}. Therefore it's not possible to have exported fields on a struct implementing hermes.Theme interface.

About Button

Hi, when using a button, I need two options, yes or no (for moderated emails), is there any way to add two buttons to one email body?

Raw HTML displayed

Hey, thanks for such a great library. You made our lives much easier.

I have been struggling with a small issue. Whenever I send an email to a gmail or any other email address with the body of the email generated by using GenerateHTML, I always get the raw HTML. However, if I save the html to a local file it works perfectly well. What seems to be the problem?

Plugin system?

Hello !

Is a plugin system planned on Hermes roadmap? :)

I would live to develop one to add support for image charts to hermes. (like I did for mjml with mjml-charts)

Hermes 1.2.0 is using Blackfriday V2 which uses modules dependency

I'm currently using Hermes on a project that has some dependencies issues and cannot be used with modules at the moment.

Thing is, this hermes version supposedly supports the old dep system, but the ToHTML method (line 76) on hermes.go uses the blackfriday/v2 dependency which only works with modules and I can't make a proper build of my project without commenting it.

Send email

Hey how could I send an email using this?

Support anonymous Table columns without header text

It would be useful to provide support for anonymous columns, or column renaming with support to define empty name. Maybe Table.Columns.CustomName.

Use case: order notification with following fields:

  • description (name of item, plus details, variant,.. ),
  • anonymous price per unit of measurement (e.g. 14€ / pc, 19€ / liter, 5€ / kg,...),
  • anonymous amount (e.g. 2 pcs, 4 liters, 32 kg,...),
  • price contains price per unit * amount).

I don't really want to display names for price per unit and amount columns. These headers prolong the width of these columns, as header is wider than content. And, it's the meaning of the column pretty much obvious from the content of fields..

Changing the Theme

Hello,

I am not able to change the theme to flat. No example was also shown. Please add this to the documentation and tell how to change the default theme to flat?

undefined: blackfriday.Run

New install:

vendor/github.com/matcornic/hermes/hermes.go:76:23: undefined: blackfriday.Run

Seems blackfriday API has changed:

// ToHTML converts Markdown to HTML
    func (c Markdown) ToHTML() template.HTML {
            return template.HTML(blackfriday.Run([]byte(string(c))))
    }

Unconfigured Email

I'm running some tests using hermes, but one of the emails appears unconfigured to me. Did I do something wrong?

E-mail image

http://prntscr.com/gj4e4z

My Script

body, err := h.GenerateHTML(email)
if err != nil {
	panic(err)
}

emailAddress := "my-email"
to := []string{emailAddress}
title := "Recuperar senha"

mime := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
subject := "Subject: " + title + "!\n"
msg := []byte(subject + mime + "\n" + body)
addr := "smtp.gmail.com:587"

auth := smtp.PlainAuth("", emailAddress, "my-password", "smtp.gmail.com")
if err := smtp.SendMail(addr, auth, emailAddress, to, msg); err != nil {
	log.Println("Error")
} else {
	log.Println("Success")
}

Content Email

Date: Sat, 09 Sep 2017 11:00:18 -0700 (PDT)
From: my-email
Subject: Recuperar senha!
MIME-version: 1.0;
Content-Type: text/html; charset="UTF-8";



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <style type="text/css" rel="stylesheet" media="all">
     
    *:not(br):not(tr):not(html) {
      font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
    }
    body {
      width: 100% !important;
      height: 100%;
      margin: 0;
      line-height: 1.4;
      background-color: #2c3e50;
      color: #74787E;
      -webkit-text-size-adjust: none;
    }
    a {
      color: #3869D4;
    }

     
    .email-wrapper {
      width: 100%;
      margin: 0;
      padding: 0;
      background-color: #2c3e50;
    }
    .email-content {
      width: 100%;
      margin: 0;
      padding: 0;
    }
     
    .email-masthead {
      padding: 25px 0;
      text-align: center;
    }
    .email-masthead_logo {
      max-width: 400px;
      border: 0;
    }
    .email-masthead_name {
      font-size: 16px;
      font-weight: bold;
      color: #2F3133;
      text-decoration: none;
      text-shadow: 0 1px 0 white;
    }
    .email-logo {
      max-height: 50px;
    }
     
    .email-body {
      width: 100%;
      margin: 0;
      padding: 0;
      border-top: 1px solid #EDEFF2;
      border-bottom: 1px solid #EDEFF2;
      background-color: #FFF;
    }
    .email-body_inner {
      width: 570px;
      margin: 0 auto;
      padding: 0;
    }
    .email-footer {
      width: 570px;
      margin: 0 auto;
      padding: 0;
      text-align: center;
    }
    .email-footer p {
      color: #eaeaea;
    }
    .body-action {
      width: 100%;
      margin: 30px auto;
      padding: 0;
      text-align: center;
    }

    .body-dictionary {
      width: 100%;
      overflow: hidden;
      margin: 20px auto 20px;
      padding: 0;
    }
    .body-dictionary dt {
      clear: both;
      color: #000;
      font-weight: bold;
      float: left;
      width: 50%;
      padding: 0;
      margin: 0;
      margin-bottom: 0.3em;
    }
    .body-dictionary dd {
      float: left;
      width: 50%;
      padding: 0;
      margin: 0;
    }
    .body-sub {
      margin-top: 25px;
      padding-top: 25px;
      border-top: 1px solid #EDEFF2;
      table-layout: fixed;
    }
    .body-sub a {
      word-break: break-all;
    }
    .content-cell {
      padding: 35px;
    }
    .align-right {
      text-align: right;
    }
     
    h1 {
      margin-top: 0;
      color: #2F3133;
      font-size: 19px;
      font-weight: bold;
    }
    h2 {
      margin-top: 0;
      color: #2F3133;
      font-size: 16px;
      font-weight: bold;
    }
    h3 {
      margin-top: 0;
      color: #2F3133;
      font-size: 14px;
      font-weight: bold;
    }
    blockquote {
      margin: 1.7rem 0;
      padding-left: 0.85rem;
      border-left: 10px solid #F0F2F4;
    }
    blockquote p {
        font-size: 1.1rem;
        color: #999;
    }
    blockquote cite {
        display: block;
        text-align: right;
        color: #666;
        font-size: 1.2rem;
    }
    cite {
      display: block;
      font-size: 0.925rem; 
    }
    cite:before {
      content: "\2014 \0020";
    }
    p {
      margin-top: 0;
      color: #74787E;
      font-size: 16px;
      line-height: 1.5em;
    }
    p.sub {
      font-size: 12px;
    }
    p.center {
      text-align: center;
    }
    table {
      width: 100%;
    }
    th {
      padding: 0px 5px;
      padding-bottom: 8px;
      border-bottom: 1px solid #EDEFF2;
    }
    th p {
      margin: 0;
      color: #9BA2AB;
      font-size: 12px;
    }
    td {
      padding: 10px 5px;
      color: #74787E;
      font-size: 15px;
      line-height: 18px;
    }
    .content {
      align: center;
      padding: 0;
    }
     
    .data-wrapper {
      width: 100%;
      margin: 0;
      padding: 35px 0;
    }
    .data-table {
      width: 100%;
      margin: 0;
    }
    .data-table th {
      text-align: left;
      padding: 0px 5px;
      padding-bottom: 8px;
      border-bottom: 1px solid #EDEFF2;
    }
    .data-table th p {
      margin: 0;
      color: #9BA2AB;
      font-size: 12px;
    }
    .data-table td {
      padding: 10px 5px;
      color: #74787E;
      font-size: 15px;
      line-height: 18px;
    }
     
    .button {
      display: inline-block;
      width: 100%;
      background-color: #00948d;
      color: #ffffff;
      font-size: 15px;
      line-height: 45px;
      text-align: center;
      text-decoration: none;
      -webkit-text-size-adjust: none;
      mso-hide: all;
    }
     
    @media only screen and (max-width: 600px) {
      .email-body_inner,
      .email-footer {
        width: 100% !important;
      }
    }
  </style>
</head>
<body dir="ltr">
  <table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0">
    <tr>
      <td class="content">
        <table class="email-content" width="100%" cellpadding="0" cellspacing="0">
          
          <tr>
            <td class="email-masthead">
              <a class="email-masthead_name" href="https://example-hermes.com/" target="_blank">
                
                  <img src="http://www.duchess-france.org/wp-content/uploads/2016/01/gopher.png" class="email-logo" />
                
                </a>
            </td>
          </tr>

          
          <tr>
            <td class="email-body" width="100%">
              <table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0">
                
                <tr>
                  <td class="content-cell">
                    <h1>Hi Jon Snow,</h1>
                    
                        
                          
                            <p>You have received this email because a password reset request for Hermes account was received.</p>
                          
                        
                    
                    

                      

                      
                      
                        
                        
                        
                      

                      
                      
                        
                          
                            <p>Click the button below to reset your password:</p>
                            <table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0">
                              <tr>
                                <td align="center">
                                  <div>
                                    <a href="https://hermes-example.com/reset-password?token=d9729feb74992cc3482b350163a1a010" class="button" style="background-color: #DC4D2F" target="_blank">
                                      Reset your password
                                    </a>
                                  </div>
                                </td>
                              </tr>
                            </table>
                          
                        
                      

                    
                     
                        
                          
                            <p>If you did not request a password reset, no further action is required on your part.</p>
                          
                        
                      

                    <p>
                      Thanks,
                      <br />
                      Hermes
                    </p>

                    
                       
                        <table class="body-sub">
                          <tbody>
                              
                                <tr>
                                  <td>
                                    <p class="sub">If you’re having trouble with the button &#39;Reset your password&#39;, copy and paste the URL below into your web browser.</p>
                                    <p class="sub"><a href="https://hermes-example.com/reset-password?token=d9729feb74992cc3482b350163a1a010">https://hermes-example.com/reset-password?token=d9729feb74992cc3482b350163a1a010</a></p>
                                  </td>
                                </tr>
                              
                          </tbody>
                        </table>
                      
                    
                  </td>
                </tr>
              </table>
            </td>
          </tr>
          <tr>
            <td>
              <table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0">
                <tr>
                  <td class="content-cell">
                    <p class="sub center">
                      Copyright © 2017 Hermes. All rights reserved.
                    </p>
                  </td>
                </tr>
              </table>
            </td>
          </tr>
        </table>
      </td>
    </tr>
  </table>
</body>
</html>
```

too long link make it out of the div

when I have link with long token, it was not break to another new line, maybe this need to fix break line on style
this issue happen on Aol browser email
Screen Shot 2019-09-27 at 20 53 17

Considering using Markdown content instead of plain text

Intros and Outros are plain text for now.

Consider using Markdown instead of plain text. For example, with Markdown, we are able to add links, emphase some words, and so on...

But it means that:

  • Rendering should be handled in Plain Text
  • A nice rendering should be handled in both HTML themes

MarkdownCommon is undefined

some thing wrong with deps../vendor/github.com/matcornic/hermes/hermes.go:76:23: undefined: blackfriday.MarkdownCommon

Still cannot get Blackfriday

There are several closed issues relating to this but it still seems to be a problem.

Firstly, I can do

$ go get -u github.com/matcornic/hermes/[email protected]
go: github.com/Masterminds/semver upgrade => v1.5.0
go: github.com/Masterminds/sprig upgrade => v2.22.0+incompatible
go: github.com/shurcooL/sanitized_anchor_name upgrade => v1.0.0
go: github.com/imdario/mergo upgrade => v0.3.10
go: github.com/olekukonko/tablewriter upgrade => v0.0.4
go: github.com/huandu/xstrings upgrade => v1.3.2
go: golang.org/x/crypto upgrade => v0.0.0-20200728195943-123391ffb6de
go: golang.org/x/net upgrade => v0.0.0-20200707034311-ab3426394381
go: github.com/google/uuid upgrade => v1.1.1
go: github.com/mattn/go-runewidth upgrade => v0.0.9
go: github.com/jaytaylor/html2text upgrade => v0.0.0-20200412013138-3577fbdbcff7
go: finding module for package github.com/mitchellh/copystructure
go: found github.com/mitchellh/copystructure in github.com/mitchellh/copystructure v1.0.0
go: github.com/mitchellh/reflectwalk upgrade => v1.0.1

So far, so good.

But then I run

$ go get -u ./...
go: finding module for package github.com/matcornic/hermes
go: found github.com/matcornic/hermes in github.com/matcornic/hermes v1.2.0
go: finding module for package gopkg.in/russross/blackfriday.v2
go: found gopkg.in/russross/blackfriday.v2 in gopkg.in/russross/blackfriday.v2 v2.0.1
go: r4/roster4/mail imports
	github.com/matcornic/hermes imports
	gopkg.in/russross/blackfriday.v2: gopkg.in/russross/[email protected]: parsing go.mod:
	module declares its path as: github.com/russross/blackfriday/v2
	        but was required as: gopkg.in/russross/blackfriday.v2

This is a failure I can't seem to recover from.

There seems to be a problem with Blackfriday which is messing with Hermes. Probably the Hemes dependency should be github.com/russross/blackfriday/v2 instead of gopkg.in/russross/blackfriday.v2
`.

Feature Request: FreeHTML option

Hi,

Thanks for a great project - loving the ui and clean interface! I have a question and a potential feature request.

I'm working on a project that generates moderately complex html, and I'm trying to have this in the email. Would you be open to adding anFreeMarkdown analogue such as FreeHTML? I've been playing with casting and subclassing hermes.Markdown but not seeing any success.

Essentially I'm trying to get my html template data injected.

Thanks!

Button not rendering properly

Hey guys,

Hope you are having a great day, today we found a kind of bug in our prod enviroment, we are using hermes to generate a simple "Reset your password" email template, unfortunately, it does not show properly the button in Outlook App on Windows 10:

Reset button not showing

The button should read "Reset your password"

I have tried to reproduce this behaviour in other devices with different screen sizes and all of them work flawlessly, but Outlook App on Windows 10.

Tested on:

Android 12, Outlook App - Works as expected
Android 12, Google Chrome Outlook View - Works as expected
Ubuntu 20.04 - Google Chrome Outlook Page - Works as expected
Ubuntu 20.04 - ThunderBird Mail - Works as expected
Windows 10 Pro - Email App - Works as expected
Windows 10 Pro - Google Chrome Outlook Page - Works as expected
Windows 10 Pro - Outlook App - Does not work as expected

All desktop environments were tested under 800x600 and 3440x1440 resolutions.

Any suggestion?

Thanks in advance, regards !

Cannot use "tel:" links

I want to add a button containing a phone number linke this:

email := hermes.Email{}
email.Body.Actions = append(email.Body.Actions, hermes.Action{
	Instructions: lp.Sprintf("Use this button to call sender"),
	Button: hermes.Button{
		Color: "#57cbcc",
		Text:  "Call",
		Link: "tel:0123456789",
	},
})

This is what I get when I render the mail:

<a href="#ZgotmplZ" class="button" style="display:inline-block;border-radius:3px;font-size:15px;line-height:45px;text-align:center;text-decoration:none;-webkit-text-size-adjust:none;mso-hide:all;color:#ffffff;background-color:#57cbcc;width:200px" target="_blank" width="200">
Call
</a>

#ZgotmplZ is pretty unexpected. It works well with mailto: links.

I guess Go is treating tel: as unsafe content: https://stackoverflow.com/a/14796642/10385339

Add imprint

Hi,
first of all, thanks for this great library.

Currently, the body can be customized via markdown, however this is not possible for copyright.

As required by law, you need the senders contact details (imprint) in the mail, it would be great when the copyright field can be used for that, or even create a new field.

Mostly they have the following structure:

Company Name
John Doe Street 11
<postalcode> Cityname

This will be transformed to Company Name John Doe Street 11 <postalcode> Cityname which is not that great. Thus, markdown or keeping the line breaks at least would be great. This may not work due to html sanitizing.

CSS inlining

It looks like CSS is not inlined. This is an important compatibility problem.

GenerateEmails function?

Hello,

I have a question regarding generateEmails function.

as it always generating new HTML & text files for every request and we are using those two files in the email body.

so what will happen, when two requests have been placed at the same time?

button error

I generated email using the welcome example and changed the button link, but it seems that the button doesn't work.

CID Embedded Images

hi,
is it possible to use the library with content - id images and refer them in the HTML?
i understood the library targets more buttons, but for different client campaigns i should not be having the logo images in an external server, therefore the images need to be sent with the email .

thank you

Minimize themes

Hi!
Would you consider minimizing the html/css themes?

For example we could:

config := hermes.Config{
    // Optional Theme
    // Theme: new(Default) 
    Product: hermes.Product{
        // Appears in header & footer of e-mails
        Name: "Hermes",
        Link: "https://example-hermes.com/",
        // Optional product logo
        Logo: "http://www.duchess-france.org/wp-content/uploads/2016/01/gopher.png",
    },
}

h := hermes.New(config)
...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.