diff --git a/background/comms.go b/background/comms.go index e5e81390..0af5277b 100644 --- a/background/comms.go +++ b/background/comms.go @@ -97,8 +97,19 @@ func startWorkerText(ctx context.Context, channel chan jobText) { } func jobProcessEmail(job jobEmail) error { - log.Info().Str("dest", job.Destination).Str("type", string(job.Type)).Msg("Pretend doing email job") - return nil + switch job.Type { + case enums.CommsMessagetypeemailInitialContact: + return comms.SendEmailInitialContact(job.Destination) + default: + return errors.New("not implemented") + } + /* + case enums.CommsMessagetypeemailReportSubscriptionConfirmation: + case enums.CommsMessagetypeemailReportStatusScheduled: + case enums.CommsMessagetypeemailReportStatusComplete: + + } + */ } func jobProcessText(job jobText) error { diff --git a/comms/email.go b/comms/email.go index a2e2a992..26c43f1b 100644 --- a/comms/email.go +++ b/comms/email.go @@ -13,13 +13,39 @@ import ( "github.com/rs/zerolog/log" ) +func RenderEmailInitial(w http.ResponseWriter, destination string) { + content := newContentEmailInitial(destination) + renderOrError(w, initialT, content) +} + func RenderEmailReportConfirmation(w http.ResponseWriter, report_id string) { - content := contentEmailSubscriptionConfirmation(report_id) + content := newContentEmailSubscriptionConfirmation(report_id) renderOrError(w, reportConfirmationT, content) } + +func SendEmailInitialContact(destination string) error { + content := newContentEmailInitial(destination) + text, html, err := renderEmailTemplates(reportConfirmationT, content) + if err != nil { + return fmt.Errorf("Failed to render email temlate: %w", err) + } + resp, err := sendEmail(emailRequest{ + From: config.ForwardEmailReportAddress, + HTML: html, + Subject: "Welcome", + Text: text, + To: destination, + }) + if err != nil { + return fmt.Errorf("Failed to send email to %s: %w", err) + } + log.Info().Str("id", resp.ID).Str("to", destination).Msg("Sent initial contact email") + return nil +} + func SendEmailReportConfirmation(to string, report_id string) error { report_id_str := publicReportID(report_id) - content := contentEmailSubscriptionConfirmation(report_id) + content := newContentEmailSubscriptionConfirmation(report_id) text, html, err := renderEmailTemplates(reportConfirmationT, content) if err != nil { return fmt.Errorf("Failed to render template %s: %w", reportConfirmationT.name, err) @@ -39,6 +65,7 @@ func SendEmailReportConfirmation(to string, report_id string) error { } var ( + initialT = buildTemplate("initial") reportConfirmationT = buildTemplate("report-subscription-confirmation") ) @@ -50,11 +77,20 @@ type attachmentRequest struct { Content string `json:"content"` } +type contentEmailBase struct { + URLLogo string + URLUnsubscribe string + URLViewInBrowser string +} + type contentEmailReportConfirmation struct { - URLLogo string - URLReportStatus string - URLReportUnsubscribe string - URLViewInBrowser string + Base contentEmailBase + URLReportStatus string +} +type contentEmailInitial struct { + Base contentEmailBase + Destination string + URLSubscribe string } type emailRequest struct { @@ -104,13 +140,28 @@ type emailResponse struct { Message string `json:"message"` } -func contentEmailSubscriptionConfirmation(report_id string) contentEmailReportConfirmation { - return contentEmailReportConfirmation{ - URLLogo: config.MakeURLReport("/static/img/nidus-logo-no-lettering-64.png"), - URLReportStatus: config.MakeURLReport("/status/%s", report_id), - URLReportUnsubscribe: config.MakeURLReport("/report/%s/unsubscribe", report_id), - URLViewInBrowser: config.MakeURLReport("/email/report/%s/subscription-confirmation", report_id), - } +func newContentBase(b *contentEmailBase, url string) { + b.URLLogo = config.MakeURLReport("/static/img/nidus-logo-no-lettering-64.png") + b.URLUnsubscribe = config.MakeURLReport("/email/unsubscribe") + b.URLViewInBrowser = url +} + +func newContentEmailInitial(destination string) (result contentEmailInitial) { + newContentBase( + &result.Base, + config.MakeURLReport("/email/initial"), + ) + result.Destination = destination + result.URLSubscribe = config.MakeURLReport("/email/subscribe?email=%s", destination) + return result +} +func newContentEmailSubscriptionConfirmation(report_id string) (result contentEmailReportConfirmation) { + newContentBase( + &result.Base, + config.MakeURLReport("/email/report/%s/subscription-confirmation", report_id), + ) + result.URLReportStatus = config.MakeURLReport("/status/%s", report_id) + return result } func publicReportID(s string) string { diff --git a/comms/template/initial.html b/comms/template/initial.html new file mode 100644 index 00000000..821db38a --- /dev/null +++ b/comms/template/initial.html @@ -0,0 +1,97 @@ + + + + + + Welcome + + + +
+
+ Email not displaying correctly? View it in your browser +
+ +
+ + +
+ +
+

Welcome

+ +

We're sending you this email because it's the first time we've gotten this email address ({{.Destination}}).

+ +

If you'd rather not receive emails from us you can reply with "Unsubscribe" in the subject or body of the email. You can also use the "Unsubscribe" feature of your mail client, if it supports list unsubscribes.

+ +

If instead you'd like to confirm that you're willing to receive emails at this address, you can do so by clicking below:

+ +
+ I want emails from Report Mosquitoes Online +
+
+ + +
+ + diff --git a/comms/template/initial.txt b/comms/template/initial.txt new file mode 100644 index 00000000..eaf6a7cc --- /dev/null +++ b/comms/template/initial.txt @@ -0,0 +1 @@ +Welcome to Report Mosquitoes Online. diff --git a/config/config.go b/config/config.go index 51a72f85..584e5f0c 100644 --- a/config/config.go +++ b/config/config.go @@ -2,6 +2,7 @@ package config import ( "fmt" + "net/url" "os" "github.com/nyaruka/phonenumbers" @@ -35,18 +36,22 @@ func IsProductionEnvironment() bool { return Environment == "PRODUCTION" } -func makeURL(domain, path string, args ...interface{}) string { +func makeURL(domain, path string, args ...string) string { + to_add := make([]any, 0) + for _, a := range args { + to_add = append(to_add, url.QueryEscape(a)) + } pattern := "https://" + domain + path - return fmt.Sprintf(pattern, args...) + return fmt.Sprintf(pattern, to_add...) } -func MakeURLNidus(path string, args ...interface{}) string { +func MakeURLNidus(path string, args ...string) string { return makeURL(DomainNidus, path, args...) } -func MakeURLReport(path string, args ...interface{}) string { +func MakeURLReport(path string, args ...string) string { return makeURL(DomainRMO, path, args...) } -func MakeURLTegola(path string, args ...interface{}) string { +func MakeURLTegola(path string, args ...string) string { return makeURL(DomainTegola, path, args...) } diff --git a/public-report/email.go b/public-report/email.go new file mode 100644 index 00000000..e39d9de0 --- /dev/null +++ b/public-report/email.go @@ -0,0 +1,17 @@ +package publicreport + +import ( + "net/http" + + "github.com/Gleipnir-Technology/nidus-sync/comms" + "github.com/go-chi/chi/v5" +) + +func getEmailInitial(w http.ResponseWriter, r *http.Request) { + email := chi.URLParam(r, "email") + comms.RenderEmailInitial(w, email) +} +func getEmailReportSubscriptionConfirmation(w http.ResponseWriter, r *http.Request) { + report_id := chi.URLParam(r, "report_id") + comms.RenderEmailReportConfirmation(w, report_id) +} diff --git a/public-report/quick.go b/public-report/quick.go index bf2106c8..0c344f41 100644 --- a/public-report/quick.go +++ b/public-report/quick.go @@ -75,7 +75,7 @@ func getQuickSubmitComplete(w http.ResponseWriter, r *http.Request) { log.Debug().Int32("org_id", org.ID).Int32("d_gid", d.Gid).Msg("Getting district") if d != nil { district = &District{ - LogoURL: config.MakeURLNidus("/api/district/%d/logo", org_id), + LogoURL: config.MakeURLNidus("/api/district/%s/logo", strconv.Itoa(int(org_id))), Name: d.Agency.GetOr("Unknown"), } } diff --git a/public-report/report.go b/public-report/report.go index 3a6960bd..b5baeb8f 100644 --- a/public-report/report.go +++ b/public-report/report.go @@ -4,11 +4,7 @@ import ( "crypto/rand" "fmt" "math/big" - "net/http" "strings" - - "github.com/Gleipnir-Technology/nidus-sync/comms" - "github.com/go-chi/chi/v5" ) // GenerateReportID creates a 12-character random string using only unambiguous @@ -35,8 +31,3 @@ func GenerateReportID() (string, error) { return builder.String(), nil } - -func getEmailReportSubscriptionConfirmation(w http.ResponseWriter, r *http.Request) { - report_id := chi.URLParam(r, "report_id") - comms.RenderEmailReportConfirmation(w, report_id) -} diff --git a/public-report/routes.go b/public-report/routes.go index d843af5f..5fefd950 100644 --- a/public-report/routes.go +++ b/public-report/routes.go @@ -10,6 +10,7 @@ func Router() chi.Router { r.Get("/", getRoot) r.Get("/privacy", getPrivacy) r.Get("/robots.txt", getRobots) + r.Get("/email/initial", getEmailInitial) r.Get("/email/report/{report_id}/subscription-confirmation", getEmailReportSubscriptionConfirmation) r.Get("/image/{uuid}", getImageByUUID) r.Get("/nuisance", getNuisance) diff --git a/public-report/status.go b/public-report/status.go index 04a10351..02b908be 100644 --- a/public-report/status.go +++ b/public-report/status.go @@ -185,7 +185,7 @@ func contentFromQuick(ctx context.Context, report_id string) (result ContentStat for _, image := range images { result.Report.Images = append(result.Report.Images, Image{ Location: image.LocationJSON, - URL: config.MakeURLReport("/image/%s", image.StorageUUID), + URL: config.MakeURLReport("/image/%s", image.StorageUUID.String()), }) } type LocationGeoJSON struct {