Merge pull request #163 from stapelberg/starttls
smtp: STARTTLS before querying auth mechanisms
This commit is contained in:
commit
685b24b7b4
|
@ -516,9 +516,9 @@ func writeEmailBodyWithTime(w io.Writer, from, to, status string, a *Alert, mome
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSMTPAuth(hasAuth bool, mechs string) (smtp.Auth, *tls.Config, error) {
|
func getSMTPAuth(hasAuth bool, mechs string) (smtp.Auth, error) {
|
||||||
if !hasAuth {
|
if !hasAuth {
|
||||||
return nil, nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
username := os.Getenv("SMTP_AUTH_USERNAME")
|
username := os.Getenv("SMTP_AUTH_USERNAME")
|
||||||
|
@ -530,7 +530,7 @@ func getSMTPAuth(hasAuth bool, mechs string) (smtp.Auth, *tls.Config, error) {
|
||||||
if secret == "" {
|
if secret == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return smtp.CRAMMD5Auth(username, secret), nil, nil
|
return smtp.CRAMMD5Auth(username, secret), nil
|
||||||
case "PLAIN":
|
case "PLAIN":
|
||||||
password := os.Getenv("SMTP_AUTH_PASSWORD")
|
password := os.Getenv("SMTP_AUTH_PASSWORD")
|
||||||
if password == "" {
|
if password == "" {
|
||||||
|
@ -541,15 +541,14 @@ func getSMTPAuth(hasAuth bool, mechs string) (smtp.Auth, *tls.Config, error) {
|
||||||
// We need to know the hostname for both auth and TLS.
|
// We need to know the hostname for both auth and TLS.
|
||||||
host, _, err := net.SplitHostPort(*smtpSmartHost)
|
host, _, err := net.SplitHostPort(*smtpSmartHost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("invalid address: %s", err)
|
return nil, fmt.Errorf("invalid address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
auth := smtp.PlainAuth(identity, username, password, host)
|
auth := smtp.PlainAuth(identity, username, password, host)
|
||||||
cfg := &tls.Config{ServerName: host}
|
return auth, nil
|
||||||
return auth, cfg, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *notifier) sendEmailNotification(to string, op notificationOp, a *Alert) error {
|
func (n *notifier) sendEmailNotification(to string, op notificationOp, a *Alert) error {
|
||||||
|
@ -567,16 +566,21 @@ func (n *notifier) sendEmailNotification(to string, op notificationOp, a *Alert)
|
||||||
}
|
}
|
||||||
defer c.Quit()
|
defer c.Quit()
|
||||||
|
|
||||||
// Authenticate if we and the server are both configured for it.
|
// We need to know the hostname for both auth and TLS.
|
||||||
auth, tlsConfig, err := getSMTPAuth(c.Extension("AUTH"))
|
host, _, err := net.SplitHostPort(*smtpSmartHost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("invalid address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsConfig != nil {
|
tlsConfig := &tls.Config{ServerName: host}
|
||||||
if err := c.StartTLS(tlsConfig); err != nil {
|
if err := c.StartTLS(tlsConfig); err != nil {
|
||||||
return fmt.Errorf("starttls failed: %s", err)
|
return fmt.Errorf("starttls failed: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authenticate if we and the server are both configured for it.
|
||||||
|
auth, err := getSMTPAuth(c.Extension("AUTH"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if auth != nil {
|
if auth != nil {
|
||||||
|
|
|
@ -15,7 +15,6 @@ package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
|
@ -85,7 +84,7 @@ type authTestCase struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *authTestCase) test(t *testing.T) {
|
func (tc *authTestCase) test(t *testing.T) {
|
||||||
auth, cfg, err := getSMTPAuth(tc.hasAuth, tc.mechs)
|
auth, err := getSMTPAuth(tc.hasAuth, tc.mechs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tc.fail(t, "unexpected error: %s", err)
|
tc.fail(t, "unexpected error: %s", err)
|
||||||
return
|
return
|
||||||
|
@ -94,21 +93,10 @@ func (tc *authTestCase) test(t *testing.T) {
|
||||||
if auth != nil {
|
if auth != nil {
|
||||||
tc.fail(t, "expected auth to be nil, got %T", auth)
|
tc.fail(t, "expected auth to be nil, got %T", auth)
|
||||||
}
|
}
|
||||||
if cfg != nil {
|
|
||||||
tc.fail(t, "expected tls config to be nil, got %v", cfg)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if fmt.Sprintf("%T", auth) != tc.expAuthType {
|
if fmt.Sprintf("%T", auth) != tc.expAuthType {
|
||||||
tc.fail(t, "expected auth to be %s, got %T", tc.expAuthType, auth)
|
tc.fail(t, "expected auth to be %s, got %T", tc.expAuthType, auth)
|
||||||
}
|
}
|
||||||
if tc.expAuthType == "*smtp.plainAuth" {
|
|
||||||
if cfg == nil {
|
|
||||||
tc.fail(t, "expected tls config")
|
|
||||||
} else if cfg.ServerName != "testSMTPHost" {
|
|
||||||
tc.fail(t, "expected tls config to be %v, got %v",
|
|
||||||
&tls.Config{ServerName: "testSMTPHost"}, cfg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +167,8 @@ func TestGetSMTPAuth(t *testing.T) {
|
||||||
{true, "PLAIN", ""},
|
{true, "PLAIN", ""},
|
||||||
})
|
})
|
||||||
os.Setenv("SMTP_AUTH_PASSWORD", "p")
|
os.Setenv("SMTP_AUTH_PASSWORD", "p")
|
||||||
if auth, cfg, err := getSMTPAuth(true, "PLAIN"); err == nil {
|
if auth, err := getSMTPAuth(true, "PLAIN"); err == nil {
|
||||||
t.Errorf("PLAIN auth with bad host-port: expected error but got %T, %v", auth, cfg)
|
t.Errorf("PLAIN auth with bad host-port: expected error but got %T", auth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue