package smtp
-import "errors"
+import (
+ "crypto/hmac"
+ "errors"
+ "fmt"
+)
// Auth is implemented by an SMTP authentication mechanism.
type Auth interface {
}
return nil, nil
}
+
+type cramMD5Auth struct {
+ username, secret string
+}
+
+// CRAMMD5Auth returns an Auth that implements the CRAM-MD5 authentication
+// mechanism as defined in RFC 2195.
+// The returned Auth uses the given username and secret to authenticate
+// to the server using the challenge-response mechanism.
+func CRAMMD5Auth(username, secret string) Auth {
+ return &cramMD5Auth{username, secret}
+}
+
+func (a *cramMD5Auth) Start(server *ServerInfo) (string, []byte, error) {
+ return "CRAM-MD5", nil, nil
+}
+
+func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
+ if more {
+ d := hmac.NewMD5([]byte(a.secret))
+ d.Write(fromServer)
+ s := make([]byte, 0, d.Size())
+ return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil
+ }
+ return nil, nil
+}
var authTests = []authTest{
{PlainAuth("", "user", "pass", "testserver"), []string{}, "PLAIN", []string{"\x00user\x00pass"}},
{PlainAuth("foo", "bar", "baz", "testserver"), []string{}, "PLAIN", []string{"foo\x00bar\x00baz"}},
+ {CRAMMD5Auth("user", "pass"), []string{"<123456.1322876914@testserver>"}, "CRAM-MD5", []string{"", "user 287eb355114cf5c471c26a875f1ca4ae"}},
}
func TestAuth(t *testing.T) {