Sending HTML emails using templates in Golang
Tags: smtp, templates, go
Published: 2017-06-21 07:05:22

---
title: Sending HTML emails using templates in Golang
published: true
description: 
tags: smtp, templates, golang
cover_image: https://thepracticaldev.s3.amazonaws.com/i/j0ggwxjasmhog0512vpo.png
---

In the [Geektrust](https://geektrust.in) application (built on NodeJS) we send a lot of emails that are auto-generated at runtime using HTML Templates. In a new application, which we have developed in [Go](https://golang.org/), we needed the same feature. 

This post is a short read about reading an HTML template file and sending email using Go’s `html/template` and `net/smtp` packages.

The code is as given below.

```
package main

import (
	"bytes"
	"fmt"
	"html/template"
	"net/smtp"
)

var auth smtp.Auth

func main() {
	auth = smtp.PlainAuth("", "iamwho@whoami.com", "password", "smtp.gmail.com")
	templateData := struct {
		Name string
		URL  string
	}{
		Name: "Dhanush",
		URL:  "http://geektrust.in",
	}
	r := NewRequest([]string{"junk@junk.com"}, "Hello Junk!", "Hello, World!")
	err := r.ParseTemplate("template.html", templateData)
	if err != nil {
		ok, _ := r.SendEmail()
		fmt.Println(ok)
	}
}

//Request struct
type Request struct {
	from    string
	to      []string
	subject string
	body    string
}

func NewRequest(to []string, subject, body string) *Request {
	return &Request{
		to:      to,
		subject: subject,
		body:    body,
	}
}

func (r *Request) SendEmail() (bool, error) {
	mime := "MIME-version: 1.0;\nContent-Type: text/plain; charset=\"UTF-8\";\n\n"
	subject := "Subject: " + r.subject + "!\n"
	msg := []byte(subject + mime + "\n" + r.body)
	addr := "smtp.gmail.com:587"

	if err := smtp.SendMail(addr, auth, "dhanush@geektrust.in", r.to, msg); err != nil {
		return false, err
	}
	return true, nil
}

func (r *Request) ParseTemplate(templateFileName string, data interface{}) error {
	t, err := template.ParseFiles(templateFileName)
	if err != nil {
		return err
	}
	buf := new(bytes.Buffer)
	if err = t.Execute(buf, data); err != nil {
		return err
	}
	r.body = buf.String()
	return nil
}
```

In this I encapsulate the smtp request in a struct `Request`. It contains basic things like To, Subject, Body. This template file has the data placeholders which will be replaced with actual data values by Go’s `html/template` package [Execute](https://golang.org/pkg/html/template/#Template.Execute) method.

```html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>

</head>

<body>
<p>
    Hello {{.Name}}
    <a href="{{.URL}}">Confirm email address</a>
</p>
    
</body>

</html>
```

The template data is a struct which has `Name` & `URL` as the field values. It is initialised with values and passed to the NewRequest method to create an object of Request.

```go
templateData := struct {
    Name string
    URL string
 }{
    Name: "Dhanush",
    URL: "http://geektrust.in",
 }
```
Once the instance of `Request` is created, then `ParseTemplate` method is called on it. This method receives a template filename and template data. It parses the template file and executes it with the template data supplied. A `bytes.Buffer` is passed to the `Execute` method as `io.Writer` so that we get back the HTML string with the data replaced.This HTML string is then set as the Email Body.

The `SendEmail` method sets the MIME encoding as `text/html` and calls smtp package’s `SendMail` method to send the email. When the email is sent successfully the SendEmail method returns a true value.


Notes:

1. If you return the Request in ParseTemplate method, instead of the error, then we make the call in one line.
`ok,err := NewRequest([]string{“junk@junk.com”}, “Hello Junk!”, “Hello, World!”, “template.html”, templateData).ParseTemplate().SendEmail()` But then any error coming out of ParseTemplate may have to be tracked inside the method.
2. Read the package documentation of `html/template` to understand how Go replaces the HTML with actual data.
3. Thanks to [Jijesh Mohan](https://github.com/jijeshmohan/) and [Navaneeth K. N](https://github.com/navaneeth) in making the Go code more idiomatic, than it was before :)
4. This post was first published in my [personal blog](https://medium.com/@dhanushgopinath/sending-html-emails-using-templates-in-golang-9e953ca32f3d)