reorganize code

move all code to / and have only a main package. don't bother making up packages, we never gonna use them anywhere else.
22 files changed, 165 insertions(+), 293 deletions(-)

A => cmd.go
R cmd/mbs/main.go => 
R cmd/mbs/mbs => 
R cmd/nedmb/main.go => 
M command.go
A => command_test.go
M config.go
M decode.go
M edit.go
M edit_test.go
M list.go
M list_test.go
A => ls.go
A => mailbox_test.go
M cmd/mb/main.go => main.go
M mh/mh.go => mh.go
M parse.go
M reply_test.go
M send.go
M sequence.go
M sequence_test.go
M mh/setup_template.go => setup_template.go
A => cmd.go +13 -0
@@ 0,0 1,13 @@ 
+package main
+
+import (
+	"os"
+)
+
+func runList(mbox *Mailbox, args []string) error {
+	folder := mbox.DefaultFolder
+	if len(os.Args) > 2 {
+		folder = os.Args[2]
+	}
+	return List(mbox, os.Stdout, folder, NewAlwaysMatcher())
+}

          
R cmd/mbs/main.go =>  +0 -44
@@ 1,44 0,0 @@ 
-package main
-
-import (
-	"fmt"
-	"log"
-	"net"
-)
-
-func echoServer(c net.Conn) {
-	for {
-		buf := make([]byte, 512)
-		nr, err := c.Read(buf)
-		if err != nil {
-			return
-		}
-
-		data := buf[0:nr]
-		println("Server got:", string(data))
-		_, err = fmt.Fprintf(c, "stdout: %s\n", string(data))
-		if err != nil {
-			log.Fatal("Write: ", err)
-		}
-		_, err = fmt.Fprintln(c, "end:")
-		if err != nil {
-			log.Fatal("Write: ", err)
-		}
-	}
-}
-
-func main() {
-	l, err := net.Listen("unix", "/tmp/mbs.sock")
-	if err != nil {
-		log.Fatal("listen error:", err)
-	}
-
-	for {
-		fd, err := l.Accept()
-		if err != nil {
-			log.Fatal("accept error:", err)
-		}
-
-		go echoServer(fd)
-	}
-}

          
R cmd/mbs/mbs =>  +0 -0

        
R cmd/nedmb/main.go =>  +0 -160
@@ 1,160 0,0 @@ 
-package main
-
-import (
-	"bufio"
-	"fmt"
-	"net/mail"
-	"os"
-	"path"
-	"strconv"
-
-	mb "bitbucket.org/telesto/mailbox"
-)
-
-const arch = "archive"
-
-/*  attached msg problem solution:
--s mailfile  Read a single message file mailfile, as pro-
-    duced by fs, and treat it as an entire mailbox.
-    This is provided for use in plumbing rules; see
-    faces(1). */
-func main() {
-
-	in := bufio.NewReader(os.Stdin)
-	var cur uint64
-	if len(os.Args) == 1 {
-		fmt.Fprintln(os.Stderr, "missing mailbox")
-		os.Exit(2)
-	}
-
-	// todo: give this command a path, not a folder -
-	// so we can do things like "nedmb .", to work on the current path?
-	/*		The -f command line option speci-
-	fies an alternate mailbox.  Unrooted path names are inter-
-	preted relative to /mail/box/username.  If the mailfile
-	argument is omitted, the name defaults to stored. */
-	mbox := mb.NewMhMailbox()
-	folder := os.Args[1]
-	if err := mbox.Lock(folder); err != nil {
-		fmt.Fprintln(os.Stderr, err)
-		os.Exit(1)
-	}
-	// todo: no need to exit in case of an error, first print all msgs
-	mails, err := mbox.ReadFolder(folder)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err)
-		os.Exit(1)
-	}
-	mb.List(mails, os.Stdout, folder)
-	// todo: mkdir archive
-	for {
-		fmt.Printf("%s/%d: ", folder, cur)
-		cmd, err := in.ReadString('\n')
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err)
-			os.Exit(1)
-		}
-		cmd = cmd[:len(cmd)-1]
-		hits := parseCmd(cmd, mails, cur)
-		if n, err := strconv.Atoi(cmd); err == nil {
-			cur = uint64(n)
-			// when choosing a msg, print it
-			cmd = "p"
-		}
-		switch cmd {
-		case "q":
-			if err := mbox.Unlock(folder); err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				os.Exit(1)
-			}
-			return
-		case "a":
-			// archive a msg, move it to archive/<from address>
-			msgId := fmt.Sprint(cur)
-			f, err := mbox.Open(path.Join(folder, msgId))
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			msg, err := mail.ReadMessage(f)
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			from, err := mail.ParseAddressList(msg.Header.Get("From"))
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			if len(from) == 0 {
-				fmt.Fprintf(os.Stderr, "%s: no from address", from)
-			}
-			arch := path.Join("archive", path.Base(from[0].Address))
-			// todo: ignore IsExist, else fail
-			err = mbox.MkFolder(arch)
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-			}
-			// todo: make the filename safe?
-			err = mbox.Move(folder, arch, msgId)
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-		case "d":
-			for _, msg := range mails {
-				if msg.Id == cur {
-					msg.Deleted = true
-				}
-			}
-		case "p":
-			// print msg
-			f, err := mbox.Open(path.Join(folder, fmt.Sprint(cur)))
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			msg, err := mail.ReadMessage(f)
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			mb.View(os.Stdout, msg)
-		case "m":
-			// print mime parts of current msg
-			f, err := mbox.Open(path.Join(folder, fmt.Sprint(cur)))
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			msg, err := mail.ReadMessage(f)
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-			parts := make(chan string)
-			go func() {
-				err = mb.Parts(parts, msg)
-				close(parts)
-			}()
-			for part := range parts {
-				fmt.Println(part)
-			}
-			if err1 := f.Close(); err == nil {
-				err = err1
-			}
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err)
-				continue
-			}
-		case "l":
-			// list msgs
-			mb.List(mails, os.Stdout, mbox.FolderType(folder))
-		default:
-			fmt.Printf("%s: unknown command\n", cmd)
-		}
-	}
-}
-
-func parseCmd(cmd string, all []*mb.Message, cur *mb.Message) {
-}

          
M command.go +5 -7
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"bytes"

          
@@ 13,13 13,11 @@ import (
 	"strconv"
 	"strings"
 
-	"bitbucket.org/telesto/mailbox/mh"
-
 	"golang.org/x/text/transform"
 )
 
 // its not an error if no match is found.
