internal/control/adminmail.go

v1.40.1
gitbay/internal/control/adminmail.go history · blame · raw

75 lines · 2408 bytes

 1package control
 2
 3import (
 4	"fmt"
 5	"io"
 6	"time"
 7
 8	"gitbay.org/gitbay/internal/imapc"
 9	"gitbay.org/gitbay/internal/protocol"
10)
11
12func init() {
13	register(Command{Path: []string{"admin", "mail", "inbound", "check"},
14		Summary:  "connect to the reply mailbox read-only and report what is waiting",
15		Usage:    "admin mail inbound check",
16		Examples: []string{"admin mail inbound check"},
17		ReadOnly: true, Run: runAdminMailInboundCheck})
18}
19
20const unauthenticatedWarning = "require_dkim and trusted_authserv_id are unset: a reply's From is not authenticated"
21
22// runAdminMailInboundCheck logs in to the [mail.inbound] mailbox and
23// opens it with EXAMINE, which changes no flag, so a check never marks a
24// reply seen before the poller reads it.
25func runAdminMailInboundCheck(c *Ctx, args []string) int {
26	if code := requireInstanceAdmin(c); code >= 0 {
27		return code
28	}
29	if len(args) != 0 {
30		return c.usage()
31	}
32	in := c.Cfg.Mail.Inbound
33	type out struct {
34		Enabled  bool   `json:"enabled"`
35		Server   string `json:"server,omitempty"`
36		Mailbox  string `json:"mailbox,omitempty"`
37		Messages int    `json:"messages"`
38		Unseen   int    `json:"unseen"`
39		// RequireDKIM and TrustedAuthservID are how a reply's From
40		// is authenticated.
41		RequireDKIM       bool   `json:"require_dkim"`
42		TrustedAuthservID string `json:"trusted_authserv_id,omitempty"`
43		Warning           string `json:"warning,omitempty"`
44	}
45	if !in.Enabled {
46		return c.emit(out{}, func(w io.Writer) {
47			fmt.Fprintln(w, "inbound mail is off ([mail.inbound] enabled = false)")
48		})
49	}
50	cl, n, err := imapc.Open(in, true, 30*time.Second)
51	if err != nil {
52		return c.fail(protocol.ExitFailure, "%s: %v", in.Addr(), err)
53	}
54	defer cl.Close()
55	unseen, err := cl.Unseen()
56	if err != nil {
57		return c.fail(protocol.ExitFailure, "%s: %v", in.Addr(), err)
58	}
59	d := out{Enabled: true, Server: in.Addr(), Mailbox: in.MailboxName(), Messages: n, Unseen: len(unseen),
60		RequireDKIM: in.RequireDKIM, TrustedAuthservID: in.TrustedAuthservID}
61	if !in.Authenticated() {
62		d.Warning = unauthenticatedWarning
63		fmt.Fprintln(c.Stderr, "warning: "+d.Warning)
64	}
65	return c.emit(d, func(w io.Writer) {
66		c.view(w).fields(
67			"server", d.Server,
68			"mailbox", d.Mailbox,
69			"messages", fmt.Sprintf("%d", d.Messages),
70			"unseen", fmt.Sprintf("%d", d.Unseen),
71			"require_dkim", fmt.Sprintf("%t", d.RequireDKIM),
72			"trusted_authserv_id", d.TrustedAuthservID,
73		)
74	})
75}