*: depricate --email-from flag and move to email config files

This commit is contained in:
Eric Chiang 2016-06-27 23:34:55 -07:00
parent e134d4d261
commit 87faa5a1f7
14 changed files with 123 additions and 72 deletions

View file

@ -20,6 +20,7 @@ set `auth` to `plain` and specify your username and password.
"host": "smtp.example.org", "host": "smtp.example.org",
"port": 587, "port": 587,
"auth": "plain", "auth": "plain",
"from": "postmaster@example.com",
"username": "postmaster@example.org", "username": "postmaster@example.org",
"password": "foo" "password": "foo"
} }
@ -33,6 +34,7 @@ If using Mailgun the `type` field **must** be set to `mailgun`. Additionally
``` ```
{ {
"type": "mailgun", "type": "mailgun",
"from": "noreply@example.com",
"privateAPIKey": "key-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "privateAPIKey": "key-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"publicAPIKey": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY", "publicAPIKey": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
"domain": "sandboxZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.mailgun.org" "domain": "sandboxZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.mailgun.org"
@ -49,4 +51,4 @@ emailer the `type` field **must** be set to `fake`.
{ {
"type": "fake" "type": "fake"
} }
``` ```

View file

@ -43,7 +43,7 @@ func main() {
emailTemplateDirs := flagutil.StringSliceFlag{"./static/email"} emailTemplateDirs := flagutil.StringSliceFlag{"./static/email"}
fs.Var(&emailTemplateDirs, "email-templates", "comma separated list of directories of email template files") fs.Var(&emailTemplateDirs, "email-templates", "comma separated list of directories of email template files")
emailFrom := fs.String("email-from", "", "emails sent from dex will come from this address") emailFrom := fs.String("email-from", "", `DEPRICATED: use "from" field in email config.`)
emailConfig := fs.String("email-cfg", "./static/fixtures/emailer.json", "configures emailer.") emailConfig := fs.String("email-cfg", "./static/fixtures/emailer.json", "configures emailer.")
enableRegistration := fs.Bool("enable-registration", false, "Allows users to self-register. This flag cannot be used in combination with --enable-automatic-registration.") enableRegistration := fs.Bool("enable-registration", false, "Allows users to self-register. This flag cannot be used in combination with --enable-automatic-registration.")
@ -132,6 +132,10 @@ func main() {
log.Fatalf("Only 'http' and 'https' schemes are supported") log.Fatalf("Only 'http' and 'https' schemes are supported")
} }
if *emailFrom != "" {
log.Errorf(`--email-from flag is depricated. Use "from" field in email config.`)
}
scfg := server.ServerConfig{ scfg := server.ServerConfig{
IssuerURL: *issuer, IssuerURL: *issuer,
TemplateDir: *templates, TemplateDir: *templates,

View file

@ -28,14 +28,20 @@ type Emailer interface {
// SendMail queues an email to be sent to 1 or more recipients. // SendMail queues an email to be sent to 1 or more recipients.
// At least one of "text" or "html" must not be blank. If text is blank, but // At least one of "text" or "html" must not be blank. If text is blank, but
// html is not, then an html-only email should be sent and vice-versal. // html is not, then an html-only email should be sent and vice-versal.
SendMail(from, subject, text, html string, to ...string) error SendMail(subject, text, html string, to ...string) error
} }
//go:generate genconfig -o config.go email Emailer //go:generate genconfig -o config.go email Emailer
type EmailerConfig interface { type EmailerConfig interface {
EmailerID() string EmailerID() string
EmailerType() string EmailerType() string
Emailer() (Emailer, error)
// Because emailers can either be configured through command line flags or through
// JSON configs, we need a way to set the fromAddr when initializing the emailer.
//
// Values passed in the JSON config should override this value. Supplying neither
// should result in an error.
Emailer(fromAddress string) (Emailer, error)
} }
func newEmailerConfigFromReader(r io.Reader) (EmailerConfig, error) { func newEmailerConfigFromReader(r io.Reader) (EmailerConfig, error) {
@ -65,6 +71,7 @@ func NewEmailerConfigFromFile(loc string) (EmailerConfig, error) {
} }
type FakeEmailerConfig struct { type FakeEmailerConfig struct {
FromAddr string `json:"from"`
} }
func (cfg FakeEmailerConfig) EmailerType() string { func (cfg FakeEmailerConfig) EmailerType() string {
@ -75,15 +82,26 @@ func (cfg FakeEmailerConfig) EmailerID() string {
return FakeEmailerType return FakeEmailerType
} }
func (cfg FakeEmailerConfig) Emailer() (Emailer, error) { func (cfg FakeEmailerConfig) Emailer(fromAddr string) (Emailer, error) {
return FakeEmailer{}, nil from := cfg.FromAddr
if from == "" {
from = fromAddr
}
if from == "" {
// Since the emailer just prints to stdout, the actual value doesn't matter.
from = "noreply@example.com"
}
return FakeEmailer{from}, nil
} }
// FakeEmailer is an Emailer that writes emails to stdout. Should only be used in development. // FakeEmailer is an Emailer that writes emails to stdout. Should only be used in development.
type FakeEmailer struct{} type FakeEmailer struct {
from string
}
func (f FakeEmailer) SendMail(from, subject, text, html string, to ...string) error { func (f FakeEmailer) SendMail(subject, text, html string, to ...string) error {
fmt.Printf("From: %v\n", from) fmt.Printf("From: %v\n", f.from)
fmt.Printf("Subject: %v\n", subject) fmt.Printf("Subject: %v\n", subject)
fmt.Printf("To: %v\n", strings.Join(to, ",")) fmt.Printf("To: %v\n", strings.Join(to, ","))
fmt.Printf("Body(text): %v\n", text) fmt.Printf("Body(text): %v\n", text)

View file

@ -17,6 +17,7 @@ func init() {
} }
type MailgunEmailerConfig struct { type MailgunEmailerConfig struct {
FromAddr string `json:"from"`
PrivateAPIKey string `json:"privateAPIKey"` PrivateAPIKey string `json:"privateAPIKey"`
PublicAPIKey string `json:"publicAPIKey"` PublicAPIKey string `json:"publicAPIKey"`
Domain string `json:"domain"` Domain string `json:"domain"`
@ -30,10 +31,19 @@ func (cfg MailgunEmailerConfig) EmailerID() string {
return MailgunEmailerType return MailgunEmailerType
} }
func (cfg MailgunEmailerConfig) Emailer() (Emailer, error) { func (cfg MailgunEmailerConfig) Emailer(fromAddr string) (Emailer, error) {
from := cfg.FromAddr
if from == "" {
from = fromAddr
}
if from == "" {
return nil, errors.New(`missing "from" field in email config`)
}
mg := mailgun.NewMailgun(cfg.Domain, cfg.PrivateAPIKey, cfg.PublicAPIKey) mg := mailgun.NewMailgun(cfg.Domain, cfg.PrivateAPIKey, cfg.PublicAPIKey)
return &mailgunEmailer{ return &mailgunEmailer{
mg: mg, mg: mg,
from: from,
}, nil }, nil
} }
@ -64,11 +74,12 @@ func (cfg *MailgunEmailerConfig) UnmarshalJSON(data []byte) error {
} }
type mailgunEmailer struct { type mailgunEmailer struct {
mg mailgun.Mailgun mg mailgun.Mailgun
from string
} }
func (m *mailgunEmailer) SendMail(from, subject, text, html string, to ...string) error { func (m *mailgunEmailer) SendMail(subject, text, html string, to ...string) error {
msg := m.mg.NewMessage(from, subject, text, to...) msg := m.mg.NewMessage(m.from, subject, text, to...)
if html != "" { if html != "" {
msg.SetHtml(html) msg.SetHtml(html)
} }

View file

@ -9,20 +9,22 @@ import (
func TestNewEmailConfigFromReader(t *testing.T) { func TestNewEmailConfigFromReader(t *testing.T) {
tests := []struct { tests := []struct {
json string json string
want MailgunEmailerConfig want MailgunEmailerConfig
wantErr bool wantErr bool
wantInitErr bool // want error when calling Emailer() with no fromAddr
}{ }{
{ {
json: `{"type":"mailgun","id":"mg","privateAPIKey":"private","publicAPIKey":"public","domain":"example.com"}`, json: `{"type":"mailgun","id":"mg","privateAPIKey":"private","publicAPIKey":"public","domain":"example.com","from":"admin@example.com"}`,
want: MailgunEmailerConfig{ want: MailgunEmailerConfig{
PrivateAPIKey: "private", PrivateAPIKey: "private",
PublicAPIKey: "public", PublicAPIKey: "public",
Domain: "example.com", Domain: "example.com",
FromAddr: "admin@example.com",
}, },
}, },
{ {
json: `{"type":"mailgun","id":"mg","publicAPIKey":"public","domain":"example.com"}`, json: `{"type":"mailgun","id":"mg","publicAPIKey":"public","domain":"example.com",""}`,
wantErr: true, wantErr: true,
}, },
{ {
@ -33,6 +35,18 @@ func TestNewEmailConfigFromReader(t *testing.T) {
json: `{"type":"mailgun","id":"mg","privateAPIKey":"private","domain":"example.com"}`, json: `{"type":"mailgun","id":"mg","privateAPIKey":"private","domain":"example.com"}`,
wantErr: true, wantErr: true,
}, },
{
json: `{"type":"mailgun","id":"mg","privateAPIKey":"private","publicAPIKey":"public","domain":"example.com"}`,
want: MailgunEmailerConfig{
PrivateAPIKey: "private",
PublicAPIKey: "public",
Domain: "example.com",
},
// No fromAddr email provided. Calling Emailer("") should error since fromAddr needs to be provided
// in the config or as a command line argument.
wantInitErr: true,
},
} }
for i, tt := range tests { for i, tt := range tests {
@ -42,7 +56,6 @@ func TestNewEmailConfigFromReader(t *testing.T) {
if err == nil { if err == nil {
t.Errorf("case %d: want non-nil err.", i) t.Errorf("case %d: want non-nil err.", i)
} }
t.Logf("WHAT: %v", err)
continue continue
} }
if err != nil { if err != nil {
@ -52,5 +65,13 @@ func TestNewEmailConfigFromReader(t *testing.T) {
if diff := pretty.Compare(tt.want, ec); diff != "" { if diff := pretty.Compare(tt.want, ec); diff != "" {
t.Errorf("case %d: Compare(want, got): %v", i, diff) t.Errorf("case %d: Compare(want, got): %v", i, diff)
} }
_, err = ec.Emailer("")
if err != nil && !tt.wantInitErr {
t.Errorf("case %d: failed to initialize emailer: %v", i, err)
}
if err == nil && tt.wantInitErr {
t.Errorf("case %d: expected error initializing emailer", i)
}
} }
} }

View file

@ -21,6 +21,7 @@ type SmtpEmailerConfig struct {
Auth string `json:"auth"` Auth string `json:"auth"`
Username string `json:"username"` Username string `json:"username"`
Password string `json:"password"` Password string `json:"password"`
FromAddr string `json:"from"`
} }
func (cfg SmtpEmailerConfig) EmailerType() string { func (cfg SmtpEmailerConfig) EmailerType() string {
@ -31,7 +32,16 @@ func (cfg SmtpEmailerConfig) EmailerID() string {
return SmtpEmailerType return SmtpEmailerType
} }
func (cfg SmtpEmailerConfig) Emailer() (Emailer, error) { func (cfg SmtpEmailerConfig) Emailer(fromAddr string) (Emailer, error) {
from := cfg.FromAddr
if from == "" {
from = fromAddr
}
if from == "" {
return nil, errors.New(`missing "from" field in email config`)
}
var dialer *gomail.Dialer var dialer *gomail.Dialer
if cfg.Auth == "plain" { if cfg.Auth == "plain" {
dialer = gomail.NewPlainDialer(cfg.Host, cfg.Port, cfg.Username, cfg.Password) dialer = gomail.NewPlainDialer(cfg.Host, cfg.Port, cfg.Username, cfg.Password)
@ -43,6 +53,7 @@ func (cfg SmtpEmailerConfig) Emailer() (Emailer, error) {
} }
return &smtpEmailer{ return &smtpEmailer{
dialer: dialer, dialer: dialer,
from: from,
}, nil }, nil
} }
@ -66,11 +77,12 @@ func (cfg *SmtpEmailerConfig) UnmarshalJSON(data []byte) error {
type smtpEmailer struct { type smtpEmailer struct {
dialer *gomail.Dialer dialer *gomail.Dialer
from string
} }
func (emailer *smtpEmailer) SendMail(from, subject, text, html string, to ...string) error { func (emailer *smtpEmailer) SendMail(subject, text, html string, to ...string) error {
msg := gomail.NewMessage() msg := gomail.NewMessage()
msg.SetHeader("From", from) msg.SetHeader("From", emailer.from)
msg.SetHeader("To", to...) msg.SetHeader("To", to...)
msg.SetHeader("Subject", subject) msg.SetHeader("Subject", subject)
msg.SetBody("text/plain", text) msg.SetBody("text/plain", text)

View file

@ -8,7 +8,7 @@ import (
) )
// NewTemplatizedEmailerFromGlobs creates a new TemplatizedEmailer, parsing the templates found in the given filepattern globs. // NewTemplatizedEmailerFromGlobs creates a new TemplatizedEmailer, parsing the templates found in the given filepattern globs.
func NewTemplatizedEmailerFromGlobs(textGlob, htmlGlob string, emailer Emailer) (*TemplatizedEmailer, error) { func NewTemplatizedEmailerFromGlobs(textGlob, htmlGlob string, emailer Emailer, fromAddr string) (*TemplatizedEmailer, error) {
textTemplates, err := template.ParseGlob(textGlob) textTemplates, err := template.ParseGlob(textGlob)
if err != nil { if err != nil {
return nil, err return nil, err
@ -19,15 +19,16 @@ func NewTemplatizedEmailerFromGlobs(textGlob, htmlGlob string, emailer Emailer)
return nil, err return nil, err
} }
return NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer), nil return NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer, fromAddr), nil
} }
// NewTemplatizedEmailerFromTemplates creates a new TemplatizedEmailer, given root text and html templates. // NewTemplatizedEmailerFromTemplates creates a new TemplatizedEmailer, given root text and html templates.
func NewTemplatizedEmailerFromTemplates(textTemplates *template.Template, htmlTemplates *htmltemplate.Template, emailer Emailer) *TemplatizedEmailer { func NewTemplatizedEmailerFromTemplates(textTemplates *template.Template, htmlTemplates *htmltemplate.Template, emailer Emailer, fromAddr string) *TemplatizedEmailer {
return &TemplatizedEmailer{ return &TemplatizedEmailer{
emailer: emailer, emailer: emailer,
textTemplates: textTemplates, textTemplates: textTemplates,
htmlTemplates: htmlTemplates, htmlTemplates: htmlTemplates,
fromAddr: fromAddr,
} }
} }
@ -37,6 +38,7 @@ type TemplatizedEmailer struct {
htmlTemplates *htmltemplate.Template htmlTemplates *htmltemplate.Template
emailer Emailer emailer Emailer
globalCtx map[string]interface{} globalCtx map[string]interface{}
fromAddr string
} }
func (t *TemplatizedEmailer) SetGlobalContext(ctx map[string]interface{}) { func (t *TemplatizedEmailer) SetGlobalContext(ctx map[string]interface{}) {
@ -48,7 +50,7 @@ func (t *TemplatizedEmailer) SetGlobalContext(ctx map[string]interface{}) {
// the template names you want to base the message on instead of the actual // the template names you want to base the message on instead of the actual
// text. "to", "from" and "subject" will be added into the data map regardless // text. "to", "from" and "subject" will be added into the data map regardless
// of if they are used. // of if they are used.
func (t *TemplatizedEmailer) SendMail(from, subject, tplName string, data map[string]interface{}, to string) error { func (t *TemplatizedEmailer) SendMail(subject, tplName string, data map[string]interface{}, to string) error {
if tplName == "" { if tplName == "" {
return errors.New("Must provide a template name") return errors.New("Must provide a template name")
} }
@ -61,7 +63,7 @@ func (t *TemplatizedEmailer) SendMail(from, subject, tplName string, data map[st
} }
data["to"] = to data["to"] = to
data["from"] = from data["from"] = t.fromAddr
data["subject"] = subject data["subject"] = subject
for k, v := range t.globalCtx { for k, v := range t.globalCtx {
@ -84,5 +86,5 @@ func (t *TemplatizedEmailer) SendMail(from, subject, tplName string, data map[st
} }
} }
return t.emailer.SendMail(from, subject, textBuffer.String(), htmlBuffer.String(), to) return t.emailer.SendMail(subject, textBuffer.String(), htmlBuffer.String(), to)
} }

View file

@ -22,8 +22,7 @@ type testEmailer struct {
to []string to []string
} }
func (t *testEmailer) SendMail(from, subject, text, html string, to ...string) error { func (t *testEmailer) SendMail(subject, text, html string, to ...string) error {
t.from = from
t.subject = subject t.subject = subject
t.text = text t.text = text
t.html = html t.html = html
@ -118,12 +117,12 @@ func TestTemplatizedEmailSendMail(t *testing.T) {
for i, tt := range tests { for i, tt := range tests {
emailer := &testEmailer{} emailer := &testEmailer{}
templatizer := NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer) templatizer := NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer, tt.from)
if tt.ctx != nil { if tt.ctx != nil {
templatizer.SetGlobalContext(tt.ctx) templatizer.SetGlobalContext(tt.ctx)
} }
err := templatizer.SendMail(tt.from, tt.subject, tt.tplName, tt.data, tt.to) err := templatizer.SendMail(tt.subject, tt.tplName, tt.data, tt.to)
if tt.wantErr { if tt.wantErr {
if err == nil { if err == nil {
t.Errorf("case %d: err == nil, want non-nil err", i) t.Errorf("case %d: err == nil, want non-nil err", i)
@ -131,9 +130,6 @@ func TestTemplatizedEmailSendMail(t *testing.T) {
continue continue
} }
if emailer.from != tt.from {
t.Errorf("case %d: want=%q, got=%q", i, tt.from, emailer.from)
}
if emailer.subject != tt.subject { if emailer.subject != tt.subject {
t.Errorf("case %d: want=%q, got=%q", i, tt.subject, emailer.subject) t.Errorf("case %d: want=%q, got=%q", i, tt.subject, emailer.subject)
} }

View file

@ -327,7 +327,7 @@ func setEmailer(srv *Server, issuerName, fromAddress, emailerConfigFile string,
return err return err
} }
emailer, err := cfg.Emailer() emailer, err := cfg.Emailer(fromAddress)
if err != nil { if err != nil {
return err return err
} }
@ -371,7 +371,7 @@ func setEmailer(srv *Server, issuerName, fromAddress, emailerConfigFile string,
return err return err
} }
} }
tMailer := email.NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer) tMailer := email.NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer, fromAddress)
tMailer.SetGlobalContext(map[string]interface{}{ tMailer.SetGlobalContext(map[string]interface{}{
"issuer_name": issuerName, "issuer_name": issuerName,
}) })
@ -382,7 +382,6 @@ func setEmailer(srv *Server, issuerName, fromAddress, emailerConfigFile string,
srv.SessionManager.ValidityWindow, srv.SessionManager.ValidityWindow,
srv.IssuerURL, srv.IssuerURL,
tMailer, tMailer,
fromAddress,
srv.absURL(httpPathResetPassword), srv.absURL(httpPathResetPassword),
srv.absURL(httpPathEmailVerify), srv.absURL(httpPathEmailVerify),
srv.absURL(httpPathAcceptInvitation), srv.absURL(httpPathAcceptInvitation),

View file

@ -101,7 +101,6 @@ func TestSendResetPasswordEmailHandler(t *testing.T) {
wantCode: http.StatusOK, wantCode: http.StatusOK,
wantEmailer: &testEmailer{ wantEmailer: &testEmailer{
to: str("email-1@example.com"), to: str("email-1@example.com"),
from: "noreply@example.com",
subject: "Reset Your Password", subject: "Reset Your Password",
}, },
wantPRUserID: "ID-1", wantPRUserID: "ID-1",
@ -137,7 +136,6 @@ func TestSendResetPasswordEmailHandler(t *testing.T) {
wantCode: http.StatusOK, wantCode: http.StatusOK,
wantEmailer: &testEmailer{ wantEmailer: &testEmailer{
to: str("email-1@example.com"), to: str("email-1@example.com"),
from: "noreply@example.com",
subject: "Reset Your Password", subject: "Reset Your Password",
}, },
wantPRPassword: "password", wantPRPassword: "password",
@ -261,7 +259,7 @@ func TestSendResetPasswordEmailHandler(t *testing.T) {
emailer := &testEmailer{ emailer := &testEmailer{
sent: make(chan struct{}), sent: make(chan struct{}),
} }
templatizer := email.NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer) templatizer := email.NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer, "admin@example.com")
f.srv.UserEmailer.SetEmailer(templatizer) f.srv.UserEmailer.SetEmailer(templatizer)
hdlr := SendResetPasswordEmailHandler{ hdlr := SendResetPasswordEmailHandler{
tpl: f.srv.SendResetPasswordEmailTemplate, tpl: f.srv.SendResetPasswordEmailTemplate,
@ -584,13 +582,12 @@ func TestResetPasswordHandler(t *testing.T) {
} }
type testEmailer struct { type testEmailer struct {
from, subject, text, html string subject, text, html string
to []string to []string
sent chan struct{} sent chan struct{}
} }
func (t *testEmailer) SendMail(from, subject, text, html string, to ...string) error { func (t *testEmailer) SendMail(subject, text, html string, to ...string) error {
t.from = from
t.subject = subject t.subject = subject
t.text = text t.text = text
t.html = html t.html = html

View file

@ -198,7 +198,8 @@ func makeTestFixturesWithOptions(options testFixtureOptions) (*testFixtures, err
emailer, err := email.NewTemplatizedEmailerFromGlobs( emailer, err := email.NewTemplatizedEmailerFromGlobs(
emailTemplatesLocation+"/*.txt", emailTemplatesLocation+"/*.txt",
emailTemplatesLocation+"/*.html", emailTemplatesLocation+"/*.html",
&email.FakeEmailer{}) &email.FakeEmailer{},
"admin@example.com")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -266,7 +267,6 @@ func makeTestFixturesWithOptions(options testFixtureOptions) (*testFixtures, err
srv.SessionManager.ValidityWindow, srv.SessionManager.ValidityWindow,
srv.IssuerURL, srv.IssuerURL,
emailer, emailer,
"noreply@example.com",
srv.absURL(httpPathResetPassword), srv.absURL(httpPathResetPassword),
srv.absURL(httpPathEmailVerify), srv.absURL(httpPathEmailVerify),
srv.absURL(httpPathAcceptInvitation), srv.absURL(httpPathAcceptInvitation),

View file

@ -1,3 +1,4 @@
{ {
"type": "fake" "type": "fake",
} "from": "noreply@example.com"
}

View file

@ -19,7 +19,6 @@ type UserEmailer struct {
tokenValidityWindow time.Duration tokenValidityWindow time.Duration
issuerURL url.URL issuerURL url.URL
emailer *email.TemplatizedEmailer emailer *email.TemplatizedEmailer
fromAddress string
passwordResetURL url.URL passwordResetURL url.URL
verifyEmailURL url.URL verifyEmailURL url.URL
@ -33,7 +32,6 @@ func NewUserEmailer(ur user.UserRepo,
tokenValidityWindow time.Duration, tokenValidityWindow time.Duration,
issuerURL url.URL, issuerURL url.URL,
emailer *email.TemplatizedEmailer, emailer *email.TemplatizedEmailer,
fromAddress string,
passwordResetURL url.URL, passwordResetURL url.URL,
verifyEmailURL url.URL, verifyEmailURL url.URL,
invitationURL url.URL, invitationURL url.URL,
@ -45,7 +43,6 @@ func NewUserEmailer(ur user.UserRepo,
tokenValidityWindow: tokenValidityWindow, tokenValidityWindow: tokenValidityWindow,
issuerURL: issuerURL, issuerURL: issuerURL,
emailer: emailer, emailer: emailer,
fromAddress: fromAddress,
passwordResetURL: passwordResetURL, passwordResetURL: passwordResetURL,
verifyEmailURL: verifyEmailURL, verifyEmailURL: verifyEmailURL,
invitationURL: invitationURL, invitationURL: invitationURL,
@ -106,7 +103,7 @@ func (u *UserEmailer) SendResetPasswordEmail(email string, redirectURL url.URL,
resetURL.RawQuery = q.Encode() resetURL.RawQuery = q.Encode()
if u.emailer != nil { if u.emailer != nil {
err = u.emailer.SendMail(u.fromAddress, "Reset Your Password", "password-reset", err = u.emailer.SendMail("Reset Your Password", "password-reset",
map[string]interface{}{ map[string]interface{}{
"email": usr.Email, "email": usr.Email,
"link": resetURL.String(), "link": resetURL.String(),
@ -144,7 +141,7 @@ func (u *UserEmailer) SendInviteEmail(email string, redirectURL url.URL, clientI
resetURL.RawQuery = q.Encode() resetURL.RawQuery = q.Encode()
if u.emailer != nil { if u.emailer != nil {
err = u.emailer.SendMail(u.fromAddress, "Activate Your Account", "invite", err = u.emailer.SendMail("Activate Your Account", "invite",
map[string]interface{}{ map[string]interface{}{
"email": usr.Email, "email": usr.Email,
"link": resetURL.String(), "link": resetURL.String(),
@ -191,7 +188,7 @@ func (u *UserEmailer) SendEmailVerification(userID, clientID string, redirectURL
verifyURL.RawQuery = q.Encode() verifyURL.RawQuery = q.Encode()
if u.emailer != nil { if u.emailer != nil {
err = u.emailer.SendMail(u.fromAddress, "Please verify your email address.", "verify-email", err = u.emailer.SendMail("Please verify your email address.", "verify-email",
map[string]interface{}{ map[string]interface{}{
"email": usr.Email, "email": usr.Email,
"link": verifyURL.String(), "link": verifyURL.String(),

View file

@ -29,13 +29,12 @@ var (
) )
type testEmailer struct { type testEmailer struct {
from, subject, text, html string subject, text, html string
to []string to []string
sent bool sent bool
} }
func (t *testEmailer) SendMail(from, subject, text, html string, to ...string) error { func (t *testEmailer) SendMail(subject, text, html string, to ...string) error {
t.from = from
t.subject = subject t.subject = subject
t.text = text t.text = text
t.html = html t.html = html
@ -112,9 +111,9 @@ func makeTestFixtures() (*UserEmailer, *testEmailer, *key.PublicKey) {
htmlTemplates := htmltemplate.New("html") htmlTemplates := htmltemplate.New("html")
emailer := &testEmailer{} emailer := &testEmailer{}
tEmailer := email.NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer) tEmailer := email.NewTemplatizedEmailerFromTemplates(textTemplates, htmlTemplates, emailer, fromAddress)
userEmailer := NewUserEmailer(ur, pwr, signerFn, validityWindow, issuerURL, tEmailer, fromAddress, passwordResetURL, verifyEmailURL, acceptInvitationURL) userEmailer := NewUserEmailer(ur, pwr, signerFn, validityWindow, issuerURL, tEmailer, passwordResetURL, verifyEmailURL, acceptInvitationURL)
return userEmailer, emailer, publicKey return userEmailer, emailer, publicKey
} }
@ -203,10 +202,6 @@ func TestSendResetPasswordEmail(t *testing.T) {
t.Errorf("case %d: want==%v, got==%v", i, tt.email, emailer.to[0]) t.Errorf("case %d: want==%v, got==%v", i, tt.email, emailer.to[0])
} }
if fromAddress != emailer.from {
t.Errorf("case %d: want==%v, got==%v", i, fromAddress, emailer.from)
}
} else if emailer.sent { } else if emailer.sent {
t.Errorf("case %d: want !emailer.sent", i) t.Errorf("case %d: want !emailer.sent", i)
} }
@ -306,10 +301,6 @@ func TestSendEmailVerificationEmail(t *testing.T) {
t.Errorf("case %d: want==%v, got==%v", i, tt.wantEmailAddress, emailer.to[0]) t.Errorf("case %d: want==%v, got==%v", i, tt.wantEmailAddress, emailer.to[0])
} }
if fromAddress != emailer.from {
t.Errorf("case %d: want==%v, got==%v", i, fromAddress, emailer.from)
}
} else if emailer.sent { } else if emailer.sent {
t.Errorf("case %d: want !emailer.sent", i) t.Errorf("case %d: want !emailer.sent", i)
} }