diff --git a/cmd/review/email.go b/cmd/review/email.go new file mode 100644 index 0000000..70412e9 --- /dev/null +++ b/cmd/review/email.go @@ -0,0 +1,8 @@ +package main + +// TODO function for reading smtp.pw from /town/docs + +func sendInviteEmail() error { + // TODO + return nil +} diff --git a/cmd/review/main.go b/cmd/review/main.go index 14fe877..5025719 100644 --- a/cmd/review/main.go +++ b/cmd/review/main.go @@ -263,13 +263,18 @@ func _main() error { updateCount() render() if decision == models.SignupAccepted { - err = invites.InsertInvite(inviteDB, currSignup.CleanEmail) - if err != nil { + if err = invites.InsertInvite(inviteDB, currSignup.CleanEmail); err != nil { errorModal.SetText(fmt.Sprintf("error! failed to create invite: %s", err.Error())) pages.SwitchToPage("error") } - // TODO send invite email + // TODO need to get an invite back from InsertInvite so we can send it to + // the clean email using sendInviteEmail + + if err = sendInviteEmail(); err != nil { + errorModal.SetText(fmt.Sprintf("error! failed to send welcome email: %s", err.Error())) + pages.SwitchToPage("error") + } } pages.SwitchToPage("main") }) diff --git a/cmd/welcome/main.go b/cmd/welcome/main.go index 285f1a3..8af7bec 100644 --- a/cmd/welcome/main.go +++ b/cmd/welcome/main.go @@ -16,6 +16,7 @@ import ( _ "embed" ) +// TODO mark on user table what signup id led to the account for forensics // TODO add logging like the signup tool has // TODO consider merging adduser, usermod, and createkeyfile into single createuser helper to limit sudoers list // TODO move magic key machine to static page diff --git a/email/email.go b/email/email.go index 0e22961..1a96684 100644 --- a/email/email.go +++ b/email/email.go @@ -2,10 +2,18 @@ package email import ( "bytes" + "crypto/tls" "fmt" + "net/smtp" "os/exec" ) +const ( + SMTPlogin = "root@tilde.town" + SMTPHost = "smtp.zoho.com" + SMTPPort = 465 +) + func SendLocalEmail(username, subject, body string) error { cmd := exec.Command("/usr/sbin/sendmail", username) cmd.Stdin = bytes.NewBufferString(fmt.Sprintf("Subject: %s\n\n%s", subject, body)) @@ -16,3 +24,65 @@ func SendLocalEmail(username, subject, body string) error { return nil } + +type ExternalMailer struct { + Password string +} + +func NewExternalMailer(pw string) *ExternalMailer { + if pw == "" { + panic("why?") + } + return &ExternalMailer{ + Password: pw, + } +} + +func (m *ExternalMailer) Send(address, subject, body string) error { + // TODO need to add headers to prepare message + auth := smtp.PlainAuth("", SMTPlogin, m.Password, SMTPHost) + + server := fmt.Sprintf("%s:%d", SMTPHost, SMTPPort) + + tlsconf := &tls.Config{ + InsecureSkipVerify: true, + ServerName: server, + } + + conn, err := tls.Dial("tcp", server, tlsconf) + if err != nil { + return err + } + + c, err := smtp.NewClient(conn, SMTPHost) + if err != nil { + return err + } + + if err = c.Auth(auth); err != nil { + return fmt.Errorf("auth failed for smtp: %w", err) + } + + if err = c.Mail("root@tilde.town"); err != nil { + return err + } + + if err = c.Rcpt(address); err != nil { + return err + } + + w, err := c.Data() + if err != nil { + return err + } + + _, err = w.Write([]byte(body)) + if err != nil { + return err + } + + w.Close() + c.Quit() + + return nil +}