DEV Community

Cover image for Sending HTML emails using templates in Golang
Dhanush Gopinath
Dhanush Gopinath

Posted on

3

Sending HTML emails using templates in Golang

In the Geektrust 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, 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
}
Enter fullscreen mode Exit fullscreen mode

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

<!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>
Enter fullscreen mode Exit fullscreen mode

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.

templateData := struct {
    Name string
    URL string
 }{
    Name: "Dhanush",
    URL: "http://geektrust.in",
 }
Enter fullscreen mode Exit fullscreen mode

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 and Navaneeth K. N in making the Go code more idiomatic, than it was before :)
  4. This post was first published in my personal blog

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay