From 7bebdda27c9a5bcf0f2fbcd861337794e9010730 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Mon, 21 Oct 2024 22:24:21 +0200 Subject: [PATCH] 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) + } + }) + } +}