2024-07-24 17:36:01 +02:00
|
|
|
package mailcow
|
|
|
|
|
|
|
|
import (
|
2024-07-26 10:57:24 +02:00
|
|
|
"bytes"
|
2024-07-24 17:36:01 +02:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log/slog"
|
|
|
|
"net/http"
|
2024-07-26 12:16:59 +02:00
|
|
|
"os"
|
2024-07-24 17:36:01 +02:00
|
|
|
"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"`
|
2024-07-26 10:57:24 +02:00
|
|
|
IsCatchAll int `json:"is_catch_all"`
|
2024-07-24 17:36:01 +02:00
|
|
|
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
|
2024-07-26 10:57:24 +02:00
|
|
|
a.SogoVisible = 0
|
2024-07-24 17:36:01 +02:00
|
|
|
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
2024-07-25 21:45:29 +02:00
|
|
|
func LoadAliases(cfg configuration.Config) ([]MailcowAlias, []string, error) {
|
|
|
|
var aliases []MailcowAlias
|
|
|
|
var aliasSlice []string
|
2024-07-24 17:36:01 +02:00
|
|
|
|
|
|
|
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 {
|
2024-07-25 21:45:29 +02:00
|
|
|
return []MailcowAlias{}, []string{}, fmt.Errorf("failed to create alias http request: %w", err)
|
2024-07-24 17:36:01 +02:00
|
|
|
}
|
|
|
|
req.Header.Add("accept", "application/json")
|
|
|
|
req.Header.Add("X-API-Key", cfg.ApiKey)
|
|
|
|
|
|
|
|
res, err := client.Do(req)
|
|
|
|
if err != nil {
|
2024-07-25 21:45:29 +02:00
|
|
|
return []MailcowAlias{}, []string{}, fmt.Errorf("failed to request aliases from server: %w", err)
|
2024-07-24 17:36:01 +02:00
|
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
|
|
|
|
slog.Debug("alias response received", "status", res.Status, "status-code", res.StatusCode)
|
|
|
|
|
2024-07-26 12:16:59 +02:00
|
|
|
if res.StatusCode != 200 {
|
|
|
|
slog.Error("API request unsuccessful", "status", res.Status, "status-code", res.StatusCode)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2024-07-24 17:36:01 +02:00
|
|
|
body, err := io.ReadAll(res.Body)
|
|
|
|
if err != nil {
|
2024-07-25 21:45:29 +02:00
|
|
|
return []MailcowAlias{}, []string{}, fmt.Errorf("failed to read alias request body: %w", err)
|
2024-07-24 17:36:01 +02:00
|
|
|
}
|
|
|
|
|
2024-07-25 21:45:29 +02:00
|
|
|
err = json.Unmarshal(body, &aliases)
|
2024-07-24 17:36:01 +02:00
|
|
|
if err != nil {
|
2024-07-25 21:45:29 +02:00
|
|
|
return []MailcowAlias{}, []string{}, fmt.Errorf("failed to unmarshal alias request body: %w", err)
|
2024-07-24 17:36:01 +02:00
|
|
|
}
|
|
|
|
|
2024-07-25 21:45:29 +02:00
|
|
|
for _, alias := range aliases {
|
|
|
|
aliasSlice = append(aliasSlice, alias.Address)
|
|
|
|
}
|
|
|
|
|
|
|
|
return aliases, aliasSlice, nil
|
2024-07-24 17:36:01 +02:00
|
|
|
}
|
2024-07-26 10:57:24 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|