Skip to content

Commit

Permalink
Add subscription link support to notification email verification temp…
Browse files Browse the repository at this point in the history
…late (#573)

* add subscription link support to notification email verification template

* always show token for email subscription in verification email

* hide SubscribeURL from users
  • Loading branch information
paskal authored and umputun committed Jan 21, 2020
1 parent 091ac9b commit f97d823
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 9 deletions.
2 changes: 2 additions & 0 deletions backend/app/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,8 @@ func (s *ServerCommand) makeNotify(dataStore *service.DataStore, authenticator *
From: s.Notify.Email.From,
VerificationSubject: s.Notify.Email.VerificationSubject,
UnsubscribeURL: s.RemarkURL + "/email/unsubscribe.html",
// TODO: uncomment after #560 frontend part is ready and URL is known
//SubscribeURL: s.RemarkURL + "/subscribe.html?token=",
TokenGenFn: func(userID, email, site string) (string, error) {
claims := token.Claims{
Handshake: &token.Handshake{ID: userID + "::" + email},
Expand Down
23 changes: 15 additions & 8 deletions backend/app/notify/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type EmailParams struct {
MsgTemplate string // request message template
VerificationSubject string // verification message subject
VerificationTemplate string // verification message template
SubscribeURL string // full subscribe handler URL
UnsubscribeURL string // full unsubscribe handler URL

TokenGenFn func(userID, email, site string) (string, error) // Unsubscribe token generation function
Expand Down Expand Up @@ -91,10 +92,11 @@ type msgTmplData struct {

// verifyTmplData store data for verification message template execution
type verifyTmplData struct {
User string
Token string
Email string
Site string
User string
Token string
Email string
Site string
SubscribeURL string
}

const (
Expand Down Expand Up @@ -178,6 +180,10 @@ const (
<div style="text-align: center; font-family: Helvetica, Arial, sans-serif; font-size: 18px;">
<h1 style="position: relative; color: #4fbbd6; margin-top: 0.2em;">Remark42</h1>
<p style="position: relative; max-width: 20em; margin: 0 auto 1em auto; line-height: 1.4em; color:#000!important;">Confirmation for <b>{{.User}}</b> on site <b>{{.Site}}</b></p>
{{if .SubscribeURL}}
<p style="position: relative; margin: 0 0 0.5em 0;color:#000!important;"><a href="{{.SubscribeURL}}{{.Token}}">Click here to subscribe to email notifications</a></p>
<p style="position: relative; margin: 0 0 0.5em 0;color:#000!important;">Alternatively, you can use code below for subscription.</p>
{{ end }}
<div style="background-color: #eee; max-width: 20em; margin: 0 auto; border-radius: 0.4em; padding: 0.5em;">
<p style="position: relative; margin: 0 0 0.5em 0;color:#000!important;">TOKEN</p>
<p style="position: relative; font-size: 0.7em; opacity: 0.8;"><i style="color:#000!important;">Copy and paste this text into “token” field on comments page</i></p>
Expand Down Expand Up @@ -273,10 +279,11 @@ func (e *Email) buildVerificationMessage(user, email, token, site string) (strin
subject := e.VerificationSubject
msg := bytes.Buffer{}
err := e.verifyTmpl.Execute(&msg, verifyTmplData{
User: user,
Token: token,
Email: email,
Site: site,
User: user,
Token: token,
Email: email,
Site: site,
SubscribeURL: e.SubscribeURL,
})
if err != nil {
return "", errors.Wrapf(err, "error executing template to build verification message")
Expand Down
47 changes: 46 additions & 1 deletion backend/app/notify/email_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ func TestEmail_Send(t *testing.T) {
req := Request{
Comment: store.Comment{ID: "999", User: store.User{ID: "1", Name: "test_user"}, PostTitle: "test_title"},
parent: store.Comment{ID: "1", User: store.User{ID: "999", Name: "parent_user"}},
Email: "[email protected]"}
Email: "[email protected]",
}
assert.NoError(t, email.Send(context.TODO(), req))
assert.Equal(t, "[email protected]", fakeSmtp.readMail())
assert.Equal(t, 1, fakeSmtp.readQuitCount())
Expand All @@ -208,6 +209,50 @@ List-Unsubscribe: <https://remark42.com/api/v1/email/unsubscribe?site=&tkn=token
Date: `)
}

func TestEmail_SendVerification(t *testing.T) {
email, err := NewEmail(EmailParams{From: "[email protected]"}, SmtpParams{})
assert.NoError(t, err)
assert.NotNil(t, email)
fakeSmtp := fakeTestSMTP{}
email.smtp = &fakeSmtp
email.TokenGenFn = TokenGenFn
req := Request{
Email: "[email protected]",
Verification: VerificationMetadata{
SiteID: "remark",
User: "test_username",
Token: "secret_",
},
}
assert.NoError(t, email.Send(context.TODO(), req))
assert.Equal(t, "[email protected]", fakeSmtp.readMail())
assert.Equal(t, 1, fakeSmtp.readQuitCount())
assert.Equal(t, "[email protected]", fakeSmtp.readRcpt())
// test buildMessageFromRequest separately for message text
res, err := email.buildVerificationMessage(req.Verification.User, req.Email, req.Verification.Token, req.Verification.SiteID)
assert.NoError(t, err)
assert.Contains(t, res, `From: [email protected]
To: [email protected]
Subject: Email verification
Content-Transfer-Encoding: quoted-printable
MIME-version: 1.0
Content-Type: text/html; charset="UTF-8"
Date: `)
assert.Contains(t, res, `secret_`)
assert.NotContains(t, res, `https://example.org/`)
email.SubscribeURL = "https://example.org/subscribe.html?token="
res, err = email.buildVerificationMessage(req.Verification.User, req.Email, req.Verification.Token, req.Verification.SiteID)
assert.NoError(t, err)
assert.Contains(t, res, `From: [email protected]
To: [email protected]
Subject: Email verification
Content-Transfer-Encoding: quoted-printable
MIME-version: 1.0
Content-Type: text/html; charset="UTF-8"
Date: `)
assert.Contains(t, res, `https://example.org/subscribe.html?token=3Dsecret_`)
}

func Test_emailClient_Create(t *testing.T) {
creator := emailClient{}
client, err := creator.Create(SmtpParams{})
Expand Down

0 comments on commit f97d823

Please sign in to comment.