Bump the version to 2.1.0.
[mailpopbox.git] / pop3_test.go
index 2a638848586db9cd6f5f5ae3dbe1263d439f292c..2ec1f52b27c6b9ab27146b1841f647d7d4f1f48d 100644 (file)
@@ -1,7 +1,19 @@
+// mailpopbox
+// Copyright 2020 Blue Static <https://www.bluestatic.org>
+// This program is free software licensed under the GNU General Public License,
+// version 3.0. The full text of the license can be found in LICENSE.txt.
+// SPDX-License-Identifier: GPL-3.0-only
+
 package main
 
 import (
+       "io/ioutil"
+       "net/textproto"
+       "os"
+       "path/filepath"
        "testing"
+
+       "go.uber.org/zap"
 )
 
 func TestReset(t *testing.T) {
@@ -35,3 +47,229 @@ func TestReset(t *testing.T) {
                t.Errorf("reset did not un-delete message %v", msg)
        }
 }
+
+func TestOpenMailboxAuth(t *testing.T) {
+       dir, err := ioutil.TempDir("", "maildrop")
+       if err != nil {
+               t.Errorf("Failed to create temp dir: %v", err)
+               return
+       }
+       defer os.RemoveAll(dir)
+
+       s := &pop3Server{
+               config: Config{
+                       Servers: []Server{
+                               {
+                                       Domain:          "example.com",
+                                       MailboxPassword: "letmein",
+                                       MaildropPath:    dir,
+                               },
+                               {
+                                       Domain:          "test.net",
+                                       MailboxPassword: "open-sesame",
+                                       MaildropPath:    dir,
+                               },
+                       },
+               },
+               log: zap.NewNop(),
+       }
+
+       cases := []struct {
+               user, pass string
+               ok         bool
+       }{
+               {"mailbox@example.com", "letmein", true},
+               {"mailbox@test.net", "open-sesame", true},
+               {"mailbox@example.com", "open-sesame", false},
+               {"test@test.net", "open-sesame", false},
+               {"mailbox@an-example.net", "letmein", false},
+       }
+       for i, c := range cases {
+               mb, err := s.OpenMailbox(c.user, c.pass)
+               got := (mb != nil && err == nil)
+               if got != c.ok {
+                       t.Errorf("Expected error=%v for case %d (%#v), got %v (error=%v, mb=%v)", c.ok, i, c, got, err, mb)
+               }
+       }
+}
+
+func TestBasicListener(t *testing.T) {
+       dir, err := ioutil.TempDir("", "maildrop")
+       if err != nil {
+               t.Errorf("Failed to create temp dir: %v", err)
+               return
+       }
+       defer os.RemoveAll(dir)
+
+       s := &pop3Server{
+               config: Config{
+                       POP3Port: 9648,
+                       Hostname: "example.com",
+                       Servers: []Server{
+                               {
+                                       Domain:       "example.com",
+                                       MaildropPath: dir,
+                               },
+                       },
+               },
+               log: zap.NewNop(),
+       }
+
+       go s.run()
+
+       conn, err := textproto.Dial("tcp", "localhost:9648")
+       if err != nil {
+               t.Errorf("Failed to dial test server: %v", err)
+               return
+       }
+
+       _, err = conn.ReadLine()
+       if err != nil {
+               t.Errorf("Failed to read line: %v", err)
+               return
+       }
+}
+
+func TestMailbox(t *testing.T) {
+       dir, err := ioutil.TempDir("", "maildrop")
+       if err != nil {
+               t.Errorf("Failed to create temp dir: %v", err)
+               return
+       }
+       defer os.RemoveAll(dir)
+
+       // Create the first message.
+       f, err := os.Create(filepath.Join(dir, "a.msg"))
+       if err != nil {
+               t.Errorf("Failed to create a.msg: %v", err)
+               return
+       }
+       for i := 0; i < 1024*10; i++ {
+               buf := []byte{'a'}
+               _, err = f.Write(buf)
+               if err != nil {
+                       t.Errorf("Failed to write a.msg: %v", err)
+               }
+       }
+       f.Close()
+
+       // Create the second message.
+       f, err = os.Create(filepath.Join(dir, "b.msg"))
+       if err != nil {
+               t.Errorf("Failed to create b.msg: %v", err)
+               return
+       }
+       for i := 0; i < 1024*3; i++ {
+               buf := []byte{'z'}
+               _, err = f.Write(buf)
+               if err != nil {
+                       t.Errorf("Failed to write z.msg: %v", err)
+               }
+       }
+       f.Close()
+
+       s := &pop3Server{
+               config: Config{
+                       Servers: []Server{
+                               {
+                                       Domain:          "example.com",
+                                       MailboxPassword: "letmein",
+                                       MaildropPath:    dir,
+                               },
+                       },
+               },
+               log: zap.NewNop(),
+       }
+
+       // Test message metadata.
+       mb, err := s.OpenMailbox("mailbox@example.com", "letmein")
+       if err != nil {
+               t.Errorf("Failed to open mailbox: %v", err)
+       }
+
+       msgs, err := mb.ListMessages()
+       if err != nil {
+               t.Errorf("Failed to list messages: %v", err)
+       }
+
+       if want, got := 2, len(msgs); want != got {
+               t.Errorf("Want %d messages, got %d", want, got)
+       }
+
+       if mb.GetMessage(0) != nil {
+               t.Errorf("Messages should be 1-indexed")
+       }
+       if mb.GetMessage(3) != nil {
+               t.Errorf("Retreived unexpected message")
+       }
+
+       if msgs[0] != mb.GetMessage(msgs[0].ID()) {
+               t.Errorf("Failed to look up message by ID")
+       }
+
+       if want, got := "a", msgs[0].UniqueID(); want != got {
+               t.Errorf("Want message #1 unique ID to be %s, got %s", want, got)
+       }
+       if want, got := 1024*10, msgs[0].Size(); want != got {
+               t.Errorf("Want message #1 size to be %v, got %v", want, got)
+       }
+
+       if want, got := "b", msgs[1].UniqueID(); want != got {
+               t.Errorf("Want message #2 unique ID to be %s, got %s", want, got)
+       }
+       if want, got := 1024*3, msgs[1].Size(); want != got {
+               t.Errorf("Want message #2 size to be %v, got %v", want, got)
+       }
+
+       // Test message contents.
+       rc, err := mb.Retrieve(msgs[0])
+       if err != nil {
+               t.Errorf("Failed to retrieve message: %v", err)
+       }
+       rc.Close()
+
+       // Test deletion marking and reset.
+       err = mb.Delete(msgs[1])
+       if err != nil {
+               t.Errorf("Failed to mark message #2 for deletion: %v", err)
+       }
+
+       if !msgs[1].Deleted() {
+               t.Errorf("Message should be marked for deletion and isn't")
+       }
+
+       mb.Reset()
+
+       if msgs[1].Deleted() {
+               t.Errorf("Message is marked for deletion and shouldn't be")
+       }
+
+       // Test deletion for real.
+       err = mb.Delete(msgs[0])
+       if err != nil {
+               t.Errorf("Failed to mark message for deletion: %v", err)
+       }
+
+       err = mb.Close()
+       if err != nil {
+               t.Errorf("Failed to close mailbox: %v", err)
+       }
+
+       mb, err = s.OpenMailbox("mailbox@example.com", "letmein")
+       if err != nil {
+               t.Errorf("Failed to re-open mailbox: %v", err)
+       }
+
+       msgs, err = mb.ListMessages()
+       if err != nil {
+               t.Errorf("Failed to list messages: %v", err)
+       }
+
+       if want, got := 1, len(msgs); want != got {
+               t.Errorf("Number of messages should be %d, got %d", want, got)
+       }
+
+       if want, got := "b", msgs[0].UniqueID(); want != got {
+               t.Errorf("Message Unique ID should be %s, got %s", want, got)
+       }
+}