// Copyright (c) 2026 Sławomir Koszewski. All rights reserved. // Use of this source code is governed by the MIT License // that can be found in the LICENSE file. package main import ( "flag" "fmt" "os" miab "gitea.koszewscy.waw.pl/koszewscy/mailinabox-go" ) func usage() { fmt.Fprintf(os.Stderr, `Usage: miab [options] Commands: list [--type TYPE] List custom DNS records set [--type TYPE] Set (replace) a DNS record add [--type TYPE] Add a DNS record delete [--type TYPE] [value] Delete a DNS record Credentials: any empty parameter falls back to environment variables. MIAB_HOST / MAILINABOX_BASE_URL Mail-in-a-Box hostname (MIAB_HOST takes precedence; hostname is parsed from MAILINABOX_BASE_URL if set) MIAB_USERNAME / MAILINABOX_EMAIL Admin email address MIAB_PASSWORD / MAILINABOX_PASSWORD Admin password `) } func miabClient() *miab.Client { c, err := miab.NewClient("", "", "") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } return c } func main() { flag.Usage = usage flag.Parse() if flag.NArg() < 1 { usage() os.Exit(1) } cmd := flag.Arg(0) args := flag.Args()[1:] switch cmd { case "list": runList(args) case "set": runSet(args) case "delete": runDelete(args) case "add": runAdd(args) default: fmt.Fprintf(os.Stderr, "miab: unknown command %q\n", cmd) usage() os.Exit(1) } } func runList(args []string) { fs := flag.NewFlagSet("list", flag.ExitOnError) recordType := fs.String("type", "", "Filter by record type (e.g. A, TXT, MX)") fs.Parse(args) client := miabClient() records, err := client.ListRecords(*recordType) if err != nil { fmt.Fprintf(os.Stderr, "miab: %v\n", err) os.Exit(1) } if *recordType != "" { fmt.Printf("Custom %s records:\n", *recordType) } else { fmt.Println("Custom DNS records:") } for _, r := range records { fmt.Printf(" - %s (%s): %s\n", r.Name, r.Type, r.Value) } } func runSet(args []string) { fs := flag.NewFlagSet("set", flag.ExitOnError) recordType := fs.String("type", "A", "Record type (e.g. A, TXT)") fs.Parse(args) if fs.NArg() < 2 { fmt.Fprintln(os.Stderr, "miab set: usage: set [--type TYPE] ") os.Exit(1) } name, value := fs.Arg(0), fs.Arg(1) client := miabClient() if err := client.SetRecord(name, *recordType, value); err != nil { fmt.Fprintf(os.Stderr, "miab: %v\n", err) os.Exit(1) } } func runDelete(args []string) { fs := flag.NewFlagSet("delete", flag.ExitOnError) recordType := fs.String("type", "A", "Record type (e.g. A, TXT)") fs.Parse(args) if fs.NArg() < 1 { fmt.Fprintln(os.Stderr, "miab delete: usage: delete [--type TYPE] [value]") os.Exit(1) } name := fs.Arg(0) value := fs.Arg(1) client := miabClient() if err := client.DeleteRecord(name, *recordType, value); err != nil { fmt.Fprintf(os.Stderr, "miab: %v\n", err) os.Exit(1) } } func runAdd(args []string) { fs := flag.NewFlagSet("add", flag.ExitOnError) recordType := fs.String("type", "A", "Record type (e.g. A, TXT)") fs.Parse(args) if fs.NArg() < 2 { fmt.Fprintln(os.Stderr, "miab add: usage: add [--type TYPE] ") os.Exit(1) } name, value := fs.Arg(0), fs.Arg(1) client := miabClient() if err := client.AddRecord(name, *recordType, value); err != nil { fmt.Fprintf(os.Stderr, "miab: %v\n", err) os.Exit(1) } }