package mailcow import ( "bytes" "encoding/json" "fmt" "io" "log/slog" "net/http" "os" "time" "code.lila.network/adoralaura/mailcow-admin-aliases/internal/configuration" ) type MailcowAlias struct { ID int `json:"id"` Domain string `json:"domain"` PublicComment string `json:"public_comment"` PrivateComment string `json:"private_comment"` Goto string `json:"goto"` Address string `json:"address"` IsCatchAll int `json:"is_catch_all"` Active int `json:"active"` ActiveInt int `json:"active_int"` SogoVisible int `json:"sogo_visible"` SogoVisibleInt int `json:"sogo_visible_int"` } func NewAlias(alias string, destination string) MailcowAlias { var a MailcowAlias a.Active = 1 a.PublicComment = "automatically generated by the mail server admin" a.PrivateComment = "automatically generated by the mail server admin" a.Address = alias a.Goto = destination a.SogoVisible = 0 return a } func LoadAliases(cfg configuration.Config) ([]MailcowAlias, []string, error) { var aliases []MailcowAlias var aliasSlice []string url := cfg.ApiEndpoint + configuration.AllAliasesApiEndpoint method := "GET" client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest(method, url, nil) slog.Debug("alias request", "method", method, "url", url) if err != nil { return []MailcowAlias{}, []string{}, fmt.Errorf("failed to create alias http request: %w", err) } req.Header.Add("accept", "application/json") req.Header.Add("X-API-Key", cfg.ApiKey) res, err := client.Do(req) if err != nil { return []MailcowAlias{}, []string{}, fmt.Errorf("failed to request aliases from server: %w", err) } defer res.Body.Close() slog.Debug("alias response received", "status", res.Status, "status-code", res.StatusCode) if res.StatusCode != 200 { slog.Error("API request unsuccessful", "status", res.Status, "status-code", res.StatusCode) os.Exit(1) } body, err := io.ReadAll(res.Body) if err != nil { return []MailcowAlias{}, []string{}, fmt.Errorf("failed to read alias request body: %w", err) } err = json.Unmarshal(body, &aliases) if err != nil { return []MailcowAlias{}, []string{}, fmt.Errorf("failed to unmarshal alias request body: %w", err) } for _, alias := range aliases { aliasSlice = append(aliasSlice, alias.Address) } return aliases, aliasSlice, nil } func (a MailcowAlias) Create(cfg configuration.Config) error { url := cfg.ApiEndpoint + configuration.AliasAddApiEndpoint method := "POST" payload, err := json.Marshal(a) if err != nil { return fmt.Errorf("failed to marshal api body: %w", err) } client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest(method, url, bytes.NewReader(payload)) if err != nil { return fmt.Errorf("failed to create new POST request: %w", err) } slog.Debug("alias create request", "method", method, "url", url) req.Header.Add("accept", "application/json") req.Header.Add("Content-Type", "application/json") req.Header.Add("X-API-Key", cfg.ApiKey) res, err := client.Do(req) if err != nil { return fmt.Errorf("failed to POST new alias to server: %w", err) } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { return fmt.Errorf("failed to read response body: %w", err) } err = checkApiResponseOK(body) if err != nil { return fmt.Errorf("api returned an error: %w", err) } return nil }