internal/control/adminmail.go
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}