Search code examples
emailgosmtpsmtp-auth

Golang SMTP error: 535 5.7.0 Invalid login or password


I'm trying to create emailing service with go. When i tried to send email via gmail or office365 code works just fine but when i tried to send email via custom smtp i get "535 5.7.0 Invalid login or password" error.

I know username and password is correct because i am using same password and username with another python service with flask-mail and other services works just fine.

I don't have any documentation for custom smtp server but i know smtp server uses TLS

I tried plain auth, gomailer, smtp.SendMail() function and without startTLS but nothing changed.

here is my code;

func (m *Mail) sendMail(body, to, subject string) bool {
env := common.GetEnvironment()
mailServer := env.MailServer
mailUsername := env.MailUsername

SMTP := fmt.Sprintf("%s:%s", mailServer, env.MailPort)
auth := LoginAuth(mailUsername, env.MailPassword)

tlsconfig := &tls.Config{
    ServerName: mailServer,
}

c, err := smtp.Dial(SMTP)
if err != nil {
    zap.S().Error(err)
    return false
}

c.StartTLS(tlsconfig)

if err = c.Auth(auth); err != nil {
    zap.S().Error(err)
    return false
}

if err = c.Mail(mailUsername); err != nil {
    zap.S().Error(err)
    return false
}

if err = c.Rcpt(to); err != nil {
    zap.S().Error(err)
    return false
}

w, err := c.Data()
if err != nil {
    zap.S().Error(err)
    return false
}

_, err = w.Write([]byte(body))
if err != nil {
    zap.S().Error(err)
    return false
}

err = w.Close()
if err != nil {
    zap.S().Error(err)
    return false
}

c.Quit()
return true

}

auth function;

 import (
    "errors"
    "net/smtp"
)

type loginAuth struct {
    username, password string
}

func LoginAuth(username, password string) smtp.Auth {
    return &loginAuth{username, password}
}

func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
    return "LOGIN", []byte(a.username), nil
}

func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
    if more {
        switch string(fromServer) {
        case "Username:":
            return []byte(a.username), nil
        case "Password:":
            return []byte(a.password), nil
        default:
            return nil, errors.New("unknown from server")
        }
    }
    return nil, nil
}

Thank you for your helps


Solution

  • The error you get is definitely returned from smtp server. There are several authentication mechanisms supported by smtp protocol. If you do not know for sure which are supported by your server, you can debug it manually with the following command openssl s_client -crlf -ign_eof -connect <smtp_host>:<TLS_port>. After sending EHLO to the server it will announce supported authentication mechanism(s). Then you can try to login manually and implement Start() and Next() properly.
    Notice that some methods require login and password to be encoded(base64, md5, etc).