mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: support optional SMTP auth (#14533)
This commit is contained in:
@ -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 {
|
||||
|
@ -203,7 +203,6 @@ func TestSMTP(t *testing.T) {
|
||||
retryable: false,
|
||||
},
|
||||
{
|
||||
// No auth, no problem!
|
||||
name: "No auth mechanisms supported, none configured",
|
||||
authMechs: []string{},
|
||||
cfg: codersdk.NotificationsEmailConfig{
|
||||
@ -213,6 +212,16 @@ func TestSMTP(t *testing.T) {
|
||||
toAddrs: []string{to},
|
||||
expectedAuthMeth: "",
|
||||
},
|
||||
{
|
||||
name: "Auth mechanisms supported optionally, none configured",
|
||||
authMechs: []string{sasl.Login, sasl.Plain},
|
||||
cfg: codersdk.NotificationsEmailConfig{
|
||||
Hello: hello,
|
||||
From: from,
|
||||
},
|
||||
toAddrs: []string{to},
|
||||
expectedAuthMeth: "",
|
||||
},
|
||||
/**
|
||||
* TLS connections
|
||||
*/
|
||||
|
Reference in New Issue
Block a user