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  }