email accepted users

trunk
vilmibm 2023-03-09 06:33:31 +00:00
parent cee8b75bad
commit c43adc49fb
5 changed files with 104 additions and 32 deletions

View File

@ -1,8 +1,67 @@
package main package main
// TODO function for reading smtp.pw from /town/docs import (
"errors"
"fmt"
"os"
func sendInviteEmail() error { "git.tilde.town/tildetown/town/email"
// TODO "git.tilde.town/tildetown/town/invites"
return nil )
const emailText = `hello!
You applied to https://tilde.town at some point and your application has been approved ^_^
Your invite code is: %s
To redeem your code, please open a terminal and run:
ssh welcome@tilde.town
You'll fill in details like your desired username and SSH public key.
If you're brand new to SSH or have never heard of it that is okay!
This page has information on what SSH is and how to use it, including how to create an ssh key pair which you'll need to access your town account: https://tilde.town/wiki/getting-started/ssh.html
If you run into confusion or problems creating a key pair on your computer, this page can generate one for you: https://tilde.town/keymachine . However you'll still need to save the generated key files to your computer in order to use them.
If you end up stuck, e-mail root@tilde.town with any questions.
See you on the server,
~vilmibm`
func loadPassword() (string, error) {
f, err := os.Open("/town/docs/smtp.pw")
if err != nil {
return "", err
}
pw := make([]byte, 100)
n, err := f.Read(pw)
if err != nil {
return "", err
}
if n == 0 {
return "", errors.New("read nothing")
}
return string(pw[0:n]), nil
}
func sendInviteEmail(invite invites.Invite) error {
pw, err := loadPassword()
if err != nil {
return fmt.Errorf("could not read password: %w", err)
}
body := fmt.Sprintf(emailText, invite.Code)
mailer := email.NewExternalMailer(pw)
return mailer.Send(
invite.Email,
"your tilde.town application was accepted",
body)
} }

View File

@ -263,15 +263,16 @@ func _main() error {
updateCount() updateCount()
render() render()
if decision == models.SignupAccepted { if decision == models.SignupAccepted {
if err = invites.InsertInvite(inviteDB, currSignup.CleanEmail); err != nil { invite := &invites.Invite{
Email: currSignup.CleanEmail,
}
if err = invite.Insert(inviteDB); err != nil {
errorModal.SetText(fmt.Sprintf("error! failed to create invite: %s", err.Error())) errorModal.SetText(fmt.Sprintf("error! failed to create invite: %s", err.Error()))
pages.SwitchToPage("error") pages.SwitchToPage("error")
} }
// TODO need to get an invite back from InsertInvite so we can send it to if err = sendInviteEmail(*invite); err != nil {
// the clean email using sendInviteEmail
if err = sendInviteEmail(); err != nil {
errorModal.SetText(fmt.Sprintf("error! failed to send welcome email: %s", err.Error())) errorModal.SetText(fmt.Sprintf("error! failed to send welcome email: %s", err.Error()))
pages.SwitchToPage("error") pages.SwitchToPage("error")
} }

View File

@ -262,7 +262,8 @@ func _main(l *log.Logger, db *sql.DB) error {
newScene("done", heredoc.Doc(` newScene("done", heredoc.Doc(`
thank you for applying to tilde.town! thank you for applying to tilde.town!
please be on the look out for an email from [-:-:b]root@tilde.town[-:-:-] please be on the look out for an email from [-:-:b]root@tilde.town[-:-:-].
it's almost certain that it will end up in your spam filter, unfortunately.
you can [-:-:b]/quit[-:-:-] now you can [-:-:b]/quit[-:-:-] now

View File

@ -9,9 +9,9 @@ import (
) )
const ( const (
SMTPlogin = "root@tilde.town" from = "root@tilde.town"
SMTPHost = "smtp.zoho.com" SMTPHost = "smtp.zoho.com"
SMTPPort = 465 SMTPPort = 465
) )
func SendLocalEmail(username, subject, body string) error { func SendLocalEmail(username, subject, body string) error {
@ -39,8 +39,19 @@ func NewExternalMailer(pw string) *ExternalMailer {
} }
func (m *ExternalMailer) Send(address, subject, body string) error { func (m *ExternalMailer) Send(address, subject, body string) error {
// TODO need to add headers to prepare message headers := map[string]string{
auth := smtp.PlainAuth("", SMTPlogin, m.Password, SMTPHost) "From": from,
"To": address,
"Subject": subject,
}
message := ""
for k, v := range headers {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + body
auth := smtp.PlainAuth("", from, m.Password, SMTPHost)
server := fmt.Sprintf("%s:%d", SMTPHost, SMTPPort) server := fmt.Sprintf("%s:%d", SMTPHost, SMTPPort)

View File

@ -24,6 +24,23 @@ type Invite struct {
Used bool Used bool
} }
func (i *Invite) Insert(db *sql.DB) error {
stmt, err := db.Prepare(`
INSERT INTO invites (code, email) VALUES (?, ?)
`)
if err != nil {
return err
}
_, err = stmt.Exec(generateCode(i.Email), i.Email)
if err != nil {
return err
}
defer stmt.Close()
return nil
}
func ConnectDB() (*sql.DB, error) { func ConnectDB() (*sql.DB, error) {
db, err := sql.Open("sqlite3", dsn) db, err := sql.Open("sqlite3", dsn)
if err != nil { if err != nil {
@ -66,23 +83,6 @@ func Decode(code string) ([]string, error) {
return strings.Split(string(decoded), " "), nil return strings.Split(string(decoded), " "), nil
} }
func InsertInvite(db *sql.DB, email string) error {
stmt, err := db.Prepare(`
INSERT INTO invites (code, email) VALUES (?, ?)
`)
if err != nil {
return err
}
_, err = stmt.Exec(generateCode(email), email)
if err != nil {
return err
}
defer stmt.Close()
return nil
}
func Get(db *sql.DB, code string) (*Invite, error) { func Get(db *sql.DB, code string) (*Invite, error) {
inv := &Invite{ inv := &Invite{
Code: code, Code: code,