feat: support optional SMTP auth (#14533)

This commit is contained in:
Danny Kopping
2024-09-03 11:51:34 +02:00
committed by GitHub
parent 0eca1fcb8b
commit f23a05075e
2 changed files with 27 additions and 5 deletions

View File

@ -53,7 +53,8 @@ type SMTPHandler struct {
cfg codersdk.NotificationsEmailConfig
log slog.Logger
loginWarnOnce sync.Once
noAuthWarnOnce sync.Once
loginWarnOnce sync.Once
helpers template.FuncMap
}
@ -136,14 +137,20 @@ func (s *SMTPHandler) dispatch(subject, htmlBody, plainBody, to string) Delivery
// Check for authentication capabilities.
if ok, avail := c.Extension("AUTH"); ok {
// Ensure the auth mechanisms available are ones we can use.
// Ensure the auth mechanisms available are ones we can use, and create a SASL client.
auth, err := s.auth(ctx, avail)
if err != nil {
return true, xerrors.Errorf("determine auth mechanism: %w", err)
}
// If so, use the auth mechanism to authenticate.
if auth != nil {
if auth == nil {
// If we get here, no SASL client (which handles authentication) was returned.
// This is expected if auth is supported by the smarthost BUT no authentication details were configured.
s.noAuthWarnOnce.Do(func() {
s.log.Warn(ctx, "skipping auth; no authentication client created")
})
} else {
// We have a SASL client, use it to authenticate.
if err := c.Auth(auth); err != nil {
return true, xerrors.Errorf("%T auth: %w", auth, err)
}
@ -431,6 +438,12 @@ func (s *SMTPHandler) loadCertificate() (*tls.Certificate, error) {
func (s *SMTPHandler) auth(ctx context.Context, mechs string) (sasl.Client, error) {
username := s.cfg.Auth.Username.String()
// All auth mechanisms require username, so if one is not defined then don't return an auth client.
if username == "" {
// nolint:nilnil // This is a valid response.
return nil, nil
}
var errs error
list := strings.Split(mechs, " ")
for _, mech := range list {