-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
auth.go
60 lines (50 loc) · 1.6 KB
/
auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package email
import (
"errors"
"net/smtp"
)
// authMethod is SMTP authentication method
type authMethod string
// List of supported authentication methods
const (
authMethodPlain authMethod = "PLAIN"
authMethodLogin authMethod = "LOGIN"
)
// newLoginAuth returns smtp.Auth that implements the LOGIN authentication
// mechanism as defined in the LOGIN SASL Mechanism document,
// https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt.
// The returned smtp.Auth uses the given username and password to authenticate
// to the host.
//
// LOGIN will only send the credentials if the connection is using TLS
// or is connected to localhost. Otherwise authentication will fail with an
// error, without sending the credentials.
//
// LOGIN is described as obsolete in the SASL Mechanisms document
// but the mechanism is still in use, e.g. in Office 365 and Outlook.com.
func newLoginAuth(usr, pwd, host string) smtp.Auth {
return &loginAuth{usr, pwd, host}
}
type loginAuth struct {
user string
password string
host string
}
func isLocalhost(name string) bool {
return name == "localhost" || name == "127.0.0.1" || name == "::1"
}
func (a *loginAuth) Start(server *smtp.ServerInfo) (proto string, toServer []byte, err error) {
if !server.TLS && !isLocalhost(server.Name) {
return "", nil, errors.New("unencrypted connection")
}
if server.Name != a.host {
return "", nil, errors.New("wrong host name")
}
return "LOGIN", []byte(a.user), nil
}
func (a *loginAuth) Next(fromServer []byte, more bool) (toServer []byte, err error) {
if more {
return []byte(a.password), nil
}
return nil, nil
}