
In theGeektrust 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 inGo, we needed the same feature.
This post is a short read about reading an HTML template file and sending email using Go’shtml/template
andnet/smtp
packages.
The code is as given below.
package mainimport ( "bytes" "fmt" "html/template" "net/smtp")var auth smtp.Authfunc 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 structtype 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 structRequest
. 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’shtml/template
packageExecute 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}}<ahref="{{.URL}}">Confirm email address</a></p></body></html>
The template data is a struct which hasName
&URL
as the field values. It is initialised with values and passed to the NewRequest method to create an object of Request.
templateData:=struct{NamestringURLstring}{Name:"Dhanush",URL:"http://geektrust.in",}
Once the instance ofRequest
is created, thenParseTemplate
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. Abytes.Buffer
is passed to theExecute
method asio.Writer
so that we get back the HTML string with the data replaced.This HTML string is then set as the Email Body.
TheSendEmail
method sets the MIME encoding astext/html
and calls smtp package’sSendMail
method to send the email. When the email is sent successfully the SendEmail method returns a true value.
Notes:
- 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. - Read the package documentation of
html/template
to understand how Go replaces the HTML with actual data. - Thanks toJijesh Mohan andNavaneeth K. N in making the Go code more idiomatic, than it was before :)
- This post was first published in mypersonal blog
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse