Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Golang SSL SMTP Example
package main
import (
"fmt"
"log"
"net"
"net/mail"
"net/smtp"
"crypto/tls"
)
// SSL/TLS Email Example
func main() {
from := mail.Address{"", "username@example.tld"}
to := mail.Address{"", "username@anotherexample.tld"}
subj := "This is the email subject"
body := "This is an example body.\n With two lines."
// Setup headers
headers := make(map[string]string)
headers["From"] = from.String()
headers["To"] = to.String()
headers["Subject"] = subj
// Setup message
message := ""
for k,v := range headers {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + body
// Connect to the SMTP Server
servername := "smtp.example.tld:465"
host, _, _ := net.SplitHostPort(servername)
auth := smtp.PlainAuth("","username@example.tld", "password", host)
// TLS config
tlsconfig := &tls.Config {
InsecureSkipVerify: true,
ServerName: host,
}
// Here is the key, you need to call tls.Dial instead of smtp.Dial
// for smtp servers running on 465 that require an ssl connection
// from the very beginning (no starttls)
conn, err := tls.Dial("tcp", servername, tlsconfig)
if err != nil {
log.Panic(err)
}
c, err := smtp.NewClient(conn, host)
if err != nil {
log.Panic(err)
}
// Auth
if err = c.Auth(auth); err != nil {
log.Panic(err)
}
// To && From
if err = c.Mail(from.Address); err != nil {
log.Panic(err)
}
if err = c.Rcpt(to.Address); err != nil {
log.Panic(err)
}
// Data
w, err := c.Data()
if err != nil {
log.Panic(err)
}
_, err = w.Write([]byte(message))
if err != nil {
log.Panic(err)
}
err = w.Close()
if err != nil {
log.Panic(err)
}
c.Quit()
}

horrido commented Aug 16, 2014

This is a wonderful example you've provided. (Thank you very much!) However, it doesn't work. I get the following error message:

2014/08/16 07:44:45 tls: first record does not look like a TLS handshake
panic: tls: first record does not look like a TLS handshake

goroutine 16 [running]:
runtime.panic(0x18d660, 0xc2080005a0)
/usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
log.Panic(0x671e30, 0x1, 0x1)
/usr/local/go/src/pkg/log/log.go:307 +0xb6
main.main()
/Users/richardeng/fred.go:52 +0x7a9

Line 52, as in your example, refers to the tls.Dial() call. What's wrong??

(FYI, the servername I'm using is "smtp.gmail.com:587".)

Thanks for the great example! Worked for me "out of the box" using AWS SES.

Thanks a bunch, Chris. Very useful.

@horrido: Didn't work for me either on gmail (same error message). I don't know why, but it worked fine with the two other mail services I tried it with. It's weird that it doesn't work with Gmail, of all services!

Which mail services does it work with?

It works for Gmail out of the box, thanks!

This rocks. Thank you. Ps. If you are using rackspace email, this will help with what servers to use http://www.rackspace.com/apps/support/portal/1088

alecha commented Jul 10, 2015

Works with Amazon SES only if using port 465, thanks ;)

arteev commented Aug 9, 2015

It works for Yandex. Thanks!

This was very useful, thank you.

Curious, why are you disabling peer verification? (https://gist.github.com/chrisgillis/10888032#file-ssl_smtp_example-go-L43) That allows MitM and sort of obviates the whole point of forcing TLS.
Btw, the example here: https://golang.org/pkg/net/smtp/#example_SendMail (Example/SendMail) is much shorter, and if used with Amazon SES endpoint specified as port 587, will use StartTLS.

Hi Dave,
Someone just tried to sign in to your Google Account xxxx@gmail.com from an app that doesn't meet modern security standards.

suntong commented May 28, 2016

Thanks for the great example! Worked for me "out of the box" for aliyun.
I avoided gmail because the very problem DaveAppleton mentioned.

How would you integrate attachments into this?

It works for QQ mail, and thanks very very much!

Thanks! Works for smtp.zoho.com

Thanks Works for smtp.mxhichina.com

I am getting "Msg": "first record does not look like a TLS handshake", using office365 (smtp.office365.com:587)

Nice

@cruiz1391 See the discussion here for a solution using office365
mattermost/platform#954
golang/go#9899
Using the workaround for AUTH LOGIN worked for me.

JIElite commented Feb 2, 2017

Thank you for sharing
It do works for AWS SES!

just modify

  1. servername: endpoint, like: email-smtp.us-west-2.amazonaws.com:465
  2. smtp.PlainAuth username: IAM username
  3. smtp.PlainAuth password: IAM password

Thank you for shaing!

JoelTrottier commented Aug 30, 2017

Referred to this code for sending Yahoo! mail: smtp.mail.yahoo.com:465
Worked as intended. Thanks!

If you get this error:
(#MBR1212) Incorrect username or password.

Make sure you toggle this Account Security option in your Yahoo! account settings:
Allow apps that use less secure sign in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment