package cli import "fmt" // DoctorCmd runs connectivity/auth diagnostics. For each account (optionally // filtered to one), it checks IMAP and — for RW accounts with an SMTP host — // SMTP, printing a human-readable per-check result. It returns errCommandFailed // if any check fails so the process can exit non-zero. Secrets are never printed. func DoctorCmd(d Deps, account string) error { accounts, err := d.Store.ListAccounts() if err != nil { fmt.Fprintf(d.Out, "FAIL: cannot list accounts: %v\n", err) return errCommandFailed } anyFail := false checked := 0 for _, listed := range accounts { if account != "" && listed.Name != account { continue } checked++ // ListAccounts strips secrets; re-fetch to get decrypted credentials. a, err := d.Store.GetAccount(listed.Name) if err != nil { fmt.Fprintf(d.Out, "%s\n FAIL: %v\n", listed.Name, err) anyFail = true continue } fmt.Fprintf(d.Out, "%s (%s)\n", a.Name, a.Mode) if err := d.CheckIMAP(a); err != nil { fmt.Fprintf(d.Out, " IMAP FAIL: %v\n", err) anyFail = true } else { fmt.Fprintf(d.Out, " IMAP ok\n") } switch { case a.Mode != "RW": fmt.Fprintf(d.Out, " SMTP n/a (read-only)\n") case a.SMTPHost == "": fmt.Fprintf(d.Out, " SMTP n/a (no smtp host configured)\n") default: if err := d.CheckSMTP(a); err != nil { fmt.Fprintf(d.Out, " SMTP FAIL: %v\n", err) anyFail = true } else { fmt.Fprintf(d.Out, " SMTP ok\n") } } } if account != "" && checked == 0 { fmt.Fprintf(d.Out, "FAIL: account not found: %s\n", account) return errCommandFailed } if anyFail { return errCommandFailed } return nil }