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() }