package main import ( "bytes" "crypto/tls" "fmt" "log" "net/smtp" ) type TransportCtx struct { Config SmtpConfig Address string Auth *smtp.Auth Tls *tls.Config Client *smtp.Client } func NewTransport(config SmtpConfig) *TransportCtx { ctx := TransportCtx{} ctx.Config = config ctx.Address = fmt.Sprintf("%s:%d", config.Hostname, config.Port) ctx.Auth = NewTransportAuth(config) ctx.Tls = NewTransportTls(config) return &ctx } func NewTransportAuth(config SmtpConfig) *smtp.Auth { switch config.AuthType { case "plain": auth := smtp.PlainAuth( "", config.Username, config.Password, config.Hostname, ) return &auth case "login": auth := LoginAuth(config.Username, config.Password) return &auth default: } return nil } func NewTransportTls(config SmtpConfig) *tls.Config { // TLS config return &tls.Config{ InsecureSkipVerify: true, ServerName: config.Hostname, } } func (ctx *TransportCtx) DialInsecure() { // no SSL/TLS c, err := smtp.Dial(ctx.Address) if err != nil { log.Panic(err) } ctx.Client = c } func (ctx *TransportCtx) DialTls() { conn, err := tls.Dial("tcp", ctx.Address, ctx.Tls) if err != nil { log.Panic(err) } c, err := smtp.NewClient(conn, ctx.Config.Hostname) if err != nil { log.Panic(err) } ctx.Client = c } func (ctx *TransportCtx) DialStartTls() { c, err := smtp.Dial(ctx.Address) if err != nil { log.Panic(err) } c.StartTLS(ctx.Tls) ctx.Client = c } func (ctx *TransportCtx) Dial() { switch ctx.Config.SecurityType { case "tls": ctx.DialTls() case "starttls": ctx.DialStartTls() default: ctx.DialInsecure() } } func (ctx *TransportCtx) Authenticate() { err := ctx.Client.Auth(*ctx.Auth) if err != nil { log.Panic(err) } } func (ctx *TransportCtx) Quit() { ctx.Client.Quit() } func (ctx *TransportCtx) Send(email *EmailCtx) { // Set email header ctx.Client.Mail(email.Headers["From"]) ctx.Client.Rcpt(email.Headers["To"]) // Set email body wc, err := ctx.Client.Data() if err != nil { log.Panic(err) } defer wc.Close() buffer := bytes.NewBufferString(email.String()) if _, err = buffer.WriteTo(wc); err != nil { log.Panic(err) } return }