This commit is contained in:
Christoph Haas 2026-03-21 22:41:23 +01:00
commit f4be03ceba
1826 changed files with 830924 additions and 0 deletions

View file

@ -0,0 +1,88 @@
package mail
import (
"bufio"
"bytes"
"context"
"os/exec"
"regexp"
"strings"
"time"
)
type LogEntry struct {
Timestamp string `json:"timestamp"`
Priority string `json:"priority"`
Message string `json:"message"`
}
func GetLogs(hours int, filter string) ([]LogEntry, error) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
args := []string{
"-u", "postfix",
"--since", formatDuration(hours),
"--no-pager",
"-o", "short=false",
}
cmd := exec.CommandContext(ctx, "journalctl", args...)
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return nil, err
}
var entries []LogEntry
scanner := bufio.NewScanner(&out)
priorityRegex := regexp.MustCompile(`\[([^\]]+)\]`)
for scanner.Scan() {
line := scanner.Text()
if filter != "" && !strings.Contains(strings.ToLower(line), strings.ToLower(filter)) {
continue
}
parts := strings.SplitN(line, " ", 4)
if len(parts) < 4 {
continue
}
timestamp := parts[0] + " " + parts[1]
matches := priorityRegex.FindStringSubmatch(parts[2])
priority := "info"
if len(matches) > 1 {
priority = matches[1]
} else if strings.Contains(parts[2], "err") {
priority = "err"
} else if strings.Contains(parts[2], "warning") || strings.Contains(parts[2], "warn") {
priority = "warning"
}
message := parts[3]
if filter != "" && !strings.Contains(strings.ToLower(message), strings.ToLower(filter)) {
continue
}
entries = append(entries, LogEntry{
Timestamp: timestamp,
Priority: priority,
Message: message,
})
}
if entries == nil {
entries = []LogEntry{}
}
return entries, nil
}
func formatDuration(hours int) string {
return time.Now().Add(-time.Duration(hours) * time.Hour).Format("15:04:05 2006-01-02")
}

View file

@ -0,0 +1,123 @@
package mail
import (
"bufio"
"bytes"
"encoding/json"
"os/exec"
"regexp"
"strconv"
"strings"
)
type QueueEntry struct {
ID string `json:"id"`
Sender string `json:"sender"`
Recipients []string `json:"recipients"`
Size int `json:"size"`
Time string `json:"time"`
Reason string `json:"reason"`
}
var queueLineRegex = regexp.MustCompile(`^([A-Fa-f0-9]+)\s+(\d+)\s+(\w+)\s+([A-Za-z]+\s+\d+\s+[\d:]+)\s+([^\s]+)\s+(.+)$`)
func GetQueue() ([]QueueEntry, error) {
cmd := exec.Command("postqueue", "-p", "-j")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return nil, err
}
var entries []QueueEntry
scanner := bufio.NewScanner(&out)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || !strings.HasPrefix(line, "{") {
continue
}
var entry struct {
QueueID string `json:"queueid"`
Sender string `json:"sender"`
Recipients []struct {
Address string `json:"address"`
} `json:"recipients"`
Size int64 `json:"size"`
Arrival string `json:"arrival_timestamp"`
Delay string `json:"delay_reason"`
}
if err := json.Unmarshal([]byte(line), &entry); err != nil {
continue
}
recipients := make([]string, len(entry.Recipients))
for i, r := range entry.Recipients {
recipients[i] = r.Address
}
entries = append(entries, QueueEntry{
ID: entry.QueueID,
Sender: entry.Sender,
Recipients: recipients,
Size: int(entry.Size),
Time: entry.Arrival,
Reason: entry.Delay,
})
}
if entries == nil {
entries = []QueueEntry{}
}
return entries, nil
}
func RequeueMail(id string) error {
cmd := exec.Command("postqueue", "-f", "-v")
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &out
if err := cmd.Run(); err != nil {
return err
}
return nil
}
func DeleteFromQueue(id string) error {
cmd := exec.Command("postsuper", "-d", id)
return cmd.Run()
}
func GetQueueCount() (int, error) {
cmd := exec.Command("postqueue", "-p")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return 0, err
}
count := 0
scanner := bufio.NewScanner(&out)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, " mail queue") {
parts := strings.Fields(line)
for i, p := range parts {
if n, err := strconv.Atoi(p); err == nil && n > 0 {
count = n
if i > 0 && parts[i-1] == "in" {
return n, nil
}
}
}
}
}
return count, nil
}