Skip to content

Commit c9c8a3b

Browse files
authored
Merge pull request #429 from wneessen/bug/428_smtpauthcustom-setsmtpauth-doesnt-appear-to-be-effectual
Fix regression of custom smtp.Auth not working. Closes #428
2 parents 9920ddb + 2c2c977 commit c9c8a3b

File tree

4 files changed

+140
-3
lines changed

4 files changed

+140
-3
lines changed

.golangci.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## SPDX-License-Identifier: MIT
44

55
[run]
6-
go = "1.23"
6+
go = "1.24"
77
tests = true
88
exclude-dirs = ["examples"]
99

client.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,9 @@ func (c *Client) Send(messages ...*Msg) (returnErr error) {
12301230
// or if the authentication process fails.
12311231
func (c *Client) auth(client *smtp.Client, isEnc bool) error {
12321232
var smtpAuth smtp.Auth
1233+
if c.smtpAuthType == SMTPAuthCustom {
1234+
smtpAuth = c.smtpAuth
1235+
}
12331236
if c.smtpAuth == nil && c.smtpAuthType != SMTPAuthNoAuth {
12341237
hasSMTPAuth, smtpAuthType := client.Extension("AUTH")
12351238
if !hasSMTPAuth {

client_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,6 +2630,107 @@ func TestClient_auth(t *testing.T) {
26302630
t.Fatalf("client should have failed to connect")
26312631
}
26322632
})
2633+
// https://github.com/wneessen/go-mail/issues/428
2634+
t.Run("auth with custom auth type should succeed", func(t *testing.T) {
2635+
ctx, cancel := context.WithCancel(context.Background())
2636+
defer cancel()
2637+
PortAdder.Add(1)
2638+
serverPort := int(TestServerPortBase + PortAdder.Load())
2639+
featureSet := "250-AUTH CUSTOM\r\n250-8BITMIME\r\n250-STARTTLS\r\n250-DSN\r\n250 SMTPUTF8"
2640+
go func() {
2641+
if err := simpleSMTPServer(ctx, t, &serverProps{
2642+
FeatureSet: featureSet,
2643+
ListenPort: serverPort,
2644+
}); err != nil {
2645+
t.Errorf("failed to start test server: %s", err)
2646+
return
2647+
}
2648+
}()
2649+
time.Sleep(time.Millisecond * 30)
2650+
2651+
ctxDial, cancelDial := context.WithTimeout(ctx, time.Millisecond*500)
2652+
t.Cleanup(cancelDial)
2653+
2654+
message := testMessage(t)
2655+
client, err := NewClient(DefaultHost, WithPort(serverPort),
2656+
WithTLSPolicy(TLSMandatory), WithSMTPAuthCustom(newTestCustomAuth()), WithTLSConfig(&tlsConfig),
2657+
WithUsername("test"), WithPassword("password"))
2658+
if err != nil {
2659+
t.Fatalf("failed to create new client: %s", err)
2660+
}
2661+
if err = client.DialWithContext(ctxDial); err != nil {
2662+
t.Fatalf("failed to connect to test server: %s", err)
2663+
}
2664+
if err = client.Send(message); err != nil {
2665+
t.Errorf("failed to send message: %s", err)
2666+
}
2667+
})
2668+
// https://github.com/wneessen/go-mail/issues/428
2669+
t.Run("auth with custom auth type should fail", func(t *testing.T) {
2670+
ctx, cancel := context.WithCancel(context.Background())
2671+
defer cancel()
2672+
PortAdder.Add(1)
2673+
serverPort := int(TestServerPortBase + PortAdder.Load())
2674+
featureSet := "250-AUTH UNKNOWN\r\n250-8BITMIME\r\n250-STARTTLS\r\n250-DSN\r\n250 SMTPUTF8"
2675+
go func() {
2676+
if err := simpleSMTPServer(ctx, t, &serverProps{
2677+
FeatureSet: featureSet,
2678+
ListenPort: serverPort,
2679+
}); err != nil {
2680+
t.Errorf("failed to start test server: %s", err)
2681+
return
2682+
}
2683+
}()
2684+
time.Sleep(time.Millisecond * 30)
2685+
2686+
ctxDial, cancelDial := context.WithTimeout(ctx, time.Millisecond*500)
2687+
t.Cleanup(cancelDial)
2688+
2689+
client, err := NewClient(DefaultHost, WithPort(serverPort),
2690+
WithTLSPolicy(TLSMandatory), WithSMTPAuthCustom(newTestCustomAuth()), WithTLSConfig(&tlsConfig),
2691+
WithUsername("test"), WithPassword("password"))
2692+
if err != nil {
2693+
t.Fatalf("failed to create new client: %s", err)
2694+
}
2695+
if err = client.DialWithContext(ctxDial); err == nil {
2696+
t.Fatalf("client should have failed to connect")
2697+
}
2698+
})
2699+
// https://github.com/wneessen/go-mail/issues/428
2700+
t.Run("auth with custom auth type overridden by SetCustomAuth", func(t *testing.T) {
2701+
ctx, cancel := context.WithCancel(context.Background())
2702+
defer cancel()
2703+
PortAdder.Add(1)
2704+
serverPort := int(TestServerPortBase + PortAdder.Load())
2705+
featureSet := "250-AUTH CUSTOM\r\n250-8BITMIME\r\n250-STARTTLS\r\n250-DSN\r\n250 SMTPUTF8"
2706+
go func() {
2707+
if err := simpleSMTPServer(ctx, t, &serverProps{
2708+
FeatureSet: featureSet,
2709+
ListenPort: serverPort,
2710+
}); err != nil {
2711+
t.Errorf("failed to start test server: %s", err)
2712+
return
2713+
}
2714+
}()
2715+
time.Sleep(time.Millisecond * 30)
2716+
2717+
ctxDial, cancelDial := context.WithTimeout(ctx, time.Millisecond*500)
2718+
t.Cleanup(cancelDial)
2719+
2720+
message := testMessage(t)
2721+
client, err := NewClient(DefaultHost, WithPort(serverPort),
2722+
WithTLSPolicy(TLSMandatory), WithSMTPAuth(SMTPAuthPlain), WithTLSConfig(&tlsConfig))
2723+
if err != nil {
2724+
t.Fatalf("failed to create new client: %s", err)
2725+
}
2726+
client.SetSMTPAuthCustom(newTestCustomAuth())
2727+
if err = client.DialWithContext(ctxDial); err != nil {
2728+
t.Fatalf("failed to connect to test server: %s", err)
2729+
}
2730+
if err = client.Send(message); err != nil {
2731+
t.Errorf("failed to send message: %s", err)
2732+
}
2733+
})
26332734
}
26342735

26352736
func TestClient_authTypeAutoDiscover(t *testing.T) {
@@ -3913,6 +4014,39 @@ func (t *testSender) Send(ctx context.Context, m *Msg) error {
39134014
return nil
39144015
}
39154016

4017+
// testCustomAuth is a custom authentication mechanism implementation that satisfies the smtp.Auth
4018+
// interface. It is used to test the SMTPAuthCustom type.
4019+
type testCustomAuth struct{}
4020+
4021+
// newTestCustomAuth initializes and returns a new testCustomAuth instance for use in testing
4022+
// custom authentication.
4023+
func newTestCustomAuth() *testCustomAuth {
4024+
return &testCustomAuth{}
4025+
}
4026+
4027+
// Start begins the custom authentication process, verifying if the "CUSTOM" method is supported
4028+
// by the SMTP server.
4029+
func (a *testCustomAuth) Start(info *smtp.ServerInfo) (proto string, toServer []byte, err error) {
4030+
if len(info.Auth) > 0 {
4031+
supported := false
4032+
for _, method := range info.Auth {
4033+
if method == "CUSTOM" {
4034+
supported = true
4035+
}
4036+
}
4037+
if !supported {
4038+
return "", nil, fmt.Errorf("custom auth method not supported")
4039+
}
4040+
}
4041+
return "CUSTOM", nil, nil
4042+
}
4043+
4044+
// Next processes the next step in the authentication exchange, returning data to send to the server
4045+
// or an error.
4046+
func (a *testCustomAuth) Next([]byte, bool) (toServer []byte, err error) {
4047+
return nil, nil
4048+
}
4049+
39164050
// parseJSONLog parses a JSON encoded log from the provided buffer and returns a slice of logLine structs.
39174051
// In case of a decode error, it reports the error to the testing framework.
39184052
func parseJSONLog(t *testing.T, buf *bytes.Buffer) logData {

msg_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7314,7 +7314,7 @@ func (mw uppercaseMiddleware) Handle(m *Msg) *Msg {
73147314
if !ok {
73157315
fmt.Println("can't find the subject header")
73167316
}
7317-
if s == nil || len(s) < 1 {
7317+
if len(s) < 1 {
73187318
s = append(s, "")
73197319
}
73207320
m.Subject(strings.ToUpper(s[0]))
@@ -7335,7 +7335,7 @@ func (mw encodeMiddleware) Handle(m *Msg) *Msg {
73357335
if !ok {
73367336
fmt.Println("can't find the subject header")
73377337
}
7338-
if s == nil || len(s) < 1 {
7338+
if len(s) < 1 {
73397339
s = append(s, "")
73407340
}
73417341
m.Subject(strings.Replace(s[0], "a", "@", -1))

0 commit comments

Comments
 (0)