Compare commits

..

2 commits

Author SHA1 Message Date
b7ffce62aa
Add TLS connection state tests for SMTP client
Introduce tests to verify TLS connection state handling in the SMTP client. Ensure that normal TLS connections return a valid state, and non-TLS connections do not wrongly indicate a TLS state.
2024-11-09 15:22:23 +01:00
8f28babc47
Add tests for Client StartTLS functionality
Introduce new tests to cover the Client's behavior when initiating a STARTTLS session under different conditions: normal operation, failure on EHLO/HELO, and a server not supporting STARTTLS. This ensures robustness in handling STARTTLS interactions.
2024-11-09 14:58:23 +01:00

View file

@ -1691,6 +1691,182 @@ func TestClient_cmd(t *testing.T) {
}) })
} }
func TestClient_StartTLS(t *testing.T) {
t.Run("normal STARTTLS should succeed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
PortAdder.Add(1)
serverPort := int(TestServerPortBase + PortAdder.Load())
featureSet := "250-STARTTLS\r\n250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, t, &serverProps{
FeatureSet: featureSet,
ListenPort: serverPort,
},
); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 30)
client, err := Dial(fmt.Sprintf("%s:%d", TestServerAddr, serverPort))
if err != nil {
t.Errorf("failed to dial to test server: %s", err)
}
t.Cleanup(func() {
if err = client.Close(); err != nil {
t.Errorf("failed to close client: %s", err)
}
})
tlsConfig := &tls.Config{InsecureSkipVerify: true}
if err = client.StartTLS(tlsConfig); err != nil {
t.Errorf("failed to initialize STARTTLS session: %s", err)
}
})
t.Run("STARTTLS fails on EHLO/HELO", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
PortAdder.Add(1)
serverPort := int(TestServerPortBase + PortAdder.Load())
featureSet := "250-STARTTLS\r\n250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, t, &serverProps{
FailOnEhlo: true,
FailOnHelo: true,
FeatureSet: featureSet,
ListenPort: serverPort,
},
); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 30)
client, err := Dial(fmt.Sprintf("%s:%d", TestServerAddr, serverPort))
if err != nil {
t.Errorf("failed to dial to test server: %s", err)
}
t.Cleanup(func() {
if err = client.Close(); err != nil {
t.Errorf("failed to close client: %s", err)
}
})
tlsConfig := &tls.Config{InsecureSkipVerify: true}
if err = client.StartTLS(tlsConfig); err == nil {
t.Error("STARTTLS should fail on EHLO")
}
})
t.Run("STARTTLS fails on server not supporting STARTTLS", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
PortAdder.Add(1)
serverPort := int(TestServerPortBase + PortAdder.Load())
featureSet := "250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, t, &serverProps{
FailOnSTARTTLS: true,
FeatureSet: featureSet,
ListenPort: serverPort,
},
); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 30)
client, err := Dial(fmt.Sprintf("%s:%d", TestServerAddr, serverPort))
if err != nil {
t.Errorf("failed to dial to test server: %s", err)
}
t.Cleanup(func() {
if err = client.Close(); err != nil {
t.Errorf("failed to close client: %s", err)
}
})
tlsConfig := &tls.Config{InsecureSkipVerify: true}
if err = client.StartTLS(tlsConfig); err == nil {
t.Error("STARTTLS should fail for server not supporting it")
}
})
}
func TestClient_TLSConnectionState(t *testing.T) {
t.Run("normal TLS connection should return a state", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
PortAdder.Add(1)
serverPort := int(TestServerPortBase + PortAdder.Load())
featureSet := "250-STARTTLS\r\n250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, t, &serverProps{
FeatureSet: featureSet,
ListenPort: serverPort,
},
); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 30)
client, err := Dial(fmt.Sprintf("%s:%d", TestServerAddr, serverPort))
if err != nil {
t.Errorf("failed to dial to test server: %s", err)
}
t.Cleanup(func() {
if err = client.Close(); err != nil {
t.Errorf("failed to close client: %s", err)
}
})
tlsConfig := &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS12}
if err = client.StartTLS(tlsConfig); err != nil {
t.Errorf("failed to initialize STARTTLS session: %s", err)
}
state, ok := client.TLSConnectionState()
if !ok {
t.Errorf("failed to get TLS connection state")
}
if state.Version < tls.VersionTLS12 {
t.Errorf("TLS connection state version is %d, should be >= %d", state.Version, tls.VersionTLS12)
}
})
t.Run("no TLS state on non-TLS connection", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
PortAdder.Add(1)
serverPort := int(TestServerPortBase + PortAdder.Load())
featureSet := "250-STARTTLS\r\n250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, t, &serverProps{
FeatureSet: featureSet,
ListenPort: serverPort,
},
); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 30)
client, err := Dial(fmt.Sprintf("%s:%d", TestServerAddr, serverPort))
if err != nil {
t.Errorf("failed to dial to test server: %s", err)
}
t.Cleanup(func() {
if err = client.Close(); err != nil {
t.Errorf("failed to close client: %s", err)
}
})
_, ok := client.TLSConnectionState()
if ok {
t.Error("non-TLS connection should not have TLS connection state")
}
})
}
// Issue 17794: don't send a trailing space on AUTH command when there's no password. // Issue 17794: don't send a trailing space on AUTH command when there's no password.
func TestClient_Auth_trimSpace(t *testing.T) { func TestClient_Auth_trimSpace(t *testing.T) {
server := "220 hello world\r\n" + server := "220 hello world\r\n" +