-
-
Notifications
You must be signed in to change notification settings - Fork 79
NTLM Auth
Out of the box, go-mail does not support NTML authentication but we do support custom authentication
methods that satisfy the smtp.Auth
interface.
go-mail user @mkalus was nice enough to share their custom NTLM implementation with us that should work out of the box with go-mail.
The custom SMTP Auth implementation looks like this:
import (
"fmt"
"github.com/songxiang93/go-ntlm/ntlm"
"github.com/wneessen/go-mail/smtp"
)
type NTLMCustomAuth struct {
UserName string
Password string
Domain string
session ntlm.ClientSession
}
// Constructor function added by the go-mail team
func NTLMAuth(username, password, domain string) Auth {
return &NTLMCustomAuth{
UserName: username,
Password: password,
Domain: domain,
}
}
func (a *NTLMCustomAuth) Start(info *smtp.ServerInfo) (proto string, toServer []byte, err error) {
if len(info.Auth) > 0 {
supported := false
for _, method := range info.Auth {
if method == "NTLM" {
supported = true
}
}
if !supported {
return "", nil, fmt.Errorf("NTLM auth method not supported")
}
a.session, err = ntlm.CreateClientSession(ntlm.Version2, ntlm.ConnectionlessMode)
if err != nil {
return "", nil, fmt.Errorf("failed to create NTLM client session: %v", err)
}
a.session.SetUserInfo(a.UserName, a.Password, a.Domain)
negotiate, err := a.session.GenerateNegotiateMessage()
if err != nil {
return "", nil, fmt.Errorf("failed to generate negotiate message: %v", err)
}
return "NTLM", negotiate.Bytes(), nil
}
return "NTLM", nil, nil
}
func (a *NTLMCustomAuth) Next(challengeBytes []byte, more bool) (toServer []byte, err error) {
if more {
challenge, err := ntlm.ParseChallengeMessage(challengeBytes)
if err != nil {
return nil, fmt.Errorf("failed to parse challenge message: %v", err)
}
err = a.session.ProcessChallengeMessage(challenge)
if err != nil {
return nil, fmt.Errorf("failed to process challenge message: %v", err)
}
authenticate, err := a.session.GenerateAuthenticateMessage()
if err != nil {
return nil, fmt.Errorf("failed to generate authenticate message: %v", err)
}
return authenticate.Bytes(), nil
}
return nil, nil
}
To use this authentication method with go-mail, one would initialize the Client
with the WithSMTPAuthCustom()
option:
client, err := mail.NewClient("example.com", mail.WithSMTPAuthCustom(NTLMAuth("user", "password", "domain")))
Please be aware that this solution makes use of a 3rd party Go package: songxiang93/go-ntlm. The go-mail team has not verified this package nor is associated with this package, so please make sure that it fits your requirements before you use it together with this custom authentication solution.
Due to the lack of a NTLM server to test this against, we cannot guarantee that this solution works as expected and we cannot provide any support accordingly. Please use it at your own discretion.
Thanks again to @mkalus for sharing!
Socials: go-mail on Mastodon | #go-mail on Discord | #go-mail on Slack