package main import ( "log" "log/slog" "net/smtp" "github.com/emersion/go-sasl" ) // The ANONYMOUS mechanism name. const Anonymous = "ANONYMOUS" type anonymousClient struct { Trace string } func (c *anonymousClient) Start(si *smtp.ServerInfo) (mech string, ir []byte, err error) { mech = Anonymous ir = []byte(c.Trace) return } func (c *anonymousClient) Next(challenge []byte, b bool) (response []byte, err error) { return nil, sasl.ErrUnexpectedServerChallenge } // A client implementation of the ANONYMOUS authentication mechanism, as // described in RFC 4505. func NewAnonymousClient(trace string) smtp.Auth { return &anonymousClient{trace} } // The PLAIN mechanism name. const Plain = "PLAIN" type plainClient struct { Identity string Username string Password string } func (a *plainClient) Start(si *smtp.ServerInfo) (mech string, ir []byte, err error) { mech = "PLAIN" ir = []byte(a.Identity + "\x00" + a.Username + "\x00" + a.Password) return } func (a *plainClient) Next(challenge []byte, b bool) (response []byte, err error) { slog.Info("Next: %v", challenge) return nil, nil } // A client implementation of the PLAIN authentication mechanism, as described // in RFC 4616. Authorization identity may be left blank to indicate that it is // the same as the username. func NewPlainClient(identity, username, password string) smtp.Auth { return &plainClient{identity, username, password} } func main() { // hostname is used by PlainAuth to validate the TLS certificate. hostname := "localhost" auth := NewPlainClient("", "username", "password") // auth := NewAnonymousClient("test") recipients := []string{"something@something.com", "caca@caca.com"} msg := []byte("\r\nwithout title") from := "hello@localhost" err := smtp.SendMail(hostname+":11025", auth, from, recipients, msg) if err != nil { log.Fatal(err) } }