Compare commits

...

3 commits

Author SHA1 Message Date
c1f6ef07d4
Skip test cases when client creation fails
Updated the client creation check to skip test cases if the client cannot be created, instead of marking them as errors. This ensures tests dependent on a successful client creation do not fail unnecessarily but are instead skipped.
2024-09-27 17:09:00 +02:00
6e98d7e47d
Reduce message loop iterations and add XOAUTH2 tests
Loop iterations in `client_test.go` were reduced from 50 to 20 for efficiency. Added new tests to verify XOAUTH2 authentication support and error handling by simulating SMTP server responses.
2024-09-27 17:00:21 +02:00
8791ce5a33
Fix deferred mutex unlock in TLSConnectionState
Correct the sequence of mutex unlocking in TLSConnectionState to ensure the mutex is always released properly. This prevents potential deadlocks and ensures the function behaves as expected in a concurrent context.
2024-09-27 17:00:07 +02:00
2 changed files with 77 additions and 4 deletions

View file

@ -1735,7 +1735,7 @@ func TestClient_DialSendConcurrent_online(t *testing.T) {
client, err := getTestConnection(true)
if err != nil {
t.Errorf("unable to create new client: %s", err)
t.Skipf("failed to create test client: %s. Skipping tests", err)
}
var messages []*Msg
@ -1799,7 +1799,7 @@ func TestClient_DialSendConcurrent_local(t *testing.T) {
}
var messages []*Msg
for i := 0; i < 50; i++ {
for i := 0; i < 20; i++ {
message := NewMsg()
if err := message.From("valid-from@domain.tld"); err != nil {
t.Errorf("failed to set FROM address: %s", err)
@ -2021,6 +2021,72 @@ func getTestConnectionWithDSN(auth bool) (*Client, error) {
}
func TestXOAuth2OK(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
serverPort := TestServerPortBase + 30
featureSet := "250-AUTH XOAUTH2\r\n250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, featureSet, false, serverPort); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 500)
c, err := NewClient("127.0.0.1",
WithPort(serverPort),
WithTLSPortPolicy(TLSOpportunistic),
WithSMTPAuth(SMTPAuthXOAUTH2),
WithUsername("user"),
WithPassword("token"))
if err != nil {
t.Fatalf("unable to create new client: %v", err)
}
if err = c.DialWithContext(context.Background()); err != nil {
t.Fatalf("unexpected dial error: %v", err)
}
if err = c.Close(); err != nil {
t.Fatalf("disconnect from test server failed: %v", err)
}
}
func TestXOAuth2Unsupported(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
serverPort := TestServerPortBase + 31
featureSet := "250-AUTH LOGIN PLAIN\r\n250-8BITMIME\r\n250-DSN\r\n250 SMTPUTF8"
go func() {
if err := simpleSMTPServer(ctx, featureSet, false, serverPort); err != nil {
t.Errorf("failed to start test server: %s", err)
return
}
}()
time.Sleep(time.Millisecond * 500)
c, err := NewClient("127.0.0.1",
WithPort(serverPort),
WithTLSPolicy(TLSOpportunistic),
WithSMTPAuth(SMTPAuthXOAUTH2),
WithUsername("user"),
WithPassword("token"))
if err != nil {
t.Fatalf("unable to create new client: %v", err)
}
if err = c.DialWithContext(context.Background()); err == nil {
t.Fatal("expected dial error got nil")
} else {
if !errors.Is(err, ErrXOauth2AuthNotSupported) {
t.Fatalf("expected %v; got %v", ErrXOauth2AuthNotSupported, err)
}
}
if err = c.Close(); err != nil {
t.Fatalf("disconnect from test server failed: %v", err)
}
}
func TestXOAuth2OK_faker(t *testing.T) {
server := []string{
"220 Fake server ready ESMTP",
"250-fake.server",
@ -2060,7 +2126,7 @@ func TestXOAuth2OK(t *testing.T) {
}
}
func TestXOAuth2Unsupported(t *testing.T) {
func TestXOAuth2Unsupported_faker(t *testing.T) {
server := []string{
"220 Fake server ready ESMTP",
"250-fake.server",
@ -2231,6 +2297,13 @@ func handleTestServerConnection(connection net.Conn, featureSet string, failRese
break
}
writeOK()
case strings.HasPrefix(data, "AUTH XOAUTH2"):
auth := strings.TrimPrefix(data, "AUTH XOAUTH2 ")
if !strings.EqualFold(auth, "dXNlcj11c2VyAWF1dGg9QmVhcmVyIHRva2VuAQE=") {
_ = writeLine("535 5.7.8 Error: authentication failed")
break
}
_ = writeLine("235 2.7.0 Authentication successful")
case strings.HasPrefix(data, "AUTH PLAIN"):
auth := strings.TrimPrefix(data, "AUTH PLAIN ")
if !strings.EqualFold(auth, "AHRvbmlAdGVzdGVyLmNvbQBWM3J5UzNjcjN0Kw==") {

View file

@ -209,13 +209,13 @@ func (c *Client) StartTLS(config *tls.Config) error {
// not succeed.
func (c *Client) TLSConnectionState() (state tls.ConnectionState, ok bool) {
c.mutex.RLock()
defer c.mutex.RUnlock()
tc, ok := c.conn.(*tls.Conn)
if !ok {
return
}
state, ok = tc.ConnectionState(), true
c.mutex.RUnlock()
return
}