Implement printing mailqueue in table, restructuring
This commit is contained in:
parent
d39fb736dc
commit
2a9ae87b2f
36
main.go
36
main.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"text/tabwriter"
|
||||||
)
|
)
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -41,6 +42,21 @@ func interactiveShell() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showQueue() {
|
func showQueue() {
|
||||||
|
entries, err := fetchQueueEntries()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Could not fetch queue entries: %s\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
pagerReader, pagerWriter := io.Pipe()
|
||||||
|
pagerDone := make(chan bool)
|
||||||
|
go launchPager(pagerReader, pagerDone)
|
||||||
|
printQueueEntries(entries, pagerWriter)
|
||||||
|
pagerWriter.Close()
|
||||||
|
// Wait for pager to be closed before continuing the main program
|
||||||
|
<-pagerDone
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchQueueEntries() ([]parser.QEntry, error) {
|
||||||
var entries []parser.QEntry
|
var entries []parser.QEntry
|
||||||
var err error
|
var err error
|
||||||
if settings["mailqCommandArgs"] == "" {
|
if settings["mailqCommandArgs"] == "" {
|
||||||
|
@ -48,24 +64,22 @@ func showQueue() {
|
||||||
} else {
|
} else {
|
||||||
entries, err = readFromCmd(exec.Command(settings["mailqCommand"], settings["mailqCommandArgs"]))
|
entries, err = readFromCmd(exec.Command(settings["mailqCommand"], settings["mailqCommandArgs"]))
|
||||||
}
|
}
|
||||||
if err != nil {
|
return entries, err
|
||||||
fmt.Printf("Error reading: %s\n", err.Error())
|
}
|
||||||
os.Exit(1)
|
|
||||||
}
|
func printQueueEntries(entries []parser.QEntry, writer io.Writer) {
|
||||||
reader, writer := io.Pipe()
|
tabWriter := tabwriter.NewWriter(writer, 0, 2, 1, ' ', tabwriter.TabIndent)
|
||||||
pagerDone := make(chan bool)
|
fmt.Fprintf(tabWriter, "%s\t%s\t%s\t%s\t%s\t%s\n", "Date", "Id", "Size", "Sender", "#", "First Recipient")
|
||||||
go launchPager(reader, pagerDone)
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
_, writeError := fmt.Fprintf(writer, "%s\n", entry.String())
|
_, writeError := fmt.Fprintf(tabWriter, "%s\t%s\t%d\t%s\t{%d}\t%s\n", entry.Date, entry.Id, entry.Size, entry.Sender, len(entry.Recipients), entry.Recipients[0])
|
||||||
if writeError != nil {
|
if writeError != nil {
|
||||||
// A writeError is expected once the reader was closed
|
// A writeError is expected once the reader was closed
|
||||||
// This happens when the pager application got terminated
|
// This happens when the pager application got terminated
|
||||||
|
fmt.Printf("Error writing!: %s\n", writeError.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.Close()
|
tabWriter.Flush()
|
||||||
// Wait for pager to be closed before continuing the main program
|
|
||||||
<-pagerDone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func launchPager(reader *io.PipeReader, pagerDone chan<- bool) {
|
func launchPager(reader *io.PipeReader, pagerDone chan<- bool) {
|
||||||
|
|
|
@ -12,35 +12,35 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type QEntry struct {
|
type QEntry struct {
|
||||||
id string
|
Id string
|
||||||
status string
|
Status string
|
||||||
date time.Time
|
Date time.Time
|
||||||
size int
|
Size int
|
||||||
sender string
|
Sender string
|
||||||
recipients []string
|
Recipients []string
|
||||||
reason string
|
Reason string
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortableDateFormat = "2006-01-02 15:04:05"
|
const sortableDateFormat = "2006-01-02 15:04:05"
|
||||||
|
|
||||||
func (m QEntry) ShortString() string {
|
func (m QEntry) ShortString() string {
|
||||||
return fmt.Sprintf("[%s] %s <%s> -> %d recipients (%d bytes)", m.date.Format(sortableDateFormat), m.id, m.sender, len(m.recipients), m.size)
|
return fmt.Sprintf("[%s] %s <%s> -> %d recipients (%d bytes)", m.Date.Format(sortableDateFormat), m.Id, m.Sender, len(m.Recipients), m.Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m QEntry) String() string {
|
func (m QEntry) String() string {
|
||||||
var recipientSuffix string
|
var recipientSuffix string
|
||||||
if len(m.recipients) > 1 {
|
if len(m.Recipients) > 1 {
|
||||||
recipientSuffix = ",..."
|
recipientSuffix = ",..."
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("[%s] %s <%s> -> {%d}<%s>%s (%s, %d bytes)", m.date.Format(sortableDateFormat), m.id, m.sender, len(m.recipients), m.recipients[0], recipientSuffix, m.status, m.size)
|
return fmt.Sprintf("[%s] %s <%s> -> {%d}<%s>%s (%s, %d bytes)", m.Date.Format(sortableDateFormat), m.Id, m.Sender, len(m.Recipients), m.Recipients[0], recipientSuffix, m.Status, m.Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m QEntry) DetailedString() string {
|
func (m QEntry) DetailedString() string {
|
||||||
var reasonStr string
|
var reasonStr string
|
||||||
if m.reason == "" {
|
if m.Reason == "" {
|
||||||
reasonStr = "-/-"
|
reasonStr = "-/-"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Id: %s\nDate: %s\nStatus: %s\nReason: %s\nSize: %d\nSender: %s\nRecipients: %s", m.id, m.date.Format(sortableDateFormat), m.status, reasonStr, m.size, m.sender, strings.Join(m.recipients, ", "))
|
return fmt.Sprintf("Id: %s\nDate: %s\nStatus: %s\nReason: %s\nSize: %d\nSender: %s\nRecipients: %s", m.Id, m.Date.Format(sortableDateFormat), m.Status, reasonStr, m.Size, m.Sender, strings.Join(m.Recipients, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseMailQ(dataSource io.Reader) ([]QEntry, error) {
|
func ParseMailQ(dataSource io.Reader) ([]QEntry, error) {
|
||||||
|
@ -71,26 +71,26 @@ func ParseMailQ(dataSource io.Reader) ([]QEntry, error) {
|
||||||
// Handle line starting next mail in queue
|
// Handle line starting next mail in queue
|
||||||
messageId := fields[0]
|
messageId := fields[0]
|
||||||
if strings.HasSuffix(messageId, "*") {
|
if strings.HasSuffix(messageId, "*") {
|
||||||
currentMail.status = "active"
|
currentMail.Status = "active"
|
||||||
} else if strings.HasSuffix(messageId, "!") {
|
} else if strings.HasSuffix(messageId, "!") {
|
||||||
currentMail.status = "hold"
|
currentMail.Status = "hold"
|
||||||
} else {
|
} else {
|
||||||
currentMail.status = "deferred"
|
currentMail.Status = "deferred"
|
||||||
}
|
}
|
||||||
dateString := strconv.Itoa(time.Now().Year()) + " " + strings.Join(fields[2:6], " ")
|
dateString := strconv.Itoa(time.Now().Year()) + " " + strings.Join(fields[2:6], " ")
|
||||||
mailDate, _ := time.Parse(dateFormat, dateString)
|
mailDate, _ := time.Parse(dateFormat, dateString)
|
||||||
currentMail.id = strings.TrimRight(messageId, "*!")
|
currentMail.Id = strings.TrimRight(messageId, "*!")
|
||||||
currentMail.size, _ = strconv.Atoi(fields[1])
|
currentMail.Size, _ = strconv.Atoi(fields[1])
|
||||||
currentMail.date = mailDate
|
currentMail.Date = mailDate
|
||||||
currentMail.sender = fields[6]
|
currentMail.Sender = fields[6]
|
||||||
continue
|
continue
|
||||||
} else if strings.HasPrefix(line, "(") && strings.HasSuffix(line, ")") {
|
} else if strings.HasPrefix(line, "(") && strings.HasSuffix(line, ")") {
|
||||||
// Handle reason for deferred status (if deferred at all, may be missing)
|
// Handle reason for deferred status (if deferred at all, may be missing)
|
||||||
currentMail.reason = strings.Trim(strings.TrimSpace(line), "()")
|
currentMail.Reason = strings.Trim(strings.TrimSpace(line), "()")
|
||||||
continue
|
continue
|
||||||
} else if len(fields) == 1 {
|
} else if len(fields) == 1 {
|
||||||
// Handle line with one of the mail recipients
|
// Handle line with one of the mail recipients
|
||||||
currentMail.recipients = append(currentMail.recipients, fields[0])
|
currentMail.Recipients = append(currentMail.Recipients, fields[0])
|
||||||
continue
|
continue
|
||||||
} else if len(fields) == 0 {
|
} else if len(fields) == 0 {
|
||||||
// If the next line is empty, make sure to push current mail to list
|
// If the next line is empty, make sure to push current mail to list
|
||||||
|
|
Loading…
Reference in New Issue