14 "github.com/mjl-/mox/mlog"
15 "github.com/mjl-/mox/mox-"
18func TestExport(t *testing.T) {
19 // Set up an account, add 2 messages to different 2 mailboxes. export as tar/zip
20 // and maildir/mbox. check there are 2 files in the repo, no errors.txt.
22 log := mlog.New("export", nil)
24 os.RemoveAll("../testdata/store/data")
25 mox.ConfigStaticPath = filepath.FromSlash("../testdata/store/mox.conf")
26 mox.MustLoadConfig(true, false)
28 acc, err := OpenAccount(pkglog, "mjl", false)
29 tcheck(t, err, "open account")
32 log.Check(err, "closing account")
36 msgFile, err := CreateMessageTemp(pkglog, "mox-test-export")
37 tcheck(t, err, "create temp")
38 defer os.Remove(msgFile.Name()) // To be sure.
40 const msg = "test: test\r\n\r\ntest\r\n"
41 _, err = msgFile.Write([]byte(msg))
42 tcheck(t, err, "write message")
45 acc.WithWLock(func() {
46 m = Message{Received: time.Now(), Size: int64(len(msg))}
47 err = acc.DeliverMailbox(pkglog, "Inbox", &m, msgFile)
48 tcheck(t, err, "deliver")
50 m = Message{Received: time.Now(), Size: int64(len(msg))}
51 err = acc.DeliverMailbox(pkglog, "Trash", &m, msgFile)
52 tcheck(t, err, "deliver")
55 var maildirZip, maildirTar, mboxZip, mboxTar bytes.Buffer
57 archive := func(archiver Archiver, mailbox string, messageIDs []int64, maildir bool) {
59 err = ExportMessages(ctxbg, log, acc.DB, acc.Dir, archiver, maildir, mailbox, messageIDs, true)
60 tcheck(t, err, "export messages")
61 err = archiver.Close()
62 tcheck(t, err, "archiver close")
65 os.RemoveAll("../testdata/exportmaildir")
66 os.RemoveAll("../testdata/exportmbox")
68 archive(ZipArchiver{zip.NewWriter(&maildirZip)}, "", nil, true)
69 archive(ZipArchiver{zip.NewWriter(&mboxZip)}, "", nil, false)
70 archive(TarArchiver{tar.NewWriter(&maildirTar)}, "", nil, true)
71 archive(TarArchiver{tar.NewWriter(&mboxTar)}, "", nil, false)
72 archive(TarArchiver{tar.NewWriter(&mboxTar)}, "Inbox", nil, false)
73 archive(TarArchiver{tar.NewWriter(&mboxTar)}, "", []int64{m.ID}, false)
74 archive(DirArchiver{filepath.FromSlash("../testdata/exportmaildir")}, "", nil, true)
75 archive(DirArchiver{filepath.FromSlash("../testdata/exportmbox")}, "", nil, false)
77 const defaultMailboxes = 6 // Inbox, Drafts, etc
78 if r, err := zip.NewReader(bytes.NewReader(maildirZip.Bytes()), int64(maildirZip.Len())); err != nil {
79 t.Fatalf("reading maildir zip: %v", err)
80 } else if len(r.File) != defaultMailboxes*3+2 {
81 t.Fatalf("maildir zip, expected %d*3 dirs, and 2 files, got %d files", defaultMailboxes, len(r.File))
84 if r, err := zip.NewReader(bytes.NewReader(mboxZip.Bytes()), int64(mboxZip.Len())); err != nil {
85 t.Fatalf("reading mbox zip: %v", err)
86 } else if len(r.File) != defaultMailboxes {
87 t.Fatalf("maildir zip, expected %d files, got %d files", defaultMailboxes, len(r.File))
90 checkTarFiles := func(r io.Reader, n int) {
92 tr := tar.NewReader(r)
100 if h.Name == "errors.txt" {
101 t.Fatalf("got errors.txt")
103 _, err = io.Copy(io.Discard, tr)
104 tcheck(t, err, "copy")
107 t.Fatalf("got %d files, expected %d", have, n)
111 checkTarFiles(&maildirTar, defaultMailboxes*3+2)
112 checkTarFiles(&mboxTar, defaultMailboxes)
114 checkDirFiles := func(dir string, n int) {
117 err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
118 if err == nil && !d.IsDir() {
123 tcheck(t, err, "walkdir")
125 t.Fatalf("got %d files, expected %d", have, n)
129 checkDirFiles(filepath.FromSlash("../testdata/exportmaildir"), 2)
130 checkDirFiles(filepath.FromSlash("../testdata/exportmbox"), defaultMailboxes)