diff --git a/smtp/auth_cram_md5.go b/smtp/auth_cram_md5.go index 5357032..a02e3f1 100644 --- a/smtp/auth_cram_md5.go +++ b/smtp/auth_cram_md5.go @@ -11,6 +11,9 @@ // // SPDX-License-Identifier: BSD-3-Clause AND MIT +//go:build go1.19 +// +build go1.19 + package smtp import ( diff --git a/smtp/auth_cram_md5_118.go b/smtp/auth_cram_md5_118.go new file mode 100644 index 0000000..c9ff86f --- /dev/null +++ b/smtp/auth_cram_md5_118.go @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2010 The Go Authors. All rights reserved. +// SPDX-FileCopyrightText: Copyright (c) 2022-2023 The go-mail Authors +// +// Original net/smtp code from the Go stdlib by the Go Authors. +// Use of this source code is governed by a BSD-style +// LICENSE file that can be found in this directory. +// +// go-mail specific modifications by the go-mail Authors. +// Licensed under the MIT License. +// See [PROJECT ROOT]/LICENSES directory for more information. +// +// SPDX-License-Identifier: BSD-3-Clause AND MIT + +//go:build !go1.19 +// +build !go1.19 + +package smtp + +import ( + "crypto/hmac" + "crypto/md5" + "fmt" +) + +// cramMD5Auth is the type that satisfies the Auth interface for the "SMTP CRAM_MD5" auth +type cramMD5Auth struct { + username, secret string +} + +// CRAMMD5Auth returns an Auth that implements the CRAM-MD5 authentication +// mechanism as defined in RFC 2195. +// The returned Auth uses the given username and secret to authenticate +// to the server using the challenge-response mechanism. +func CRAMMD5Auth(username, secret string) Auth { + return &cramMD5Auth{username, secret} +} + +func (a *cramMD5Auth) Start(_ *ServerInfo) (string, []byte, error) { + return "CRAM-MD5", nil, nil +} + +func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) { + if more { + d := hmac.New(md5.New, []byte(a.secret)) + d.Write(fromServer) + s := make([]byte, 0, d.Size()) + return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil + } + return nil, nil +} diff --git a/smtp/smtp.go b/smtp/smtp.go index 4b23170..9d8c029 100644 --- a/smtp/smtp.go +++ b/smtp/smtp.go @@ -137,29 +137,6 @@ func (c *Client) helo() error { return err } -// ehlo sends the EHLO (extended hello) greeting to the server. It -// should be the preferred greeting for servers that support it. -func (c *Client) ehlo() error { - _, msg, err := c.cmd(250, "EHLO %s", c.localName) - if err != nil { - return err - } - ext := make(map[string]string) - extList := strings.Split(msg, "\n") - if len(extList) > 1 { - extList = extList[1:] - for _, line := range extList { - k, v, _ := strings.Cut(line, " ") - ext[k] = v - } - } - if mechs, ok := ext["AUTH"]; ok { - c.auth = strings.Split(mechs, " ") - } - c.ext = ext - return err -} - // StartTLS sends the STARTTLS command and encrypts all further communication. // Only servers that advertise the STARTTLS extension support this function. func (c *Client) StartTLS(config *tls.Config) error { diff --git a/smtp/smtp_ehlo.go b/smtp/smtp_ehlo.go new file mode 100644 index 0000000..ae80a62 --- /dev/null +++ b/smtp/smtp_ehlo.go @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: Copyright 2010 The Go Authors. All rights reserved. +// SPDX-FileCopyrightText: Copyright (c) 2022-2023 The go-mail Authors +// +// Original net/smtp code from the Go stdlib by the Go Authors. +// Use of this source code is governed by a BSD-style +// LICENSE file that can be found in this directory. +// +// go-mail specific modifications by the go-mail Authors. +// Licensed under the MIT License. +// See [PROJECT ROOT]/LICENSES directory for more information. +// +// SPDX-License-Identifier: BSD-3-Clause AND MIT + +//go:build go1.18 +// +build go1.18 + +package smtp + +import "strings" + +// ehlo sends the EHLO (extended hello) greeting to the server. It +// should be the preferred greeting for servers that support it. +func (c *Client) ehlo() error { + _, msg, err := c.cmd(250, "EHLO %s", c.localName) + if err != nil { + return err + } + ext := make(map[string]string) + extList := strings.Split(msg, "\n") + if len(extList) > 1 { + extList = extList[1:] + for _, line := range extList { + k, v, _ := strings.Cut(line, " ") + ext[k] = v + } + } + if mechs, ok := ext["AUTH"]; ok { + c.auth = strings.Split(mechs, " ") + } + c.ext = ext + return err +} diff --git a/smtp/smtp_ehlo_117.go b/smtp/smtp_ehlo_117.go new file mode 100644 index 0000000..6e52858 --- /dev/null +++ b/smtp/smtp_ehlo_117.go @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: Copyright 2010 The Go Authors. All rights reserved. +// SPDX-FileCopyrightText: Copyright (c) 2022-2023 The go-mail Authors +// +// Original net/smtp code from the Go stdlib by the Go Authors. +// Use of this source code is governed by a BSD-style +// LICENSE file that can be found in this directory. +// +// go-mail specific modifications by the go-mail Authors. +// Licensed under the MIT License. +// See [PROJECT ROOT]/LICENSES directory for more information. +// +// SPDX-License-Identifier: BSD-3-Clause AND MIT + +//go:build !go1.18 +// +build !go1.18 + +package smtp + +import "strings" + +// ehlo sends the EHLO (extended hello) greeting to the server. It +// should be the preferred greeting for servers that support it. +func (c *Client) ehlo() error { + _, msg, err := c.cmd(250, "EHLO %s", c.localName) + if err != nil { + return err + } + ext := make(map[string]string) + extList := strings.Split(msg, "\n") + if len(extList) > 1 { + extList = extList[1:] + for _, line := range extList { + args := strings.SplitN(line, " ", 2) + if len(args) > 1 { + ext[args[0]] = args[1] + } else { + ext[args[0]] = "" + } + } + } + if mechs, ok := ext["AUTH"]; ok { + c.auth = strings.Split(mechs, " ") + } + c.ext = ext + return err +}