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