2023-09-26 20:36:03 +00:00
|
|
|
package scsusers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/rand"
|
|
|
|
"encoding/base32"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"net/smtp"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2023-10-06 22:39:58 +00:00
|
|
|
func RecoverByEmail(email string) {
|
|
|
|
u, ok := Get(email)
|
|
|
|
if !ok {
|
|
|
|
return
|
2023-09-26 20:36:03 +00:00
|
|
|
}
|
2023-10-06 22:39:58 +00:00
|
|
|
recoverycode := randBytes(16)
|
2023-09-26 20:36:03 +00:00
|
|
|
|
2023-10-06 22:39:58 +00:00
|
|
|
u.Set("recoverycode", string(recoverycode))
|
2023-10-06 23:06:54 +00:00
|
|
|
u.Set("recoverytime", fmt.Sprintf("%d", time.Now().Add(time.Minute*60).Unix()))
|
2023-10-06 22:39:58 +00:00
|
|
|
|
|
|
|
SendRecoveryEmail(email, email, string(recoverycode))
|
2023-09-26 20:36:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2023-10-06 23:39:33 +00:00
|
|
|
err := c.Templates.Recovery.Execute(&body, data)
|
2023-09-26 20:36:03 +00:00
|
|
|
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 {
|
2023-09-26 20:45:19 +00:00
|
|
|
SiteName string
|
|
|
|
FromEmail string
|
|
|
|
FullName string
|
|
|
|
Code string
|
2023-09-26 20:36:03 +00:00
|
|
|
}{
|
2023-09-26 20:45:19 +00:00
|
|
|
SiteName: c.SiteName,
|
|
|
|
FromEmail: c.FromEmail,
|
|
|
|
FullName: fullname,
|
|
|
|
Code: code,
|
2023-09-26 20:36:03 +00:00
|
|
|
}
|
|
|
|
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()
|
|
|
|
}
|