@@ -10,6 +10,7 @@ import (
1010 "github.com/indexdata/crosslink/broker/events"
1111 "github.com/indexdata/crosslink/broker/ill_db"
1212 pr_db "github.com/indexdata/crosslink/broker/patron_request/db"
13+ "github.com/indexdata/crosslink/broker/patron_request/proapi"
1314 psservice "github.com/indexdata/crosslink/broker/pullslip/service"
1415 "github.com/indexdata/go-utils/utils"
1516)
2021 MAX_RECORDS_PER_EMAIL = int32 (utils .Must (utils .GetEnvInt ("BATCH_PULLSLIP_MAX_COUNT" , 100 )))
2122)
2223
24+ type pullslipEmailData struct {
25+ To []string `json:"to"`
26+ TemplateLabel string `json:"templateLabel"`
27+ IncludePdf bool `json:"includePdf"`
28+ }
29+
2330type EmailSenderService struct {
2431 prRepo pr_db.PrRepo
2532 illRepo ill_db.IllRepo
@@ -85,11 +92,24 @@ func (s *EmailSenderService) generateAndEmailPullslip(ctx common.ExtendedContext
8592 if len (emailData .To ) == 0 {
8693 return events .NewErrorResult ("invalid email event data" , "to field is required" )
8794 }
88- if emailData .Subject == "" {
89- return events .NewErrorResult ("invalid email event data" , "subject field is required" )
95+ if emailData .TemplateLabel == "" {
96+ return events .NewErrorResult ("invalid email event data" , "templateLabel field is required" )
97+ }
98+
99+ template , err := s .prRepo .GetTemplateByPurposeAudienceLabelAndOwner (ctx , pr_db.GetTemplateByPurposeAudienceLabelAndOwnerParams {
100+ Owner : event .EventData .BatchActionData .Owner ,
101+ Purpose : string (proapi .Email ),
102+ Label : emailData .TemplateLabel ,
103+ Audience : string (proapi .ModelActionParamsSendToStaff ),
104+ })
105+ if err != nil {
106+ return events .NewErrorResult ("failed to load email template" , err .Error ())
107+ }
108+ if ! template .Subject .Valid || template .Subject .String == "" {
109+ return events .NewErrorResult ("invalid email template" , "subject field is required" )
90110 }
91- if emailData .Body == "" {
92- return events .NewErrorResult ("invalid email event data " , "body field is required" )
111+ if template .Body == "" {
112+ return events .NewErrorResult ("invalid email template " , "body field is required" )
93113 }
94114
95115 prs , fullCount , err := s .prRepo .ListPatronRequests (ctx , pr_db.ListPatronRequestsParams {Limit : MAX_RECORDS_PER_EMAIL , Offset : 0 }, pgcql )
@@ -114,31 +134,47 @@ func (s *EmailSenderService) generateAndEmailPullslip(ctx common.ExtendedContext
114134 pdfAttachment = & email.PdfAttach {Filename : "pull-slips.pdf" , Data : pdfBytes }
115135 }
116136
117- emailData .Body = strings .ReplaceAll (emailData .Body , "{{fullCount}}" , fmt .Sprintf ("%d" , fullCount ))
118- emailData .Body = strings .ReplaceAll (emailData .Body , "{{actualCount}}" , fmt .Sprintf ("%d" , len (prs )))
119- emailData .Body = strings .ReplaceAll (emailData .Body , "{{batchQuery}}" , event .EventData .BatchActionData .Selector )
137+ placeholders := map [string ]string {
138+ "fullCount" : fmt .Sprintf ("%d" , fullCount ),
139+ "actualCount" : fmt .Sprintf ("%d" , len (prs )),
140+ "batchQuery" : event .EventData .BatchActionData .Selector ,
141+ }
142+ messageData := email.EmailData {
143+ To : emailData .To ,
144+ Subject : renderEmailTemplate (template .Subject .String , placeholders ),
145+ Body : renderEmailTemplate (template .Body , placeholders ),
146+ IsHTML : template .ContentType == string (proapi .Html ),
147+ IncludePdf : emailData .IncludePdf ,
148+ }
120149
121- raw , err := email .BuildRawMessage (* owner .CustomData .FromEmail , emailData , pdfAttachment )
150+ raw , err := email .BuildRawMessage (* owner .CustomData .FromEmail , messageData , pdfAttachment )
122151 if err != nil {
123152 return events .NewErrorResult ("failed to build email message" , err .Error ())
124153 }
125154
126- err = s .emailService .SendEmail (* owner .CustomData .FromEmail , emailData .To , raw )
155+ err = s .emailService .SendEmail (* owner .CustomData .FromEmail , messageData .To , raw )
127156 if err != nil {
128157 return events .NewErrorResult ("failed to send email via SMTP" , err .Error ())
129158 }
130159 return events .EventStatusSuccess , nil
131160}
132161
133- // extractEmailData retrieves EmailData from the event's CustomData map.
134- func extractEmailData (eventData events.EventData ) (email.EmailData , error ) {
162+ func renderEmailTemplate (value string , placeholders map [string ]string ) string {
163+ for key , replacement := range placeholders {
164+ value = strings .ReplaceAll (value , "{{" + key + "}}" , replacement )
165+ }
166+ return value
167+ }
168+
169+ // extractEmailData retrieves email pullslip parameters from the event's CustomData map.
170+ func extractEmailData (eventData events.EventData ) (pullslipEmailData , error ) {
135171 if eventData .CustomData == nil {
136- return email. EmailData {}, fmt .Errorf ("customData is nil" )
172+ return pullslipEmailData {}, fmt .Errorf ("customData is nil" )
137173 }
138174
139175 toRaw , ok := eventData .CustomData ["to" ]
140176 if ! ok {
141- return email. EmailData {}, fmt .Errorf ("missing 'to' field in customData" )
177+ return pullslipEmailData {}, fmt .Errorf ("missing 'to' field in customData" )
142178 }
143179 var toAddrs []string
144180 switch v := toRaw .(type ) {
@@ -148,24 +184,20 @@ func extractEmailData(eventData events.EventData) (email.EmailData, error) {
148184 for _ , item := range v {
149185 s , ok := item .(string )
150186 if ! ok {
151- return email. EmailData {}, fmt .Errorf ("'to' field contains non-string value" )
187+ return pullslipEmailData {}, fmt .Errorf ("'to' field contains non-string value" )
152188 }
153189 toAddrs = append (toAddrs , s )
154190 }
155191 default :
156- return email. EmailData {}, fmt .Errorf ("'to' field has unexpected type %T" , toRaw )
192+ return pullslipEmailData {}, fmt .Errorf ("'to' field has unexpected type %T" , toRaw )
157193 }
158194
159- subject , _ := eventData .CustomData ["subject" ].(string )
160- body , _ := eventData .CustomData ["body" ].(string )
161- isHTML , _ := eventData .CustomData ["isHtml" ].(bool )
195+ templateLabel , _ := eventData .CustomData ["templateLabel" ].(string )
162196 includePdf , _ := eventData .CustomData ["includePdf" ].(bool )
163197
164- return email.EmailData {
165- To : toAddrs ,
166- Subject : subject ,
167- Body : body ,
168- IsHTML : isHTML ,
169- IncludePdf : includePdf ,
198+ return pullslipEmailData {
199+ To : toAddrs ,
200+ TemplateLabel : templateLabel ,
201+ IncludePdf : includePdf ,
170202 }, nil
171203}
0 commit comments