package emailApi import ( "fmt" "git.stuve.uni-ulm.de/stuve-it/stuve-it-backend/logger" "github.com/microcosm-cc/bluemonday" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/tools/mailer" "github.com/pocketbase/pocketbase/tools/template" "net/mail" ) // sendEmailToUser sends an email notification to the user func sendEmailToUser(app *pocketbase.PocketBase, registry *template.Registry, recipient *models.Record, sender *models.Record, emailRecord *models.Record) { // check if recipient and message are set and recipient is not the sender if recipient == nil || emailRecord == nil || sender == nil { return } // sanitize email content policy := bluemonday.UGCPolicy() content := emailRecord.GetString("content") safeContent := policy.Sanitize(content) // get recipient and sender email recipientEmail := recipient.GetString("email") senderEmail := sender.GetString("email") // render email template html, err := registry.LoadFiles( "html/blankEmail.html", ).Render(map[string]any{ "APP_URL": app.Settings().Meta.AppUrl, "SENDER_SN": sender.GetString("sn"), "SENDER_GIVENNAME": sender.GetString("givenName"), "SENDER_EMAIL": senderEmail, "CONTENT": safeContent, }) if err != nil { currentErrors := emailRecord.GetString("errors") emailRecord.Set("errors", fmt.Sprintf("%s\nThe email was not sent to the user '%s' due to an error.", currentErrors, recipient.Username())) logger.LogErrorF("Error rendering email notification to recipient with username '%s': %v", recipient.GetString("username"), err) return } // get email subject subject := emailRecord.GetString("subject") // set reply-to header headers := make(map[string]string) headers["Reply-To"] = senderEmail // send email email := &mailer.Message{ From: mail.Address{ Address: app.Settings().Meta.SenderAddress, Name: app.Settings().Meta.SenderName, }, To: []mail.Address{{Address: recipientEmail}}, Subject: "[StuVe IT] " + subject, HTML: html, Headers: headers, } if err := app.NewMailClient().Send(email); err != nil { currentErrors := emailRecord.GetString("errors") emailRecord.Set("errors", fmt.Sprintf("%s\nThe email was not sent to the user '%s' due to an error.", currentErrors, recipient.Username())) logger.LogErrorF("Error sending email notification to recipient with username '%s': %v", recipient.GetString("username"), err) } } func sendEmails(app *pocketbase.PocketBase, emailRecord *models.Record) { registry := template.NewRegistry() // expand the createdMessageRecord to get recipient user and send email notification if recipient is set if errs := app.Dao().ExpandRecord(emailRecord, []string{"recipients", "sender"}, nil); len(errs) > 0 { // return new error with all errors logger.LogErrorF("Error expanding created email record: %v", errs) emailRecord.Set("errors", fmt.Sprintf("The email was not sent to anyone due to an error.")) return } sender := emailRecord.ExpandedOne("sender") recipients := emailRecord.ExpandedAll("recipients") for _, recipient := range recipients { sendEmailToUser(app, registry, recipient, sender, emailRecord) } return } // InitEmailApi initializes the email notifier // // the function sends an email notification after it was created func InitEmailApi(app *pocketbase.PocketBase, _ *core.ServeEvent) error { logger.LogInfoF("Adding email notifier") app.OnModelAfterCreate("emails").Add(func(e *core.ModelEvent) error { // get created message record createdMessageRecord, err := app.Dao().FindRecordById("emails", e.Model.GetId()) if err != nil { return err } go sendEmails(app, createdMessageRecord) return nil }) return nil }