mlisting

Mailing list service

git clone git://git.lin.moe/go/mlisting.git

  1package service
  2
  3import (
  4	"bytes"
  5	"embed"
  6	"fmt"
  7	gomail "net/mail"
  8	"text/template"
  9
 10	"git.lin.moe/go/mlisting/storage"
 11	"github.com/emersion/go-message/mail"
 12	"github.com/emersion/go-message/textproto"
 13)
 14
 15//go:embed templates/listtext
 16var textFiles embed.FS
 17
 18type Template interface {
 19	Message() (*gomail.Message, error)
 20}
 21
 22type TemplateError interface {
 23	Template
 24	Error() string
 25}
 26
 27type DeniedReason string
 28
 29const (
 30	DENIED_SUBSCRIBE_NOPERM   DeniedReason = "subscribe_noperm"
 31	DENIED_SUBSCRIBED_ALREADY DeniedReason = "subscribe_already"
 32
 33	DENIED_POST_NOPERM DeniedReason = "post_noperm"
 34
 35	DENIED_REPLY_NOPERM  DeniedReason = "reply_noperm"
 36	DENIED_REPLY_TO_NONE DeniedReason = "reply_to_none"
 37)
 38
 39func 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 msgId
 46}
 47
 48var funcMap = template.FuncMap{
 49	"addrWithAction": addressWithAction,
 50	"messageId":      messageId,
 51}
 52
 53type TemplateDenied struct {
 54	List     storage.List
 55	InHeader textproto.Header
 56	Reason   DeniedReason
 57}
 58
 59func (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, err
 66	}
 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}
 73
 74type TemplateNeedConfirm struct {
 75	List        storage.List
 76	InHeader    textproto.Header
 77	RequestType storage.RequestType
 78	Token       string
 79}
 80
 81func (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, err
 88	}
 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}
 95
 96type TemplatePostRequest struct {
 97	InHeader    textproto.Header
 98	List        storage.List
 99	RequestType storage.RequestType
100}
101
102func (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, err
109	}
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}