summary

package
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package summary is the summary email: a daily or weekly email of what MailRules sorted per rule, what it trashed and what waits in Needs review, with links into the web app. It owns the summary's settings, builds its content from the store, and schedules it: one loop checks every minute whether one is due in the user's time zone. Every summary sent on schedule is recorded in the summaries table first, so a restart or two checks at once never send it twice. It sends through a mailer.Sender and logs counts only, never what an email says or who sent it.

Index

Constants

View Source
const (
	Daily  = "daily"
	Weekly = "weekly"
)

How often a summary goes out.

Variables

View Source
var ErrNoSMTP = errors.New("no outgoing mail server is configured")

ErrNoSMTP is what NoSMTP is, for errors.Is.

View Source
var Weekdays = []string{"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}

Weekdays are the values of Settings.Weekday, Sunday first as time.Weekday counts them.

Functions

This section is empty.

Types

type Content

type Content struct {
	Start, End   time.Time // the time it covers, in the user's zone
	DryRun       bool      // dry-run is on: what it lists was recorded, not done
	Rules        []store.RuleUse
	Sorted       int // emails a rule was applied to, trashed ones included: the sum of Rules
	Trashed      []store.SummaryEmail
	TrashedTotal int
	Review       []store.SummaryEmail // waiting in Needs review now
	ReviewTotal  int
	CostUSD      float64 // what the model decisions in the period cost
	ModelCalls   int
}

Content is what one summary reports, read from the store. It holds senders, subjects, rule names and counts; never an email's text.

type Email

type Email struct {
	Subject string
	Text    string
	HTML    string
}

Email is a rendered summary.

type NoSMTP

type NoSMTP struct{ Missing []string }

NoSMTP refuses switching the summary on while the daemon has no outgoing mail server.

func (*NoSMTP) Error

func (e *NoSMTP) Error() string

func (*NoSMTP) Is

func (e *NoSMTP) Is(err error) bool

func (*NoSMTP) Message

func (e *NoSMTP) Message() string

Message is the sentence for a person: what to set, and that a restart reads it.

type Optional

type Optional struct {
	Set   bool
	Value string // "" for null
}

Optional is a field that may be sent as null: Set says it was sent at all.

func (*Optional) UnmarshalJSON

func (o *Optional) UnmarshalJSON(b []byte) error

UnmarshalJSON takes a string or null.

type Patch

type Patch struct {
	Enabled   *bool    `json:"enabled"`
	Frequency *string  `json:"frequency"`
	Weekday   *string  `json:"weekday"`
	Time      *string  `json:"time"`
	TimeZone  *string  `json:"time_zone"`
	To        Optional `json:"to"`
}

Patch is a change to the settings; nil fields, and To unless Set, stay as they are.

type SendError

type SendError struct{ Err error }

SendError is a summary the mail server did not take: it could not be reached, refused the sign-in or the email, or lacks what the settings require. Err says which.

func (*SendError) Error

func (e *SendError) Error() string

func (*SendError) Unwrap

func (e *SendError) Unwrap() error

type Service

type Service struct {
	Store         *store.Store
	Sender        mailer.Sender // nil = no mail server is configured
	Missing       []string      // the MAILRULES_SMTP_* settings still to set; empty = it can send
	PublicURL     string        // where links in the summary lead (MAILRULES_PUBLIC_URL)
	DryRunDefault bool          // MAILRULES_DRY_RUN, for while the switch is not stored
	Now           func() time.Time
}

Service sends and shows the summary email.

func New

func New(st *store.Store, cfg *config.Config, sender mailer.Sender) *Service

New returns the service for the daemon's configuration, sending through sender.

func (*Service) Prepare

func (s *Service) Prepare(ctx context.Context, p Patch) (commit func(context.Context) error, err error)

Prepare validates a change to the settings and returns what stores it. Nothing is stored until commit runs, so the caller can check its other changes first. A problem the user can fix is a *settings.Invalid; switching on without a mail server is a *NoSMTP.

func (*Service) Preview

func (s *Service) Preview(ctx context.Context, u store.User) (Email, Content, string, error)

Preview renders the summary the next scheduled one would be if it went now, and the address it would go to.

func (*Service) Ready

func (s *Service) Ready() bool

Ready reports whether a summary can be sent.

func (*Service) Run

func (s *Service) Run(ctx context.Context)

Run checks the schedule now and then every minute until ctx ends.

func (*Service) SendTest

func (s *Service) SendTest(ctx context.Context, u store.User) (Email, string, error)

SendTest sends a summary of the last day now, to the summary's address, whether the summary is on or not. It is not recorded as a scheduled summary.

func (*Service) Tick

func (s *Service) Tick(ctx context.Context) error

Tick sends the admin's summary when one is due and has not gone out. It is safe to call from two places at once: store.ClaimSummary lets only one of them send.

func (*Service) View

func (s *Service) View(ctx context.Context, u store.User) (View, error)

View returns the settings in force for the user.

type Settings

type Settings struct {
	Enabled   bool   `json:"enabled"`
	Frequency string `json:"frequency"`  // Daily | Weekly
	Weekday   string `json:"weekday"`    // one of Weekdays; used while Weekly
	Time      string `json:"time"`       // HH:MM, 24-hour, in TimeZone
	TimeZone  string `json:"time_zone"`  // IANA name, as the browser reported it
	To        string `json:"to"`         // one address; "" = the admin account's email
	EnabledAt int64  `json:"enabled_at"` // when it was last switched on: a summary due before then is not sent
}

Settings are the summary email's settings, stored as one JSON object in the settings table (store.SettingSummary). The zero value is not valid; defaults fills it in.

type View

type View struct {
	Settings
	ToDefault  string   // the admin account's email
	Configured bool     // a mail server is set
	Missing    []string // what to set before one is; never nil
	LastSentAt int64    // 0 = none yet
	NextAt     int64    // 0 = none: off, or no mail server
}

View is the summary's settings as GET /api/settings shows them.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL