From e2854cac2f1923714b98fb6820742c2a0e4ec02a Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Tue, 26 Dec 2017 12:33:33 -0800 Subject: [PATCH] Simple mbox parser. --- cmd/mbox2maildir/mbox2maildir.go | 65 +++++++++++++++++++++++++++ cmd/mbox2maildir/mbox2maildir_test.go | 51 +++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 cmd/mbox2maildir/mbox2maildir.go create mode 100644 cmd/mbox2maildir/mbox2maildir_test.go diff --git a/cmd/mbox2maildir/mbox2maildir.go b/cmd/mbox2maildir/mbox2maildir.go new file mode 100644 index 0000000..ab558ba --- /dev/null +++ b/cmd/mbox2maildir/mbox2maildir.go @@ -0,0 +1,65 @@ +package main + +import ( + "bufio" + "bytes" + "flag" + "io" + "os" + + "github.com/golang/glog" +) + +func writeMailderFile(b []byte) error { return nil } + +func parse(r io.Reader, writeMessage func(b []byte) error) error { + from := []byte("From ") + scanner := bufio.NewScanner(r) + buf := new(bytes.Buffer) + for scanner.Scan() { + b := scanner.Bytes() + if bytes.HasPrefix(b, from) { + // New message + if buf.Len() > 0 { + msg := buf.Bytes() + // Trim empty line from end of mbox message + msg = msg[:len(msg)-1] + if err := writeMessage(msg); err != nil { + return err + } + } + buf.Reset() + } + buf.Write(b) + buf.Write([]byte("\n")) + } + if buf.Len() > 0 { + if err := writeMessage(buf.Bytes()); err != nil { + return err + } + } + return scanner.Err() +} + +func parseFile(p string) error { + r, err := os.Open(p) + if err != nil { + return err + } + defer r.Close() + + if err := parse(r, writeMailderFile); err != nil { + return err + } + + return nil +} +func main() { + flag.Parse() + defer glog.Flush() + for _, path := range flag.Args() { + if err := parseFile(path); err != nil { + glog.Errorf("Failed to parse %q: %v", err) + } + } +} diff --git a/cmd/mbox2maildir/mbox2maildir_test.go b/cmd/mbox2maildir/mbox2maildir_test.go new file mode 100644 index 0000000..088a059 --- /dev/null +++ b/cmd/mbox2maildir/mbox2maildir_test.go @@ -0,0 +1,51 @@ +package main + +import ( + "bytes" + "strings" + "testing" +) + +func TestParse(t *testing.T) { + const input = `From user1 + +Body 1 + +From user2 + +Body 2 with From in it. + +From user3 + +Body 3 +` + wants := []string{ + `From user1 + +Body 1 +`, + `From user2 + +Body 2 with From in it. +`, + `From user3 + +Body 3 +`, + } + msgN := 0 + testWriteMessage := func(got []byte) error { + want := wants[msgN] + if !bytes.Equal([]byte(want), got) { + t.Errorf("msg[%d] = %q, want %q", msgN, got, want) + } + msgN++ + return nil + } + if err := parse(strings.NewReader(input), testWriteMessage); err != nil { + t.Errorf("parse() failed: %v", err) + } + if msgN != len(wants) { + t.Errorf("Parsed %d messages, expected %d", msgN, len(wants)) + } +}