scsusers/emails.go

197 lines
5.0 KiB
Go

package scsusers
import (
"bytes"
"crypto/rand"
"database/sql"
"encoding/base32"
"fmt"
"log"
"net/smtp"
"strings"
"time"
)
func RecoverByUsername(username string) {
var email string
username = strings.ToLower(username)
q := fmt.Sprintf("select email from %s_auth where username = ?", c.TablePrefix)
err := c.db.Get(&email, q, username)
if err != sql.ErrNoRows {
recoverycode := randBytes(16)
qq := fmt.Sprintf("update %s_auth set recoverycode=?, recoverytime=NOW() where username = ?", c.TablePrefix)
_, err := c.db.Exec(qq, recoverycode, username)
if err == nil {
SendRecoveryEmail(email, username, string(recoverycode))
}
}
}
func RecoverByEmail(e string) {
var username, email string
q := fmt.Sprintf("select username from %s_auth where email = ?", c.TablePrefix)
err := c.db.Get(&username, q, e)
if err != sql.ErrNoRows {
recoverycode := randBytes(16)
qq := fmt.Sprintf("update %s_auth set recoverycode=?, recoverytime=NOW() where username = ?", c.TablePrefix)
_, err := c.db.Exec(qq, recoverycode, username)
if err == nil {
SendRecoveryEmail(email, username, string(recoverycode))
}
}
}
func randBytes(n int) []byte {
randomBytes := make([]byte, 32)
_, err := rand.Read(randomBytes)
if err != nil {
panic(err)
}
return []byte(base32.StdEncoding.EncodeToString(randomBytes)[:n])
}
func SendRegistrationEmail(recipient, username, password string) bool {
data := struct {
SiteName string
FromEmail string
UserName string
Pass string
}{
SiteName: c.SiteName,
FromEmail: c.FromEmail,
UserName: username,
Pass: password,
}
var body bytes.Buffer
err := c.Templates.Registration.Execute(&body, data)
if err != nil {
log.Printf("scsusers.sendRegistrationEmail: Registration template failed to execute: %v returned %s\n", data, err.Error())
return false
}
subject := fmt.Sprintf("Welcome to %s", c.SiteName)
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
if err != nil {
log.Printf("scsusers.SendRegistrationEmail: Error sending mail to %s: %s\n", recipient, err.Error())
return false
}
return true
}
func SendAlertEmail(username, recipient, message string) bool {
data := struct {
SiteName string
FromEmail string
UserName string
Activity string
}{
SiteName: c.SiteName,
FromEmail: c.FromEmail,
UserName: username,
Activity: message,
}
var body bytes.Buffer
err := c.Templates.Alert.Execute(&body, data)
if err != nil {
log.Printf("scsusers.sendAlertEmail: Alert template failed to execute: %v returned %s\n", data, err.Error())
return false
}
subject := fmt.Sprintf("new Activity Notification on %s", c.SiteName)
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
if err != nil {
log.Printf("scsusers.sendAlertEmail: Error sending mail to %s: %s\n", recipient, err.Error())
return false
}
return true
}
func SendRecoveryEmail(recipient, username, code string) bool {
data := struct {
SiteName string
FromEmail string
UserName string
RecoveryCode string
}{
SiteName: c.SiteName,
FromEmail: c.FromEmail,
UserName: username,
RecoveryCode: code,
}
var body bytes.Buffer
err := c.Templates.Registration.Execute(&body, data)
if err != nil {
log.Printf("scsusers.sendRecoveryEmail: Recovery template failed to execute: %v returned %s\n", data, err.Error())
return false
}
subject := fmt.Sprintf("Account recovery at %s", c.SiteName)
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
if err != nil {
log.Printf("scsusers.sendRecoveryEmail: Error sending mail to %s: %s\n", recipient, err.Error())
return false
}
return true
}
func Send2faEmail(recipient, fullname, code string) error {
data := struct {
SiteName string
FromEmail string
FullName string
Code string
}{
SiteName: c.SiteName,
FromEmail: c.FromEmail,
FullName: fullname,
Code: code,
}
var body bytes.Buffer
err := c.Templates.TwoFA.Execute(&body, data)
if err != nil {
return fmt.Errorf("scsusers.send2fayEmail: 2fa template failed to execute: %v returned %s", data, err.Error())
}
subject := fmt.Sprintf("Two Factor Authentication Code at %s", c.SiteName)
err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient)
return err
}
func SendMail(addr, from, subject, body string, to string) error {
r := strings.NewReplacer("\r\n", "", "\r", "", "\n", "", "%0a", "", "%0d", "")
c, err := smtp.Dial(addr)
if err != nil {
return err
}
defer c.Close()
if err = c.Mail(r.Replace(from)); err != nil {
return err
}
to = r.Replace(to)
if err = c.Rcpt(to); err != nil {
return err
}
w, err := c.Data()
if err != nil {
return err
}
date := time.Now()
msg := "To: " + to + "\r\n" +
"From: " + from + "\r\n" +
"Subject: " + subject + "\r\n" +
"Content-Type: text/html; charset=\"UTF-8\"\r\n" +
"Date: " + date.Format(time.RFC1123Z) + "\r\n" +
"\r\n" + body
_, err = w.Write([]byte(msg))
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return c.Quit()
}