update app logics
This commit is contained in:
parent
e8b4faec3b
commit
e625620b40
4 changed files with 97 additions and 6 deletions
|
@ -54,20 +54,39 @@ func main() {
|
||||||
slog.Error("failed to get aliases", "error", err.Error())
|
slog.Error("failed to get aliases", "error", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
slog.Info(fmt.Sprintf("Found %v domains, %v aliases.", len(domains), len(existingAliases)))
|
slog.Info(fmt.Sprintf("Found %v existing domains, %v existing aliases", len(domains), len(existingAliases)))
|
||||||
|
|
||||||
for _, domain := range domains {
|
for _, domain := range domains {
|
||||||
for _, prefix := range cfg.MailPrefixes {
|
for _, prefix := range cfg.MailPrefixes {
|
||||||
address := prefix + "@" + domain.DomainName
|
address := prefix + "@" + domain.DomainName
|
||||||
if address != cfg.AdminEmail && !misc.StringIsInStringSlice(existingAliasesSlice, address) {
|
if address != cfg.AdminEmail && !misc.StringIsInStringSlice(existingAliasesSlice, address) {
|
||||||
slog.Info(fmt.Sprintf("%v: Adding to wanted alias list", address))
|
slog.Debug(fmt.Sprintf("%v: Adding to wanted alias list", address))
|
||||||
wantedAliases = append(wantedAliases, address)
|
wantedAliases = append(wantedAliases, address)
|
||||||
} else {
|
} else {
|
||||||
slog.Info(fmt.Sprintf("%v: Ignoring alias", address))
|
slog.Debug(fmt.Sprintf("%v: Ignoring alias", address))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create aliases
|
if len(wantedAliases) == 0 {
|
||||||
|
slog.Info("Found no missing aliases. Nothing to do. Bye")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Info(fmt.Sprintf("Found %v missing aliases. Will try to create them:", len(wantedAliases)))
|
||||||
|
|
||||||
|
for _, alias := range wantedAliases {
|
||||||
|
if configuration.DryRun {
|
||||||
|
slog.Info(fmt.Sprintf("[DRYRUN] Creating alias %v", alias))
|
||||||
|
} else {
|
||||||
|
mailcowAlias := mailcow.NewAlias(alias, cfg.AdminEmail)
|
||||||
|
err = mailcowAlias.Create(cfg)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to create alias", "alias", alias, "error", err.Error())
|
||||||
|
} else {
|
||||||
|
slog.Info(fmt.Sprintf("Created alias %v", alias))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ type Config struct {
|
||||||
MailPrefixes []string `yaml:"mail_prefixes"`
|
MailPrefixes []string `yaml:"mail_prefixes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) LoadFromDisk() error {
|
func (c *Config) LoadFromDisk() error {
|
||||||
if ConfigFile == "" {
|
if ConfigFile == "" {
|
||||||
slog.Debug("no config file found, looking in working dir")
|
slog.Debug("no config file found, looking in working dir")
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package mailcow
|
package mailcow
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -18,7 +19,7 @@ type MailcowAlias struct {
|
||||||
PrivateComment string `json:"private_comment"`
|
PrivateComment string `json:"private_comment"`
|
||||||
Goto string `json:"goto"`
|
Goto string `json:"goto"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
IsCatchAll int `json:"is_catch_all"` // skip if 1
|
IsCatchAll int `json:"is_catch_all"`
|
||||||
Active int `json:"active"`
|
Active int `json:"active"`
|
||||||
ActiveInt int `json:"active_int"`
|
ActiveInt int `json:"active_int"`
|
||||||
SogoVisible int `json:"sogo_visible"`
|
SogoVisible int `json:"sogo_visible"`
|
||||||
|
@ -32,6 +33,7 @@ func NewAlias(alias string, destination string) MailcowAlias {
|
||||||
a.PrivateComment = "automatically generated by the mail server admin"
|
a.PrivateComment = "automatically generated by the mail server admin"
|
||||||
a.Address = alias
|
a.Address = alias
|
||||||
a.Goto = destination
|
a.Goto = destination
|
||||||
|
a.SogoVisible = 0
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -78,3 +80,43 @@ func LoadAliases(cfg configuration.Config) ([]MailcowAlias, []string, error) {
|
||||||
|
|
||||||
return aliases, aliasSlice, nil
|
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
|
||||||
|
}
|
||||||
|
|
30
internal/mailcow/api.go
Normal file
30
internal/mailcow/api.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package mailcow
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MailcowApiResponse struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Msg []string `json:"msg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkApiResponseOK checks if we got a positive response from the Mailcow API.
|
||||||
|
//
|
||||||
|
// Returns an error detailing why the request failed.
|
||||||
|
func checkApiResponseOK(body []byte) error {
|
||||||
|
var response []MailcowApiResponse
|
||||||
|
|
||||||
|
err := json.Unmarshal(body, &response)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response[0].Type != "success" {
|
||||||
|
return fmt.Errorf("%v", strings.Join(response[0].Msg, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue