package mail import ( "bufio" "bytes" "encoding/json" "fmt" "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("/usr/sbin/postqueue", "-j") var out bytes.Buffer var stderr bytes.Buffer cmd.Stdout = &out cmd.Stderr = &stderr err := cmd.Run() if err != nil { return nil, fmt.Errorf("/usr/sbin/postqueue -j: %v (stderr: %s)", err, stderr.String()) } 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("/usr/sbin/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("/usr/sbin/postsuper", "-d", id) return cmd.Run() } func GetQueueCount() (int, error) { cmd := exec.Command("/usr/sbin/postqueue", "-j") 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 }