Different ways to send an email with Golang

In this blog, we’ll look at different methods to send an email with Go, First we will explore inbuilt smtp package, then we will move to use a popular package Gomail and finally we will send HTML emails using custom templates.

Before You Get Started

This tutorial assumes you have:

  • A basic understanding of Go Language
  • Latest GoLang version installed on your system
  • A few minutes of your time.

In this blog, we’ll look at different methods to send an email with Go, First, we will explore inbuilt smtp package, then we will move to use a popular package Gomail and finally, we will send HTML emails using custom templates.

Package smtp

smtp is an inbuilt package provided with Golang. It implements the Simple Mail Transfer Protocol and has multiple functionalities related to it. Here to send the email we will be using only two functions PlainAuth and SendMail from the package.

Note: Click here for an overview on Go Functions

  • PlainAuth: It uses the given username and password to authenticate to host and return an identity
  • SendMail: It connects to the server at address, switches to TLS if possible, authenticates with the optional mechanism an if possible, and then sends an email to the sender.

Below is the complete code to send a plain text email with smtp package in golang.

package main

import (
  "fmt"
  "net/smtp"
)

func main() {

  // Sender data.
  from := "from@gmail.com"
  password := ""

  // Receiver email address.
  to := []string{
    "sender@example.com",
  }

  // smtp server configuration.
  smtpHost := "smtp.gmail.com"
  smtpPort := "587"

  // Message.
  message := []byte("This is a test email message.")
  
  // Authentication.
  auth := smtp.PlainAuth("", from, password, smtpHost)
  
  // Sending email.
  err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, to, message)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println("Email Sent Successfully!")
}

In the above code example we have used smtp details of a Gmail account, you should update the smtp detail according to your email provider.

Just to explain things easily, In the above snippet, we have written all the smtp and email credentials in the main function, Though in a production app you should always use env variables for configurations. You can check Viper to manage configurations in production apps.

Package Gomail

Below is the complete code to send a plain text email with Gomail package in golang.

package main

import (
  "crypto/tls"
  "fmt"

  gomail "gopkg.in/mail.v2"
)

func main() {
  m := gomail.NewMessage()

  // Set E-Mail sender
  m.SetHeader("From", "from@gmail.com")

  // Set E-Mail receivers
  m.SetHeader("To", "to@example.com")

  // Set E-Mail subject
  m.SetHeader("Subject", "Gomail test subject")

  // Set E-Mail body. You can set plain text or html with text/html
  m.SetBody("text/plain", "This is Gomail test body")

  // Settings for SMTP server
  d := gomail.NewDialer("smtp.gmail.com", 587, "from@gmail.com", "")

  // This is only needed when SSL/TLS certificate is not valid on server.
  // In production this should be set to false.
  d.TLSConfig = &tls.Config{InsecureSkipVerify: true}

  // Now send E-Mail
  if err := d.DialAndSend(m); err != nil {
    fmt.Println(err)
    panic(err)
  }

  return
}

Custom HTML Templates

Now, let's send an HTML email with smtp package, for this, we need to create two files in the root folder.

  • main.go: go code to parse HTML template and send it in email
  • template.html : HTML template for emails



    

Name:

{{.Name}}

Email:

{{.Message}}

We are using text/template package to parse HTML files and use it in smtp SendMail function.

package main

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

func main() {

  // Sender data.
  from := "from@gmail.com"
  password := ""

  // Receiver email address.
  to := []string{
    "sender@example.com",
  }

  // smtp server configuration.
  smtpHost := "smtp.gmail.com"
  smtpPort := "587"

  // Authentication.
  auth := smtp.PlainAuth("", from, password, smtpHost)

  t, _ := template.ParseFiles("template.html")

  var body bytes.Buffer

  mimeHeaders := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
  body.Write([]byte(fmt.Sprintf("Subject: This is a test subject \n%s\n\n", mimeHeaders)))

  t.Execute(&body, struct {
    Name    string
    Message string
  }{
    Name:    "Puneet Singh",
    Message: "This is a test message in a HTML template",
  })

  // Sending email.
  err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, to, body.Bytes())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println("Email Sent!")
}

Once done you need to run below command to send the emails

go run main.go

If you don't want to create your custom HTML emails, Hermes is a package that generates clean, responsive HTML e-mails for sending transactional e-mails.

Now you can send beautiful emails to the customer by your golang application, You can found the complete code used in this blog on our Github Repo

MySQL Database Insert & Get Last Insert ID in Golang

this link

https://golangcode.com/mysql-database-insert-get-last-insert-id/

Golang http client handshake failure

7

 

That server only supports a few, weak ciphers:

TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39)   DH 1024 bits (p: 128, g: 1, Ys: 128)   FS   WEAK
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33)   DH 1024 bits (p: 128, g: 1, Ys: 128)   FS   WEAK
TLS_RSA_WITH_RC4_128_SHA (0x5)   WEAK

If you really must connect to that server, Go does support the last cipher in the list, but not by default. Create a client with a new tls.Config specifying the cipher you want:

t := &http.Transport{
    Proxy: http.ProxyFromEnvironment,
    Dial: (&net.Dialer{
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
    }).Dial,
    TLSHandshakeTimeout: 10 * time.Second,
    TLSClientConfig: &tls.Config{
        CipherSuites: []uint16{tls.TLS_RSA_WITH_RC4_128_SHA},
    },
}




This is cool. Could you share how did you debug this? Also, any idea why it might've worked in 1.4.2 and broke in 1.5? – Ainar-G Sep 11 '15 at 13:13

  • 2

    @Ainar-G: RC4 is has been disabled because it's very weak, and now prohibited: tools.ietf.org/html/rfc7465. – JimB Sep 11 '15 at 13:19

  • 2

    @Ainar-G: re debugging; a common cause of handshake failures is when there are no shared ciphers, so I look up what the server supports, and check those with the constants defined in crypto/tls. (I also check if the server even supports tls1.1, tls1.2, etc. Go1.5 is a little better at falling back for misbehaving servers now, so it tends to be more forgiving) – JimB Sep 11 '15 at 13:21 

  • @JimB Thank you! Exactly what is needed. How can you check the supported protocols? – Nikolay Sep 11 '15 at 13:28

  • 1

    @Nikolay: the easiest way is ssllabs.com. You can also script it with any tls client, plus some other methods mentioned here: superuser.com/questions/109213/…, – JimB Sep 11 '15 at 13:33

 

How do you drop a Dgraph database?

16

 

Unfortunatelly, currently there's only command for dropping both schema and all data. You'll have to use the following HTTP call (or use the query directly in Ratel dashboard, since it uses HTTP communication):

curl -X POST localhost:8080/alter -d '{"drop_all": true}'

There's also possibility to drop a predicate:

curl -X POST localhost:8080/alter -d '{"drop_attr": "your_predicate_name"}'