Merge branch 'master' into imap

This commit is contained in:
emersion 2018-01-09 22:59:01 +01:00
commit fc7e906d1b
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
3 changed files with 36 additions and 14 deletions

View File

@ -5,6 +5,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io" "io"
"os" "os"
@ -97,15 +98,29 @@ func EncryptAndSave(auth *CachedAuth, username string, secretKey *[32]byte) erro
return saveAuths(auths) return saveAuths(auths)
} }
func authenticate(c *protonmail.Client, CachedAuth *CachedAuth) (openpgp.EntityList, error) { func authenticate(c *protonmail.Client, cachedAuth *CachedAuth, username string) (openpgp.EntityList, error) {
auth, err := c.AuthRefresh(&CachedAuth.Auth) auth, err := c.AuthRefresh(&cachedAuth.Auth)
if err != nil { if apiErr, ok := err.(*protonmail.ApiError); ok && apiErr.Code == 10013 {
// TODO: handle expired token, re-authenticate // Invalid refresh token, re-authenticate
authInfo, err := c.AuthInfo(username)
if err != nil {
return nil, fmt.Errorf("cannot re-authenticate: failed to get auth info: %v", err)
}
if authInfo.TwoFactor == 1 {
return nil, fmt.Errorf("cannot re-authenticate: two factor authentication enabled, please login manually")
}
auth, err = c.Auth(username, cachedAuth.LoginPassword, "", authInfo)
if err != nil {
return nil, fmt.Errorf("cannot re-authenticate: %v", err)
}
} else if err != nil {
return nil, err return nil, err
} }
CachedAuth.Auth = *auth cachedAuth.Auth = *auth
return c.Unlock(auth, CachedAuth.MailboxPassword) return c.Unlock(auth, cachedAuth.MailboxPassword)
} }
func GeneratePassword() (secretKey *[32]byte, password string, err error) { func GeneratePassword() (secretKey *[32]byte, password string, err error) {
@ -168,14 +183,14 @@ func (m *Manager) Auth(username, password string) (*protonmail.Client, openpgp.E
c := m.newClient() c := m.newClient()
c.ReAuth = func() error { c.ReAuth = func() error {
if _, err := authenticate(c, &cachedAuth); err != nil { if _, err := authenticate(c, &cachedAuth, username); err != nil {
return err return err
} }
return EncryptAndSave(&cachedAuth, username, &secretKey) return EncryptAndSave(&cachedAuth, username, &secretKey)
} }
// authenticate updates cachedAuth with the new refresh token // authenticate updates cachedAuth with the new refresh token
privateKeys, err := authenticate(c, &cachedAuth) privateKeys, err := authenticate(c, &cachedAuth, username)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -24,8 +24,10 @@ type resp struct {
func (r *resp) Err() error { func (r *resp) Err() error {
if err := r.apiError; err != nil { if err := r.apiError; err != nil {
err.code = r.Code return &ApiError{
return err Code: r.Code,
Message: err.Message,
}
} }
return nil return nil
} }
@ -35,12 +37,16 @@ type maybeError interface {
} }
type apiError struct { type apiError struct {
code int // populated by resp
Message string `json:"Error"` Message string `json:"Error"`
} }
func (err apiError) Error() string { type ApiError struct {
return fmt.Sprintf("[%v] %v", err.code, err.Message) Code int
Message string
}
func (err *ApiError) Error() string {
return fmt.Sprintf("[%v] %v", err.Code, err.Message)
} }
// Client is a ProtonMail API client. // Client is a ProtonMail API client.

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"strings"
"github.com/emersion/go-message/mail" "github.com/emersion/go-message/mail"
"github.com/emersion/go-smtp" "github.com/emersion/go-smtp"
@ -65,7 +66,7 @@ func (u *user) Send(from string, to []string, r io.Reader) error {
fromAddrStr := fromList[0].Address fromAddrStr := fromList[0].Address
var fromAddr *protonmail.Address var fromAddr *protonmail.Address
for _, addr := range u.u.Addresses { for _, addr := range u.u.Addresses {
if addr.Email == fromAddrStr { if strings.EqualFold(addr.Email, fromAddrStr) {
fromAddr = addr fromAddr = addr
break break
} }