-
-
Save chrisgillis/10888032 to your computer and use it in GitHub Desktop.
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() | |
} |
Please note, this example is prone to man-in-the-middle attacks. InsecureSkipVerify
must be set to false,
otherwise the server certificate is not being verified. Thus, a mitm attacker can just present any (e.g. self-signed) certificate and the client will silently accept and connect. You don't want that!
See also https://golang.org/pkg/crypto/tls/#Config
You should also add the date header, in order to be conform with RFC 5322:
headers["Date"] = time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700")
Thanks for the example!
thanks a lot @chrisgillis & @cddmp
Works perfectly, thanks for sharing
You can lose the annoying Go Vet warnings about composite literal using unkeyed fields by:-
from := mail.Address{Name:"", Address:"username@example.tld"}
to := mail.Address{Name:"", Address:"username@anotherexample.tld"}
This worked for me. Thanks a lot
Awesome, thanks for this!
This indeed works.
Appreaciated.
Generational answer 🫡
Passed on from debugger to debugger
Work well.
Works great!
Thanks a lot
This worked great for fastmail.com STMP. My tls config didn't require the insecure verify as well:
// TLS config
tlsconfig := &tls.Config{
ServerName: host,
}
In case someone finds it useful, to send a HTML body, add the following headers:
body := "<html><body><h1>Hello World!</h1></body></html>"
headers["MIME-Version"] = "1.0"
headers["Content-Type"] = "text/html; charset=UTF-8"
Please verify if you are using correct port