-
Notifications
You must be signed in to change notification settings - Fork 75
/
useremail.go
278 lines (220 loc) · 7.41 KB
/
useremail.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Copyright (c) 2017-2020 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package legacy
import (
"bytes"
"net/url"
"text/template"
www "github.com/decred/politeia/politeiawww/api/www/v1"
"github.com/google/uuid"
)
const (
// GUI routes. These are used in notification emails to direct the
// user to the correct GUI pages.
guiRouteRegisterNewUser = "/register"
)
// emailUserEmailVerify sends a new user verification email to the provided
// email address. This function is not rate limited by the smtp client because
// the user is only created/updated when this function is successfully executed
// and an email with the verification token is sent to the user. This email is
// also already limited by the verification token expiry hours policy.
func (p *Politeiawww) emailUserEmailVerify(email, token, username string) error {
link, err := p.createEmailLink(www.RouteVerifyNewUser, email,
token, username)
if err != nil {
return err
}
tplData := userEmailVerify{
Username: username,
Link: link,
}
subject := "Verify Your Email"
body, err := createBody(userEmailVerifyTmpl, tplData)
if err != nil {
return err
}
return p.mail.SendTo(subject, body, []string{email})
}
// emailUserKeyUpdate emails the link with the verification token used for
// setting a new key pair if the email server is set up.
func (p *Politeiawww) emailUserKeyUpdate(username, publicKey, token string, recipient map[uuid.UUID]string) error {
link, err := p.createEmailLink(www.RouteVerifyUpdateUserKey, "", token, "")
if err != nil {
return err
}
tplData := userKeyUpdate{
PublicKey: publicKey,
Username: username,
Link: link,
}
subject := "Verify Your New Identity"
body, err := createBody(userKeyUpdateTmpl, tplData)
if err != nil {
return err
}
return p.mail.SendToUsers(subject, body, recipient)
}
// emailUserPasswordReset emails the link with the reset password verification
// token to the provided email address.
func (p *Politeiawww) emailUserPasswordReset(username, token string, recipient map[uuid.UUID]string) error {
// Setup URL
u, err := url.Parse(p.cfg.WebServerAddress + www.RouteResetPassword)
if err != nil {
return err
}
q := u.Query()
q.Set("verificationtoken", token)
q.Set("username", username)
u.RawQuery = q.Encode()
// Setup email
subject := "Reset Your Password"
tplData := userPasswordReset{
Link: u.String(),
}
body, err := createBody(userPasswordResetTmpl, tplData)
if err != nil {
return err
}
// Send email
return p.mail.SendToUsers(subject, body, recipient)
}
// emailUserAccountLocked notifies the user its account has been locked and
// emails the link with the reset password verification token if the email
// server is set up.
func (p *Politeiawww) emailUserAccountLocked(username string, recipient map[uuid.UUID]string) error {
var email string
for _, e := range recipient {
email = e
}
link, err := p.createEmailLink(ResetPasswordGuiRoute,
email, "", "")
if err != nil {
return err
}
tplData := userAccountLocked{
Link: link,
Username: username,
}
subject := "Locked Account - Reset Your Password"
body, err := createBody(userAccountLockedTmpl, tplData)
if err != nil {
return err
}
return p.mail.SendToUsers(subject, body, recipient)
}
// emailUserPasswordChanged notifies the user that his password was changed,
// and verifies if he was the author of this action, for security purposes.
func (p *Politeiawww) emailUserPasswordChanged(username string, recipient map[uuid.UUID]string) error {
tplData := userPasswordChanged{
Username: username,
}
subject := "Password Changed - Security Notification"
body, err := createBody(userPasswordChangedTmpl, tplData)
if err != nil {
return err
}
return p.mail.SendToUsers(subject, body, recipient)
}
func (p *Politeiawww) createEmailLink(path, email, token, username string) (string, error) {
l, err := url.Parse(p.cfg.WebServerAddress + path)
if err != nil {
return "", err
}
q := l.Query()
if email != "" {
q.Set("email", email)
}
if token != "" {
q.Set("verificationtoken", token)
}
if username != "" {
q.Set("username", username)
}
l.RawQuery = q.Encode()
return l.String(), nil
}
func createBody(tpl *template.Template, tplData interface{}) (string, error) {
var buf bytes.Buffer
err := tpl.Execute(&buf, tplData)
if err != nil {
return "", err
}
return buf.String(), nil
}
// User email verify - Send verification link to new user
type userEmailVerify struct {
Username string // User username
Link string // Verification link
}
const userEmailVerifyText = `
Thanks for joining Politeia, {{.Username}}!
Click the link below to verify your email and complete your registration.
{{.Link}}
You are receiving this notification because this email address was used to
register a Politeia account. If you did not perform this action, please ignore
this email.
`
var userEmailVerifyTmpl = template.Must(
template.New("userEmailVerify").Parse(userEmailVerifyText))
// User key update - Send key verification link to user
type userKeyUpdate struct {
PublicKey string // User new public key
Username string
Link string // Verify key link
}
const userKeyUpdateText = `
Click the link below to verify your new identity:
{{.Link}}
You are receiving this notification because a new identity was generated for
{{.Username}} on Politeia with the following public key.
Public key: {{.PublicKey}}
If you did not perform this action, please contact a Politeia administrators in
the Politeia channel on Matrix.
https://chat.decred.org/#/room/#politeia:decred.org
`
var userKeyUpdateTmpl = template.Must(
template.New("userKeyUpdate").Parse(userKeyUpdateText))
// User password reset - Send password reset link to user
type userPasswordReset struct {
Link string // Password reset link
}
const userPasswordResetText = `
Click the link below to continue resetting your password:
{{.Link}}
A password reset was initiated for this Politeia account. If you did not
perform this action, it's possible that your account has been compromised.
Please contact a Politeia administrator in the Politeia channel on Matrix.
https://chat.decred.org/#/room/#politeia:decred.org
`
var userPasswordResetTmpl = template.Must(
template.New("userPasswordReset").Parse(userPasswordResetText))
// User account locked - Send reset password link to user
type userAccountLocked struct {
Link string // Reset password link
Username string
}
const userAccountLockedText = `
The Politeia account for {{.Username}} was locked due to too many login
attempts. You need to reset your password in order to unlock your account:
{{.Link}}
If these login attempts were not made by you, please notify a Politeia
administrators in the Politeia channel on Matrix.
https://chat.decred.org/#/room/#politeia:decred.org
`
var userAccountLockedTmpl = template.Must(
template.New("userAccountLocked").Parse(userAccountLockedText))
// User password changed - Send to user
type userPasswordChanged struct {
Username string
}
const userPasswordChangedText = `
The password has been changed for your Politeia account with the username
{{.Username}}.
If you did not perform this action, it's possible that your account has been
compromised. Please contact a Politeia administrator in the Politeia channel
on Matrix.
https://chat.decred.org/#/room/#politeia:decred.org
`
var userPasswordChangedTmpl = template.Must(
template.New("userPasswordChanged").Parse(userPasswordChangedText))