package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" ) // The response from a get reqeuest to the postmark tempalte API. type PostmarkTemplate struct { TemplateId int Name string Subject string HtmlBody string TextBody string AssociatedServerId int Active bool Alias string TemplateType string LayoutTemplate string } // The model that we're using for the template that abner made type PostmarkTemplateModel struct { Name string `json:"name"` Email string `json:"email"` Body string `json:"body"` Subject string `json:"subject"` } // The request body for the postmark validate endpoint which renders a provided tempalte if its valid type ValidateTemplateBody struct { Subject string HTMLBody string TextBody string TestRenderModel PostmarkTemplateModel // There are other body options but i think this is all we care about // InlineCssForHtmlTestRender bool // TemplateType string } // The validation error types returned from the postmark template validation api type ValidationError struct { Message string Line int CharacterPosition int } type ContentBodyValidationResponse struct { ContentIsValid bool ValidationErrors []ValidationError RenderedContent string } // The response from the postmark tempalte validation endpoint type ValidationResponse struct { AllContentIsValid bool Subject ContentBodyValidationResponse HtmlBody ContentBodyValidationResponse TextBody ContentBodyValidationResponse SuggestedTemplateModel interface{} } // Gets the tempalte in the postmark config section of the app.ini file from teh postmark server so we can render it func getPostmarkTemplate(cfg PostmarkConfig) PostmarkTemplate { // Get Template getTemplateURL := fmt.Sprintf("https://api.postmarkapp.com/templates/%v", cfg.TemplateId) getReq, err := http.NewRequest(http.MethodGet, getTemplateURL, bytes.NewBuffer([]byte(""))) if err != nil { panic(err) } getReq.Header.Add("Accept", "application/json") getReq.Header.Add("X-Postmark-Server-Token", cfg.ServerToken) client := &http.Client{} getResp, err := client.Do(getReq) if err != nil { panic(err) } defer getReq.Body.Close() template := PostmarkTemplate{} decode_error := json.NewDecoder(getResp.Body).Decode(&template) if decode_error != nil { panic(decode_error) } return template } // Given a tempalte and model use the postmark tempalte validation api to render the template func renderPostmarkTemplate(cfg PostmarkConfig, template PostmarkTemplate, model PostmarkTemplateModel) string { bodyObj := ValidateTemplateBody{ Subject: template.Subject, HTMLBody: template.HtmlBody, TextBody: template.TextBody, TestRenderModel: model, } body, err := json.Marshal(bodyObj) if err != nil { panic(err) } req, err := http.NewRequest("POST", "https://api.postmarkapp.com/templates/validate", bytes.NewBuffer(body)) if err != nil { panic(err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") req.Header.Add("X-Postmark-Server-Token", cfg.ServerToken) client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() response := &ValidationResponse{} rawBodyContent, err := io.ReadAll(resp.Body) if err != nil { panic(err) } decode_error := json.NewDecoder(bytes.NewBuffer(rawBodyContent)).Decode(response) if decode_error != nil { panic(decode_error) } return response.HtmlBody.RenderedContent }