github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/smtp/smtp.go (about) 1 package smtp 2 3 import ( 4 "crypto/tls" 5 "fmt" 6 7 "github.com/caarlos0/env/v9" 8 "github.com/caarlos0/log" 9 "github.com/goreleaser/goreleaser/internal/tmpl" 10 "github.com/goreleaser/goreleaser/pkg/config" 11 "github.com/goreleaser/goreleaser/pkg/context" 12 gomail "gopkg.in/mail.v2" 13 ) 14 15 const ( 16 defaultSubjectTemplate = `{{ .ProjectName }} {{ .Tag }} is out!` 17 defaultBodyTemplate = `You can view details from: {{ .ReleaseURL }}` 18 ) 19 20 type Pipe struct{} 21 22 func (Pipe) String() string { return "smtp" } 23 func (Pipe) Skip(ctx *context.Context) bool { return !ctx.Config.Announce.SMTP.Enabled } 24 25 type Config struct { 26 Host string `env:"SMTP_HOST"` 27 Port int `env:"SMTP_PORT"` 28 Username string `env:"SMTP_USERNAME"` 29 Password string `env:"SMTP_PASSWORD,notEmpty"` 30 } 31 32 func (Pipe) Default(ctx *context.Context) error { 33 if ctx.Config.Announce.SMTP.BodyTemplate == "" { 34 ctx.Config.Announce.SMTP.BodyTemplate = defaultBodyTemplate 35 } 36 37 if ctx.Config.Announce.SMTP.SubjectTemplate == "" { 38 ctx.Config.Announce.SMTP.SubjectTemplate = defaultSubjectTemplate 39 } 40 41 return nil 42 } 43 44 func (Pipe) Announce(ctx *context.Context) error { 45 subject, err := tmpl.New(ctx).Apply(ctx.Config.Announce.SMTP.SubjectTemplate) 46 if err != nil { 47 return fmt.Errorf("SMTP: %w", err) 48 } 49 50 body, err := tmpl.New(ctx).Apply(ctx.Config.Announce.SMTP.BodyTemplate) 51 if err != nil { 52 return fmt.Errorf("SMTP: %w", err) 53 } 54 55 m := gomail.NewMessage() 56 57 // Set E-Mail sender 58 m.SetHeader("From", ctx.Config.Announce.SMTP.From) 59 60 // Set E-Mail receivers 61 receivers := ctx.Config.Announce.SMTP.To 62 m.SetHeader("To", receivers...) 63 64 // Set E-Mail subject 65 m.SetHeader("Subject", subject) 66 67 // Set E-Mail body. You can set plain text or html with text/html 68 m.SetBody("text/plain", body) 69 70 cfg, err := getConfig(ctx.Config.Announce.SMTP) 71 if err != nil { 72 return err 73 } 74 75 // Settings for SMTP server 76 d := gomail.NewDialer(cfg.Host, cfg.Port, cfg.Username, cfg.Password) 77 78 // This is only needed when SSL/TLS certificate is not valid on server. 79 // In production this should be set to false. 80 d.TLSConfig = &tls.Config{InsecureSkipVerify: ctx.Config.Announce.SMTP.InsecureSkipVerify} 81 82 // Now send E-Mail 83 if err := d.DialAndSend(m); err != nil { 84 return fmt.Errorf("SMTP: %w", err) 85 } 86 87 log.Infof("The mail has been send from %s to %s\n", ctx.Config.Announce.SMTP.From, receivers) 88 89 return nil 90 } 91 92 var ( 93 errNoPort = fmt.Errorf("SMTP: missing smtp.port or $SMTP_PORT") 94 errNoUsername = fmt.Errorf("SMTP: missing smtp.username or $SMTP_USERNAME") 95 errNoHost = fmt.Errorf("SMTP: missing smtp.host or $SMTP_HOST") 96 ) 97 98 func getConfig(smtp config.SMTP) (Config, error) { 99 cfg := Config{ 100 Host: smtp.Host, 101 Port: smtp.Port, 102 Username: smtp.Username, 103 } 104 if err := env.Parse(&cfg); err != nil { 105 return cfg, fmt.Errorf("SMTP: %w", err) 106 } 107 if cfg.Username == "" { 108 return cfg, errNoUsername 109 } 110 if cfg.Host == "" { 111 return cfg, errNoHost 112 } 113 if cfg.Port == 0 { 114 return cfg, errNoPort 115 } 116 return cfg, nil 117 }