36 lines
1.0 KiB
Go
36 lines
1.0 KiB
Go
package services
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
|
||
"github.com/emersion/go-sasl"
|
||
)
|
||
|
||
// xoauth2SASL 实现 Microsoft / Google 邮件使用的 XOAUTH2(与 RFC7628 OAUTHBEARER 不同)。
|
||
type xoauth2SASL struct {
|
||
username string
|
||
token string
|
||
}
|
||
|
||
// NewXOAUTH2Client 供 IMAP AUTHENTICATE / SMTP AUTH 使用,username 一般为完整邮箱。
|
||
func NewXOAUTH2Client(username, accessToken string) sasl.Client {
|
||
return &xoauth2SASL{
|
||
username: strings.TrimSpace(username),
|
||
token: strings.TrimSpace(accessToken),
|
||
}
|
||
}
|
||
|
||
func (x *xoauth2SASL) Start() (mech string, ir []byte, err error) {
|
||
// https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth
|
||
s := fmt.Sprintf("user=%s\x01auth=Bearer %s\x01\x01", x.username, x.token)
|
||
return "XOAUTH2", []byte(s), nil
|
||
}
|
||
|
||
func (x *xoauth2SASL) Next(challenge []byte) ([]byte, error) {
|
||
if len(challenge) == 0 {
|
||
return nil, nil
|
||
}
|
||
return nil, fmt.Errorf("xoauth2: %s", string(challenge))
|
||
}
|