-func walk(mbox *mh.Mailbox, folder string, seq *Sequence, proc func(int64) error) error {
+func walk(mbox *Mailbox, folder string, seq *Sequence, proc func(int64) error) error {
 	// we need a sorted list, so the "Move" cmd will process the msgs
 	// in the correct time order
 

          
@@ 58,7 56,7 @@ func walk(mbox *mh.Mailbox, folder strin
 }
 
 // todo: provide a set of msgs/parts by prematching all msgs of a folder
-func Move(mbox *mh.Mailbox, srcFolder string, msgs *Sequence, dst string) error {
+func Move(mbox *Mailbox, srcFolder string, msgs *Sequence, dst string) error {
 	proc := func(id int64) error {
 		return mbox.Move(srcFolder, dst, id)
 	}

          
@@ 66,7 64,7 @@ func Move(mbox *mh.Mailbox, srcFolder st
 }
 
 // todo: provide a set of msgs/parts by prematching all msgs of a folder
-func Remove(mbox *mh.Mailbox, folder string, msgs *Sequence) error {
+func Remove(mbox *Mailbox, folder string, msgs *Sequence) error {
 	proc := func(id int64) error {
 		return mbox.Remove(folder, id)
 	}

          
@@ 117,7 115,7 @@ func Save(msg *mail.Message, number int)
 
 // todo: decode "name"
 // todo: provide a set of msgs/parts by prematching all msgs of a folder
-func Parts(mbox *mh.Mailbox, folder string, msgs *Sequence) ([]string, error) {
+func Parts(mbox *Mailbox, folder string, msgs *Sequence) ([]string, error) {
 	var parts []string
 	proc := func(id int64) error {
 		r, err := mbox.Open(folder, id)

          
A => command_test.go +20 -0
@@ 0,0 1,20 @@ 
+package main
+
+import (
+	"testing"
+)
+
+func TestParts(t *testing.T) {
+	f := failnow(t)
+	mbox := NewMailbox()
+	// todo: fix this
+	mbox.Maildir = "./testdata"
+	parts, err := Parts(NewMailbox(), "parts", NewAlwaysMatcher())
+	f(err)
+	if !assertEqual("#parts", len(parts), 2, t) {
+		return
+	}
+	assertEqual("part 1", parts[0], "parts/1:1 text/plain; charset=utf-8", t)
+	assertEqual("part 2", parts[1], "parts/1:2 image/jpeg; name=IMG_4993.JPG;", t)
+
+}

          
M config.go +1 -1
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 // The folder types for different outputs in list view.
 //

          
M decode.go +4 -2
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"io"

          
@@ 35,10 35,12 @@ func ReadMessage(r io.Reader) (*Message,
 	if err != nil {
 		return nil, err
 	}
-	return &Message{NewHeader(msg.Header), msg.Body}, nil
+	// bug: 0 is a place holder
+	return &Message{0, NewHeader(msg.Header), msg.Body}, nil
 }
 
 type Message struct {
+	Id     int64
 	Header Header
 	Body   io.Reader
 }

          
M edit.go +7 -9
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"bufio"

          
@@ 22,8 22,6 @@ import (
 	"time"
 
 	"golang.org/x/text/transform"
-
-	"bitbucket.org/telesto/mailbox/mh"
 )
 
 type quoteMessage struct {

          
@@ 56,28 54,28 @@ func (qm *quoteMessage) Transform(dst, s
 type formatMsg func(io.Writer, string, *mail.Message) error
 
 // todo:
-func Edit(mb *mh.Mailbox, msg *mail.Message) (string, error) {
+func Edit(mb *Mailbox, msg *mail.Message) (string, error) {
 	return edit(mb, msg, fmtEditMsg)
 }
 
-func Create(mb *mh.Mailbox) (string, error) {
+func Create(mb *Mailbox) (string, error) {
 	// todo: this is ugly
 	return edit(mb, &mail.Message{Header: make(map[string][]string)}, fmtNewMessage)
 }
 
-func Forward(mb *mh.Mailbox, msg *mail.Message) (string, error) {
+func Forward(mb *Mailbox, msg *mail.Message) (string, error) {
 	return edit(mb, msg, forwardMsg)
 }
 
 // todo: wouldnt make a reader or a filename make more sense here?
 // we have to rethink the whola api
-func Reply(mb *mh.Mailbox, msg *mail.Message) (string, error) {
+func Reply(mb *Mailbox, msg *mail.Message) (string, error) {
 	return edit(mb, msg, fmtReply)
 }
 
 // todo: in case of an error we need to inform the callee about the
 // tmp file that is still existing
-func edit(mbox *mh.Mailbox, msg *mail.Message, format formatMsg) (string, error) {
+func edit(mbox *Mailbox, msg *mail.Message, format formatMsg) (string, error) {
 	tmp, err := ioutil.TempFile("", "mailbox")
 	if err != nil {
 		return "", err

          
@@ 334,7 332,7 @@ func boundary(hdr textproto.MIMEHeader) 
 	return "", nil
 }
 
-func Attach(mbox *mh.Mailbox, dst io.Writer, src io.Reader, filename string) error {
+func Attach(mbox *Mailbox, dst io.Writer, src io.Reader, filename string) error {
 
 	att, err := os.Open(filename)
 	if err != nil {

          
M edit_test.go +1 -1
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import "testing"
 

          
M list.go +3 -5
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"fmt"

          
@@ 6,12 6,10 @@ import (
 	"net/mail"
 	"strings"
 	"time"
-
-	"bitbucket.org/telesto/mailbox/mh"
 )
 
 // todo: delim as param
-func List(mbox *mh.Mailbox, out io.Writer, folder string, pick *Sequence) error {
+func List(mbox *Mailbox, out io.Writer, folder string, pick *Sequence) error {
 	fType, ok := mbox.Folders[folder]
 	if !ok {
 		fType = defaultFolderType

          
@@ 29,7 27,7 @@ func List(mbox *mh.Mailbox, out io.Write
 			if !pick.IsMatch(msg.Id) {
 				continue
 			}
-			header := NewHeader(msg.Header)
+			header := msg.Header
 			// header := msg.Header
 			// ignore error, we can't do anything about it
 			date, _ := header.Date()

          
M list_test.go +2 -4
@@ 1,10 1,8 @@ 
-package mailbox
+package main
 
 import (
 	"os"
 	"testing"
-
-	"bitbucket.org/telesto/mailbox/mh"
 )
 
 func BenchmarkList(b *testing.B) {

          
@@ 13,7 11,7 @@ func BenchmarkList(b *testing.B) {
 	if err != nil {
 		panic(err)
 	}
-	mbox := mh.NewMailbox()
+	mbox := NewMailbox()
 	msgs := NewAlwaysMatcher()
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {

          
A => ls.go +8 -0
@@ 0,0 1,8 @@ 
+package main
+
+var cmdList = &Command{
+	Name:      "list",
+	UsageLine: "list [folder]",
+	Short:     "list mails in folder",
+	Long: `List lists messages in a folder.
+	`}

          
A => mailbox_test.go +58 -0
@@ 0,0 1,58 @@ 
+package main
+
+import (
+	"fmt"
+	"testing"
+)
+
+func assertNotEqual(name string, got, want interface{}, t *testing.T) bool {
+	t.Helper()
+	if got == want {
+		failf(t)("%s: got %#v, wanted != %#v", name, got, want)
+		return false
+	}
+	return true
+}
+
+func assertEqual(name string, got, want interface{}, t *testing.T) bool {
+	t.Helper()
+	if got != want {
+		failf(t)("%s: got %#v, want %#v", name, got, want)
+		return false
+	}
+	return true
+}
+
+func fail(t testing.TB) func(error) bool {
+	return func(err error) bool {
+		t.Helper()
+		if err != nil {
+			t.Error(err)
+			return true
+		}
+		return false
+	}
+}
+
+func failf(t testing.TB) func(format string, a ...interface{}) {
+	return func(format string, a ...interface{}) {
+		t.Helper()
+		fail(t)(fmt.Errorf(format, a...))
+	}
+}
+
+func failnow(t testing.TB) func(error) {
+	return func(err error) {
+		t.Helper()
+		if fail(t)(err) {
+			t.FailNow()
+		}
+	}
+}
+
+func failnowf(t testing.TB) func(format string, a ...interface{}) {
+	return func(format string, a ...interface{}) {
+		t.Helper()
+		failnow(t)(fmt.Errorf(format, a...))
+	}
+}

          
M cmd/mb/main.go => main.go +29 -32
@@ 8,16 8,13 @@ import (
 	"os"
 	"path"
 	"strconv"
-
-	mb "bitbucket.org/telesto/mailbox"
-	"bitbucket.org/telesto/mailbox/mh"
 )
 
 type Command struct {
 	Name string
 	// Run runs the command.
 	// The args are the arguments after the command name.
-	Run func(mbox *mh.Mailbox, args []string) error
+	Run func(mbox *Mailbox, args []string) error
 
 	// UsageLine is the one-line usage message.
 	UsageLine string

          
@@ 53,16 50,16 @@ func main() {
 	}
 	var err error
 	// todo: put account into mailbox ehre
-	mbox := mh.NewMailbox()
+	mbox := NewMailbox()
 	switch cmd := os.Args[1]; cmd {
 	case "parse": // for testing only
 		if len(os.Args) < 3 {
 			err = missingParams
 			break
 		}
-		var msgs *mb.Sequence
+		var msgs *Sequence
 		folder, seq := path.Split(os.Args[2])
-		msgs, err = mb.ParseSequence(seq)
+		msgs, err = ParseSequence(seq)
 		os.Stdout.WriteString("Folder: " + folder)
 		fmt.Printf("\nSequence: %+v\n", msgs)
 		if err != nil {

          
@@ 74,7 71,7 @@ func main() {
 		if len(os.Args) > 2 {
 			folder = os.Args[2]
 		}
-		err = mb.List(mbox, os.Stdout, folder, mb.NewAlwaysMatcher())
+		err = List(mbox, os.Stdout, folder, NewAlwaysMatcher())
 	case "raw":
 		var src io.ReadCloser = os.Stdin
 		if len(os.Args) > 2 {

          
@@ 100,7 97,7 @@ func main() {
 			src.Close()
 			break
 		}
-		if err = mb.View(os.Stdout, msg); err != nil {
+		if err = View(os.Stdout, msg); err != nil {
 			src.Close()
 			break
 		}

          
@@ 129,7 126,7 @@ func main() {
 			src.Close()
 			break
 		}
-		if err = mb.ViewPart(os.Stdout, msg, part); err != nil {
+		if err = ViewPart(os.Stdout, msg, part); err != nil {
 			src.Close()
 			break
 		}

          
@@ 162,7 159,7 @@ func main() {
 		}
 		// todo: save more than one part by using matchers
 		var files []string
-		files, err = mb.Save(msg, part)
+		files, err = Save(msg, part)
 		// don't break on error, print what we got so far
 		for _, file := range files {
 			os.Stdout.WriteString(file + "\n")

          
@@ 179,12 176,12 @@ func main() {
 			break
 		}
 		var folder string
-		var msgs *mb.Sequence
+		var msgs *Sequence
 		if folder, msgs, err = parseSequence(mbox, os.Args[2]); err != nil {
 			break
 		}
 		var parts []string
-		parts, err = mb.Parts(mbox, folder, msgs)
+		parts, err = Parts(mbox, folder, msgs)
 		for _, part := range parts {
 			os.Stdout.WriteString(part + "\n")
 		}

          
@@ 198,11 195,11 @@ func main() {
 		//			break
 		//		}
 		//		var folder string
-		//		var match *mb.Regexp
+		//		var match *Regexp
 		//		if folder, match, err = parseRegexpCmd(os.Args[2:]); err != nil {
 		//			break
 		//		}
-		//		var msgs []mh.Message
+		//		var msgs []Message
 		//		if msgs, errors = mbox.ReadFolder(folder); err != nil {
 		//			break
 		//		}

          
@@ 218,7 215,7 @@ func main() {
 		//		}
 	case "new":
 		var name string
-		if name, err = mb.Create(mbox); len(name) > 0 {
+		if name, err = Create(mbox); len(name) > 0 {
 			os.Stdout.WriteString(name + "\n")
 		}
 	case "attach":

          
@@ 233,7 230,7 @@ func main() {
 				break
 			}
 		}
-		err = mb.Attach(mbox, os.Stdout, src, os.Args[3])
+		err = Attach(mbox, os.Stdout, src, os.Args[3])
 		if err1 := src.Close(); err == nil {
 			err = err1
 		}

          
@@ 253,7 250,7 @@ func main() {
 			break
 		}
 		var name string
-		if name, err = mb.Reply(mbox, msg); len(name) > 0 {
+		if name, err = Reply(mbox, msg); len(name) > 0 {
 			os.Stdout.WriteString(name + "\n")
 		}
 		if err1 := src.Close(); err == nil {

          
@@ 272,7 269,7 @@ func main() {
 			break
 		}
 		var name string
-		if name, err = mb.Forward(mbox, msg); len(name) > 0 {
+		if name, err = Forward(mbox, msg); len(name) > 0 {
 			os.Stdout.WriteString(name + "\n")
 		}
 		if err1 := src.Close(); err == nil {

          
@@ 291,7 288,7 @@ func main() {
 			break
 		}
 		var name string
-		if name, err = mb.Edit(mbox, msg); len(name) > 0 {
+		if name, err = Edit(mbox, msg); len(name) > 0 {
 			os.Stdout.WriteString(name + "\n")
 		}
 		if err1 := src.Close(); err == nil {

          
@@ 309,7 306,7 @@ func main() {
 			src.Close()
 			break
 		}
-		if err = mb.Send(msg); err != nil {
+		if err = Send(msg); err != nil {
 			src.Close()
 			break
 		}

          
@@ 317,12 314,12 @@ func main() {
 			break
 		}
 		var folder string
-		var msgs *mb.Sequence
+		var msgs *Sequence
 		folder, msgs, err = parseSequence(mbox, os.Args[2])
 		if err != nil {
 			break
 		}
-		err = mb.Move(mbox, folder, msgs, mbox.Sent)
+		err = Move(mbox, folder, msgs, mbox.Sent)
 	case "mv":
 		// todo: defaultfolder
 		if len(os.Args) < 4 {

          
@@ 330,24 327,24 @@ func main() {
 			break
 		}
 		var folder string
-		var msgs *mb.Sequence
+		var msgs *Sequence
 		folder, msgs, err = parseSequence(mbox, os.Args[2])
 		if err != nil {
 			break
 		}
-		err = mb.Move(mbox, folder, msgs, os.Args[3])
+		err = Move(mbox, folder, msgs, os.Args[3])
 	case "rm":
 		if len(os.Args) < 3 {
 			err = missingParams
 			break
 		}
 		var folder string
-		var msgs *mb.Sequence
+		var msgs *Sequence
 		folder, msgs, err = parseSequence(mbox, os.Args[2])
 		if err != nil {
 			break
 		}
-		err = mb.Remove(mbox, folder, msgs)
+		err = Remove(mbox, folder, msgs)
 	case "cp":
 		// todo: do we need this?
 		err = errors.New(cmd + ": not implemented")

          
@@ 379,7 376,7 @@ func main() {
 	}
 }
 
-func openMsg(mbox *mh.Mailbox, msg string) (io.ReadCloser, error) {
+func openMsg(mbox *Mailbox, msg string) (io.ReadCloser, error) {
 	f, m := path.Split(msg)
 	if len(f) == 0 {
 		f = mbox.DefaultFolder

          
@@ 393,12 390,12 @@ func openMsg(mbox *mh.Mailbox, msg strin
 
 // todo: accept things like "inbox/5 inbox/8\ndraft/18-20"
 // todo: make the folder part of the sequence
-func parseSequence(mbox *mh.Mailbox, value string) (string, *mb.Sequence, error) {
+func parseSequence(mbox *Mailbox, value string) (string, *Sequence, error) {
 	folder, seq := path.Split(value)
 	if len(folder) == 0 {
 		folder = mbox.DefaultFolder
 	}
-	msgs, err := mb.ParseSequence(seq)
+	msgs, err := ParseSequence(seq)
 	if err != nil {
 		return "", nil, err
 	}

          
@@ 407,14 404,14 @@ func parseSequence(mbox *mh.Mailbox, val
 
 // todo: when len(args) == 0, then return alwaysmatcher
 // bullshit, give just one string here
-func parseRegexpCmd(args []string) (string, *mb.Regexp, error) {
+func parseRegexpCmd(args []string) (string, *Regexp, error) {
 	var i int
 	var folder string
 	if len(args) == 2 {
 		i = 1
 		folder = args[0]
 	}
-	m, err := mb.ParseRegexp(args[i])
+	m, err := ParseRegexp(args[i])
 	if err != nil {
 		return "", nil, err
 	}

          
M mh/mh.go => mh.go +6 -18
@@ 1,4 1,4 @@ 
-package mh
+package main
 
 // todo: move this to a mh subpackage?
 // todo: locking

          
@@ 16,17 16,6 @@ import (
 // set in setup.go
 var account *Mailbox
 
-// The folder types for different outputs in list view.
-//
-// You can add more types and add a format for the new types
-// in the formats variable below.
-// todo: copied from mailbox pkg
-const (
-	inOutbox = iota
-	inbox
-	outbox
-)
-
 // todo: maildir only, the rest is for account
 // we want to be able to use Mailbox by only providing the mail dir
 type Mailbox struct {

          
@@ 75,10 64,9 @@ func (mh *Mailbox) nextId(folder string)
 	return list[len(list)-1].Id + 1, nil
 }
 
-type Message struct {
-	Id int64
-	*mail.Message
-}
+//type Message struct {
+//	*mail.Message
+//}
 
 // returns a sorted list, can be a number file or a number dir
 func (mh *Mailbox) readDir(folder string) ([]numberInode, error) {

          
@@ 136,7 124,7 @@ func (mbox Mailbox) ReadFolder(folder st
 				mails <- errMail(list[i].Id, err)
 				continue
 			}
-			mails <- Message{list[i].Id, msg}
+			mails <- Message{list[i].Id, NewHeader(msg.Header), msg.Body}
 		}
 	}()
 	return mails, errors

          
@@ 171,7 159,7 @@ func errMail(id int64, err error) Messag
 	h := make(map[string][]string, 1)
 	h["Subject"] = []string{"Error: " + err.Error()}
 	body := strings.NewReader("Error: " + err.Error())
-	return Message{id, &mail.Message{h, body}}
+	return Message{id, NewHeader(h), body}
 }
 
 func (mh *Mailbox) MkFolder(folder string) error {

          
M parse.go +1 -1
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"encoding/base64"

          
M reply_test.go +1 -1
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"bytes"

          
M send.go +1 -1
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"fmt"

          
M sequence.go +3 -5
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import (
 	"errors"

          
@@ 7,8 7,6 @@ import (
 	"strconv"
 	"strings"
 	"unicode/utf8"
-
-	"bitbucket.org/telesto/mailbox/mh"
 )
 
 type Sequence struct {

          
@@ 72,8 70,8 @@ type Regexp struct {
 	r           *rgxp.Regexp
 }
 
-func (s Regexp) Matches(m mh.Message) bool {
-	for key := range m.Header {
+func (s Regexp) Matches(m Message) bool {
+	for key := range m.Header.Header {
 		if s.matchHeader(key) && s.r.MatchString(safeDecodeHeader(m.Header.Get(key))) {
 			return true
 		}

          
M sequence_test.go +1 -1
@@ 1,4 1,4 @@ 
-package mailbox
+package main
 
 import "testing"
 

          
M mh/setup_template.go => setup_template.go +1 -1
@@ 1,4 1,4 @@ 
-package mh
+package main
 
 // These are instructions for setting up the MH account:
 // - Copy this file to setup.go (in the same folder).