From 7bebdda27c9a5bcf0f2fbcd861337794e9010730 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Mon, 21 Oct 2024 22:24:21 +0200 Subject: [PATCH 1/3] Add fig.StringUnmarshaler support for SMTPAuthType Implement the fig.StringUnmarshaler interface for SMTPAuthType to map strings to corresponding authentication types. Added comprehensive unit tests to ensure correct functionality for all supported auth type strings. --- auth.go | 36 +++++++++++++++++++++++++++++++++++- auth_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 auth_test.go diff --git a/auth.go b/auth.go index 7888819..314cb50 100644 --- a/auth.go +++ b/auth.go @@ -4,7 +4,11 @@ package mail -import "errors" +import ( + "errors" + "fmt" + "strings" +) // SMTPAuthType is a type wrapper for a string type. It represents the type of SMTP authentication // mechanism to be used. @@ -134,3 +138,33 @@ var ( // authentication type. ErrSCRAMSHA256PLUSAuthNotSupported = errors.New("server does not support SMTP AUTH type: SCRAM-SHA-256-PLUS") ) + +// UnmarshalString satisfies the fig.StringUnmarshaler interface for the SMTPAuthType type +// https://pkg.go.dev/github.com/kkyr/fig#StringUnmarshaler +func (sa *SMTPAuthType) UnmarshalString(value string) error { + switch strings.ToLower(value) { + case "cram-md5", "crammd5", "cram": + *sa = SMTPAuthCramMD5 + case "custom": + *sa = SMTPAuthCustom + case "login": + *sa = SMTPAuthLogin + case "none", "noauth", "no": + *sa = SMTPAuthNoAuth + case "plain": + *sa = SMTPAuthPlain + case "scram-sha-1", "scram-sha1", "scramsha1": + *sa = SMTPAuthSCRAMSHA1 + case "scram-sha-1-plus", "scram-sha1-plus", "scramsha1plus": + *sa = SMTPAuthSCRAMSHA1PLUS + case "scram-sha-256", "scram-sha256", "scramsha256": + *sa = SMTPAuthSCRAMSHA256 + case "scram-sha-256-plus", "scram-sha256-plus", "scramsha256plus": + *sa = SMTPAuthSCRAMSHA256PLUS + case "xoauth2", "oauth2": + *sa = SMTPAuthXOAUTH2 + default: + return fmt.Errorf("unsupported SMTP auth type: %s", value) + } + return nil +} diff --git a/auth_test.go b/auth_test.go new file mode 100644 index 0000000..984dbd6 --- /dev/null +++ b/auth_test.go @@ -0,0 +1,47 @@ +package mail + +import "testing" + +func TestSMTPAuthType_UnmarshalString(t *testing.T) { + tests := []struct { + name string + authString string + expected SMTPAuthType + }{ + {"CRAM-MD5: cram-md5", "cram-md5", SMTPAuthCramMD5}, + {"CRAM-MD5: crammd5", "crammd5", SMTPAuthCramMD5}, + {"CRAM-MD5: cram", "cram", SMTPAuthCramMD5}, + {"CUSTOM", "custom", SMTPAuthCustom}, + {"LOGIN", "login", SMTPAuthLogin}, + {"NONE: none", "none", SMTPAuthNoAuth}, + {"NONE: noauth", "noauth", SMTPAuthNoAuth}, + {"NONE: no", "no", SMTPAuthNoAuth}, + {"PLAIN", "plain", SMTPAuthPlain}, + {"SCRAM-SHA-1: scram-sha-1", "scram-sha-1", SMTPAuthSCRAMSHA1}, + {"SCRAM-SHA-1: scram-sha1", "scram-sha1", SMTPAuthSCRAMSHA1}, + {"SCRAM-SHA-1: scramsha1", "scramsha1", SMTPAuthSCRAMSHA1}, + {"SCRAM-SHA-1-PLUS: scram-sha-1-plus", "scram-sha-1-plus", SMTPAuthSCRAMSHA1PLUS}, + {"SCRAM-SHA-1-PLUS: scram-sha1-plus", "scram-sha1-plus", SMTPAuthSCRAMSHA1PLUS}, + {"SCRAM-SHA-1-PLUS: scramsha1plus", "scramsha1plus", SMTPAuthSCRAMSHA1PLUS}, + {"SCRAM-SHA-256: scram-sha-256", "scram-sha-256", SMTPAuthSCRAMSHA256}, + {"SCRAM-SHA-256: scram-sha256", "scram-sha256", SMTPAuthSCRAMSHA256}, + {"SCRAM-SHA-256: scramsha256", "scramsha256", SMTPAuthSCRAMSHA256}, + {"SCRAM-SHA-256-PLUS: scram-sha-256-plus", "scram-sha-256-plus", SMTPAuthSCRAMSHA256PLUS}, + {"SCRAM-SHA-256-PLUS: scram-sha256-plus", "scram-sha256-plus", SMTPAuthSCRAMSHA256PLUS}, + {"SCRAM-SHA-256-PLUS: scramsha256plus", "scramsha256plus", SMTPAuthSCRAMSHA256PLUS}, + {"XOAUTH2: xoauth2", "xoauth2", SMTPAuthXOAUTH2}, + {"XOAUTH2: oauth2", "oauth2", SMTPAuthXOAUTH2}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var authType SMTPAuthType + if err := authType.UnmarshalString(tt.authString); err != nil { + t.Errorf("UnmarshalString() for type %s failed: %s", tt.authString, err) + } + if authType != tt.expected { + t.Errorf("UnmarshalString() for type %s failed: expected %s, got %s", + tt.authString, tt.expected, authType) + } + }) + } +} From bf44fd2ad14988479d763896bde8712c40be0223 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Mon, 21 Oct 2024 22:26:30 +0200 Subject: [PATCH 2/3] Add SPDX license headers to auth_test.go Included the SPDX license identifiers for copyright and license type at the beginning of the auth_test.go file. This ensures clear licensing information is provided and helps with automated license compliance. --- auth_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/auth_test.go b/auth_test.go index 984dbd6..fcb017e 100644 --- a/auth_test.go +++ b/auth_test.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2024 The go-mail Authors +// +// SPDX-License-Identifier: MIT + package mail import "testing" From 09133ef2a4b9d1ad3436424453b667b6545a48ab Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Mon, 21 Oct 2024 22:34:47 +0200 Subject: [PATCH 3/3] Add test for invalid SMTPAuthType Introduce a new test case to verify that `UnmarshalString` fails when given an invalid string. This ensures the robustness of the error handling in the `SMTPAuthType` unmarshalling process. --- auth_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/auth_test.go b/auth_test.go index fcb017e..2b8b796 100644 --- a/auth_test.go +++ b/auth_test.go @@ -48,4 +48,10 @@ func TestSMTPAuthType_UnmarshalString(t *testing.T) { } }) } + t.Run("should fail", func(t *testing.T) { + var authType SMTPAuthType + if err := authType.UnmarshalString("invalid"); err == nil { + t.Error("UnmarshalString() should have failed") + } + }) }