1package service23import (4 "bytes"5 "embed"6 "fmt"7 gomail "net/mail"8 "text/template"910 "git.lin.moe/go/mlisting/storage"11 "github.com/emersion/go-message/mail"12 "github.com/emersion/go-message/textproto"13)1415//go:embed templates/listtext16var textFiles embed.FS1718type Template interface {19 Message() (*gomail.Message, error)20}2122type TemplateError interface {23 Template24 Error() string25}2627type DeniedReason string2829const (30 DENIED_SUBSCRIBE_NOPERM DeniedReason = "subscribe_noperm"31 DENIED_SUBSCRIBED_ALREADY DeniedReason = "subscribe_already"3233 DENIED_POST_NOPERM DeniedReason = "post_noperm"3435 DENIED_REPLY_NOPERM DeniedReason = "reply_noperm"36 DENIED_REPLY_TO_NONE DeniedReason = "reply_to_none"37)3839func addressWithAction(addr string, act string) string {40 return (&Address{Address: addr}).WithAction(act).String()41}42func messageId(header textproto.Header) string {43 h := mail.HeaderFromMap(header.Map())44 msgId, _ := h.MessageID()45 return msgId46}4748var funcMap = template.FuncMap{49 "addrWithAction": addressWithAction,50 "messageId": messageId,51}5253type TemplateDenied struct {54 List storage.List55 InHeader textproto.Header56 Reason DeniedReason57}5859func (t *TemplateDenied) Error() string { return "action denied" }60func (t *TemplateDenied) Message() (*gomail.Message, error) {61 tpl, err := template.New("denied.txt").62 Funcs(funcMap).63 ParseFS(textFiles, "templates/listtext/denied.txt")64 if err != nil {65 return nil, err66 }67 var buf = bytes.NewBuffer(nil)68 if err := tpl.Execute(buf, t); err != nil {69 return nil, fmt.Errorf("template execute: %v", err)70 }71 return gomail.ReadMessage(buf)72}7374type TemplateNeedConfirm struct {75 List storage.List76 InHeader textproto.Header77 RequestType storage.RequestType78 Token string79}8081func (t *TemplateNeedConfirm) Error() string { return "need confirmation" }82func (t *TemplateNeedConfirm) Message() (*gomail.Message, error) {83 tpl, err := template.New("need_confirm.txt").84 Funcs(funcMap).85 ParseFS(textFiles, "templates/listtext/need_confirm.txt")86 if err != nil {87 return nil, err88 }89 var buf = bytes.NewBuffer(nil)90 if err := tpl.Execute(buf, t); err != nil {91 return nil, fmt.Errorf("template execute: %v", err)92 }93 return gomail.ReadMessage(buf)94}9596type TemplatePostRequest struct {97 InHeader textproto.Header98 List storage.List99 RequestType storage.RequestType100}101102func (t *TemplatePostRequest) Error() string { return "post request action" }103func (t *TemplatePostRequest) Message() (*gomail.Message, error) {104 tpl, err := template.New("post_request.txt").105 Funcs(funcMap).106 ParseFS(textFiles, "templates/listtext/post_request.txt")107 if err != nil {108 return nil, err109 }110 var buf = bytes.NewBuffer(nil)111 if err := tpl.Execute(buf, t); err != nil {112 return nil, fmt.Errorf("template execute: %v", err)113 }114 return gomail.ReadMessage(buf)115}