diff options
| author | Gab Virebent <gabriel1@virebent.art> | 2026-08-24 17:34:45 +0200 |
|---|---|---|
| committer | Gab Virebent <gabriel1@virebent.art> | 2026-08-24 17:34:45 +0200 |
| commit | e9fbbe3373eb66a345f5e3829e2563b94dc92051 (patch) | |
| tree | 950d75fda88574afb46b4aeab36e96f3c089a3bb /internal/smtpclient/client_test.go | |
| parent | fb83c4d70616ec23d8a5397409a5d31c70b70d66 (diff) | |
| download | n2usenet-main.tar.gz n2usenet-main.tar.xz n2usenet-main.zip | |
Diffstat (limited to 'internal/smtpclient/client_test.go')
| -rw-r--r-- | internal/smtpclient/client_test.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/internal/smtpclient/client_test.go b/internal/smtpclient/client_test.go index d9eec6d..e91d128 100644 --- a/internal/smtpclient/client_test.go +++ b/internal/smtpclient/client_test.go @@ -3,6 +3,7 @@ package smtpclient import ( "bufio" "context" + "encoding/base64" "net" "strings" "testing" @@ -91,3 +92,101 @@ func TestSendUsesConfiguredEnvelopeFrom(t *testing.T) { t.Fatal("configured envelope sender was not used") } } + +func TestSessionAuthPlain(t *testing.T) { + server, client := net.Pipe() + defer client.Close() + + command := make(chan string, 1) + go func() { + defer server.Close() + r := bufio.NewReader(server) + line, err := r.ReadString('\n') + if err != nil { + command <- "" + return + } + command <- line + _, _ = server.Write([]byte("235 2.7.0 authentication successful\r\n")) + }() + + session := newSession(client) + if err := session.authPlain("n2usenet@virebent.art", "test-password"); err != nil { + t.Fatalf("authPlain returned error: %v", err) + } + + line := <-command + const prefix = "AUTH PLAIN " + if !strings.HasPrefix(line, prefix) { + t.Fatalf("unexpected AUTH command: %q", line) + } + token := strings.TrimSpace(strings.TrimPrefix(line, prefix)) + decoded, err := base64.StdEncoding.DecodeString(token) + if err != nil { + t.Fatalf("decode AUTH payload: %v", err) + } + if got, want := string(decoded), "\x00n2usenet@virebent.art\x00test-password"; got != want { + t.Fatalf("unexpected AUTH payload: got %q want %q", got, want) + } +} + +func TestSessionAuthPlainRejectsNUL(t *testing.T) { + session := &session{} + if err := session.authPlain("n2usenet\x00admin", "test-password"); err == nil { + t.Fatal("authPlain accepted a username containing NUL") + } + if err := session.authPlain("n2usenet", "test\x00password"); err == nil { + t.Fatal("authPlain accepted a password containing NUL") + } +} + +func TestCheckDoesNotStartMailTransaction(t *testing.T) { + server, client := net.Pipe() + defer client.Close() + + commands := make(chan string, 8) + go func() { + defer close(commands) + defer server.Close() + r := bufio.NewReader(server) + w := bufio.NewWriter(server) + _, _ = w.WriteString("220 test\r\n") + _ = w.Flush() + for { + line, err := r.ReadString('\n') + if err != nil { + return + } + commands <- line + switch { + case strings.HasPrefix(line, "EHLO "): + _, _ = w.WriteString("250 test\r\n") + case strings.HasPrefix(line, "QUIT"): + _, _ = w.WriteString("221 bye\r\n") + _ = w.Flush() + return + default: + _, _ = w.WriteString("500 unexpected\r\n") + } + _ = w.Flush() + } + }() + + mailer := New(Config{ + Host: "mail.virebent.art", + Port: 25, + HELO: "n2usenet.virebent.art", + RequireTLS: false, + Timeout: 5 * time.Second, + }, func(context.Context, string, string) (net.Conn, error) { + return client, nil + }) + if err := mailer.Check(context.Background()); err != nil { + t.Fatalf("Check returned error: %v", err) + } + for command := range commands { + if strings.HasPrefix(command, "MAIL ") || strings.HasPrefix(command, "RCPT ") || strings.HasPrefix(command, "DATA") { + t.Fatalf("health check started a mail transaction: %q", command) + } + } +} |
