mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-14 18:02:55 +01:00
Merge pull request #335 from wneessen/bug/332_server-does-not-support-smtp-auth-error-when-using-localhost-in-v050
Add default SMTP authentication type to NewClient
This commit is contained in:
commit
e854b2192f
3 changed files with 94 additions and 10 deletions
2
auth.go
2
auth.go
|
@ -47,7 +47,7 @@ const (
|
|||
// SMTPAuthNoAuth is equivalent to performing no authentication at all. It is a convenience
|
||||
// option and should not be used. Instead, for mail servers that do no support/require
|
||||
// authentication, the Client should not be passed the WithSMTPAuth option at all.
|
||||
SMTPAuthNoAuth SMTPAuthType = ""
|
||||
SMTPAuthNoAuth SMTPAuthType = "NOAUTH"
|
||||
|
||||
// SMTPAuthPlain is the "PLAIN" authentication mechanism as described in RFC 4616.
|
||||
//
|
||||
|
|
27
client.go
27
client.go
|
@ -259,11 +259,12 @@ var (
|
|||
// - An error if any critical default values are missing or options fail to apply.
|
||||
func NewClient(host string, opts ...Option) (*Client, error) {
|
||||
c := &Client{
|
||||
connTimeout: DefaultTimeout,
|
||||
host: host,
|
||||
port: DefaultPort,
|
||||
tlsconfig: &tls.Config{ServerName: host, MinVersion: DefaultTLSMinVersion},
|
||||
tlspolicy: DefaultTLSPolicy,
|
||||
smtpAuthType: SMTPAuthNoAuth,
|
||||
connTimeout: DefaultTimeout,
|
||||
host: host,
|
||||
port: DefaultPort,
|
||||
tlsconfig: &tls.Config{ServerName: host, MinVersion: DefaultTLSMinVersion},
|
||||
tlspolicy: DefaultTLSPolicy,
|
||||
}
|
||||
|
||||
// Set default HELO/EHLO hostname
|
||||
|
@ -1064,9 +1065,16 @@ func (c *Client) DialAndSendWithContext(ctx context.Context, messages ...*Msg) e
|
|||
// determines the supported authentication methods, and applies the appropriate authentication
|
||||
// type. An error is returned if authentication fails.
|
||||
//
|
||||
// This method first verifies the connection to the SMTP server. If no custom authentication
|
||||
// mechanism is provided, it checks which authentication methods are supported by the server.
|
||||
// Based on the configured SMTPAuthType, it sets up the appropriate authentication mechanism.
|
||||
// By default NewClient sets the SMTP authentication type to SMTPAuthNoAuth, meaning, that no
|
||||
// SMTP authentication will be performed. If the user makes use of SetSMTPAuth or initialzes the
|
||||
// client with WithSMTPAuth, the SMTP authentication type will be set in the Client, forcing
|
||||
// this method to determine if the server supports the selected authentication method and
|
||||
// assigning the corresponding smtp.Auth function to it.
|
||||
//
|
||||
// If the user set a custom SMTP authentication function using SetSMTPAuthCustom or
|
||||
// WithSMTPAuthCustom, we will not perform any detection and assignment logic and will trust
|
||||
// the user with their provided smtp.Auth function.
|
||||
//
|
||||
// Finally, it attempts to authenticate the client using the selected method.
|
||||
//
|
||||
// Returns:
|
||||
|
@ -1076,7 +1084,8 @@ func (c *Client) auth() error {
|
|||
if err := c.checkConn(); err != nil {
|
||||
return fmt.Errorf("failed to authenticate: %w", err)
|
||||
}
|
||||
if c.smtpAuth == nil && c.smtpAuthType != SMTPAuthCustom {
|
||||
|
||||
if c.smtpAuth == nil && c.smtpAuthType != SMTPAuthNoAuth {
|
||||
hasSMTPAuth, smtpAuthType := c.smtpClient.Extension("AUTH")
|
||||
if !hasSMTPAuth {
|
||||
return fmt.Errorf("server does not support SMTP AUTH")
|
||||
|
|
|
@ -1180,6 +1180,81 @@ func TestClient_Send_withBrokenRecipient(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestClient_DialWithContext_switchAuth(t *testing.T) {
|
||||
if os.Getenv("TEST_ALLOW_SEND") == "" {
|
||||
t.Skipf("TEST_ALLOW_SEND is not set. Skipping mail sending test")
|
||||
}
|
||||
|
||||
// We start with no auth explicitly set
|
||||
client, err := NewClient(
|
||||
os.Getenv("TEST_HOST"),
|
||||
WithTLSPortPolicy(TLSMandatory),
|
||||
)
|
||||
defer func() {
|
||||
_ = client.Close()
|
||||
}()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create client: %s", err)
|
||||
return
|
||||
}
|
||||
if err = client.DialWithContext(context.Background()); err != nil {
|
||||
t.Errorf("failed to dial to sending server: %s", err)
|
||||
}
|
||||
if err = client.Close(); err != nil {
|
||||
t.Errorf("failed to close client connection: %s", err)
|
||||
}
|
||||
|
||||
// We switch to LOGIN auth, which the server supports
|
||||
client.SetSMTPAuth(SMTPAuthLogin)
|
||||
client.SetUsername(os.Getenv("TEST_SMTPAUTH_USER"))
|
||||
client.SetPassword(os.Getenv("TEST_SMTPAUTH_PASS"))
|
||||
if err = client.DialWithContext(context.Background()); err != nil {
|
||||
t.Errorf("failed to dial to sending server: %s", err)
|
||||
}
|
||||
if err = client.Close(); err != nil {
|
||||
t.Errorf("failed to close client connection: %s", err)
|
||||
}
|
||||
|
||||
// We switch to CRAM-MD5, which the server does not support - error expected
|
||||
client.SetSMTPAuth(SMTPAuthCramMD5)
|
||||
if err = client.DialWithContext(context.Background()); err == nil {
|
||||
t.Errorf("expected error when dialing with unsupported auth mechanism, got nil")
|
||||
return
|
||||
}
|
||||
if !errors.Is(err, ErrCramMD5AuthNotSupported) {
|
||||
t.Errorf("expected dial error: %s, but got: %s", ErrCramMD5AuthNotSupported, err)
|
||||
}
|
||||
|
||||
// We switch to CUSTOM by providing PLAIN auth as function - the server supports this
|
||||
client.SetSMTPAuthCustom(smtp.PlainAuth("", os.Getenv("TEST_SMTPAUTH_USER"),
|
||||
os.Getenv("TEST_SMTPAUTH_PASS"), os.Getenv("TEST_HOST")))
|
||||
if client.smtpAuthType != SMTPAuthCustom {
|
||||
t.Errorf("expected auth type to be Custom, got: %s", client.smtpAuthType)
|
||||
}
|
||||
if err = client.DialWithContext(context.Background()); err != nil {
|
||||
t.Errorf("failed to dial to sending server: %s", err)
|
||||
}
|
||||
if err = client.Close(); err != nil {
|
||||
t.Errorf("failed to close client connection: %s", err)
|
||||
}
|
||||
|
||||
// We switch back to explicit no authenticaiton
|
||||
client.SetSMTPAuth(SMTPAuthNoAuth)
|
||||
if err = client.DialWithContext(context.Background()); err != nil {
|
||||
t.Errorf("failed to dial to sending server: %s", err)
|
||||
}
|
||||
if err = client.Close(); err != nil {
|
||||
t.Errorf("failed to close client connection: %s", err)
|
||||
}
|
||||
|
||||
// Finally we set an empty string as SMTPAuthType and expect and error. This way we can
|
||||
// verify that we do not accidentaly skip authentication with an empty string SMTPAuthType
|
||||
client.SetSMTPAuth("")
|
||||
if err = client.DialWithContext(context.Background()); err == nil {
|
||||
t.Errorf("expected error when dialing with empty auth mechanism, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestClient_auth tests the Dial(), Send() and Close() method of Client with broken settings
|
||||
func TestClient_auth(t *testing.T) {
|
||||
tests := []struct {
|
||||
|
|
Loading…
Reference in a new issue