Browse Source

Support SMTP Auth Plain

Bishtawi 7 months ago
parent
commit
112efaae90
2 changed files with 38 additions and 6 deletions
  1. 16 6
      server/smtp_server.go
  2. 22 0
      server/smtp_server_test.go

+ 16 - 6
server/smtp_server.go

@@ -70,15 +70,20 @@ func (b *smtpBackend) Counts() (total int64, success int64, failure int64) {
 
 // smtpSession is returned after EHLO.
 type smtpSession struct {
-	backend *smtpBackend
-	conn    *smtp.Conn
-	topic   string
-	token   string
-	mu      sync.Mutex
+	backend    *smtpBackend
+	conn       *smtp.Conn
+	topic      string
+	token      string
+	mu         sync.Mutex
+	basic_auth string
 }
 
-func (s *smtpSession) AuthPlain(username, _ string) error {
+func (s *smtpSession) AuthPlain(username, password string) error {
 	logem(s.conn).Field("smtp_username", username).Debug("AUTH PLAIN (with username %s)", username)
+	basic_auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
+	s.mu.Lock()
+	s.basic_auth = basic_auth
+	s.mu.Unlock()
 	return nil
 }
 
@@ -198,6 +203,8 @@ func (s *smtpSession) publishMessage(m *message) error {
 	}
 	if s.token != "" {
 		req.Header.Add("Authorization", "Bearer "+s.token)
+	} else if s.basic_auth != "" {
+		req.Header.Add("Authorization", "Basic "+s.basic_auth)
 	}
 	rr := httptest.NewRecorder()
 	s.backend.handler(rr, req)
@@ -214,6 +221,9 @@ func (s *smtpSession) Reset() {
 }
 
 func (s *smtpSession) Logout() error {
+	s.mu.Lock()
+	s.basic_auth = ""
+	s.mu.Unlock()
 	return nil
 }
 

+ 22 - 0
server/smtp_server_test.go

@@ -1386,6 +1386,28 @@ what's up
 	writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued")
 }
 
+func TestSmtpBackend_PlaintextWithPlainAuth(t *testing.T) {
+	email := `EHLO example.com
+AUTH PLAIN dGVzdAB0ZXN0ADEyMzQ=
+MAIL FROM: phil@example.com
+RCPT TO: ntfy-mytopic@ntfy.sh
+DATA
+Subject: Very short mail
+
+what's up
+.
+`
+	s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) {
+		require.Equal(t, "/mytopic", r.URL.Path)
+		require.Equal(t, "Very short mail", r.Header.Get("Title"))
+		require.Equal(t, "Basic dGVzdDoxMjM0", r.Header.Get("Authorization"))
+		require.Equal(t, "what's up", readAll(t, r.Body))
+	})
+	defer s.Close()
+	defer c.Close()
+	writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued")
+}
+
 type smtpHandlerFunc func(http.ResponseWriter, *http.Request)
 
 func newTestSMTPServer(t *testing.T, handler smtpHandlerFunc) (s *smtp.Server, c net.Conn, conf *Config, scanner *bufio.Scanner) {