
If you’re going to build an email service/feature in your app to send emails to your audiences, you can use Gmail to be a SMTP email sender. This approach is quite simple, we will try to do it with Go.
To use Gmail as sender of your mailer, you need to setup an app password of your google account first. You can do it here.
Once you access the page, you’ll be served a tiny form to generate app passwords of your account.

When the button Create is clicked, there will be a modal popping out containing a generated password, just keep it to use later.

Now let’s jump into the code!
Start with creating a file for setup purpose in a package named mailer in a new mail folder, save the file as mail-setup.go.
// mail/setup.go
package mailer
import (
"fmt"
"net/smtp"
"sync"
)
type SMTPMailSetup struct {
Server string
Port string
Address string
Sender string
Password string
Auth smtp.Auth
}
var mailSetup *SMTPMailSetup
var once sync.Once
func getSetup() *SMTPMailSetup {
once.Do(func() {
mailSetup = &SMTPMailSetup{
Server: "smtp.gmail.com",
Port: "587",
Sender: "your_email", // change with your own email
Password: "generated_app_password", // change with your trimmed generated app password earlier
}
mailSetup.Address = fmt.Sprintf("%s:%s", mailSetup.Server, mailSetup.Port)
mailSetup.Auth = smtp.PlainAuth("", mailSetup.Sender, mailSetup.Password, mailSetup.Server)
})
return mailSetup
}
Then create a Usecase in another file.
// mail/usecase.go
package mailer
import (
"bytes"
"fmt"
"text/template"
"net/smtp"
)
type Mailer struct {
Body []byte
Setup *SMTPMailSetup
}
func NewSMTPMailer() *Mailer {
return &Mailer{
Setup: getSetup(),
}
}
func (m *Mailer) createBody(subject, htmlTemplate string, data any) (err error) {
var body bytes.Buffer
const mime = "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
body.Write([]byte(fmt.Sprintf("Subject: %s\n%s\n\n", subject, mime)))
t, err := template.ParseFiles(htmlTemplate)
if err != nil {
return
}
err = t.Execute(&body, data)
if err != nil {
return
}
m.Body = body.Bytes()
return nil
}
func (m *Mailer) Send(receipent, subject, template string, data any) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("%s | %v", "error on sending email", r)
}
}()
err = m.createBody(subject, template, data)
if err != nil {
return
}
err = smtp.SendMail(m.Setup.Address, m.Setup.Auth, m.Setup.Sender, []string{receipent}, m.Body)
return
}
Next let’s create a sample template for the body of the email. (*You probably don’t need this if you want to send a plain text instead).
// mail/sample.template
<!DOCTYPE html>
<html>
<body>
Sending email from golang app!
</body>
</html>
Finally! Let’s implement the mailer feature in the main file.
// main.go
package main
import (
"log"
"time"
mailer "mailer/mail"
)
func main () {
mail := mailer.NewSMTPMailer()
err := mail.Send("sample_receipent@xemaildomain.com", "Test", "./mail/sample.template", nil)
if err != nil {
log.Println(err)
}
time.Sleep(30 * time.Second)
}
If it successfully sent, the receipent will receive an email like below.

The full source code can be found in this repository.