package server import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/http/httptest" "net/url" "os" "strings" "testing" "github.com/axllent/mailpit/config" "github.com/axllent/mailpit/internal/logger" "github.com/axllent/mailpit/internal/storage" "github.com/axllent/mailpit/server/apiv1" "github.com/jhillyerd/enmime" ) var ( putDataStruct struct { Read bool IDs []string } ) func TestAPIv1Messages(t *testing.T) { setup() defer storage.Close() r := apiRoutes() ts := httptest.NewServer(r) defer ts.Close() m, err := fetchMessages(ts.URL + "/api/v1/messages") if err != nil { t.Errorf(err.Error()) } // check count of empty database assertStatsEqual(t, ts.URL+"/api/v1/messages", 0, 0) // insert 100 t.Log("Insert 100 messages") insertEmailData(t) assertStatsEqual(t, ts.URL+"/api/v1/messages", 100, 100) m, err = fetchMessages(ts.URL + "/api/v1/messages") if err != nil { t.Errorf(err.Error()) } // read first 10 messages t.Log("Read first 10 messages including raw & headers") for idx, msg := range m.Messages { if idx == 10 { break } if _, err := clientGet(ts.URL + "/api/v1/message/" + msg.ID); err != nil { t.Errorf(err.Error()) } // get RAW if _, err := clientGet(ts.URL + "/api/v1/message/" + msg.ID + "/raw"); err != nil { t.Errorf(err.Error()) } // get headers if _, err := clientGet(ts.URL + "/api/v1/message/" + msg.ID + "/headers"); err != nil { t.Errorf(err.Error()) } } // 10 should be marked as read assertStatsEqual(t, ts.URL+"/api/v1/messages", 90, 100) // delete all t.Log("Delete all messages") _, err = clientDelete(ts.URL+"/api/v1/messages", "{}") if err != nil { t.Errorf("Expected nil, received %s", err.Error()) } assertStatsEqual(t, ts.URL+"/api/v1/messages", 0, 0) } func TestAPIv1ToggleReadStatus(t *testing.T) { setup() defer storage.Close() r := apiRoutes() ts := httptest.NewServer(r) defer ts.Close() m, err := fetchMessages(ts.URL + "/api/v1/messages") if err != nil { t.Errorf(err.Error()) } // check count of empty database assertStatsEqual(t, ts.URL+"/api/v1/messages", 0, 0) // insert 100 t.Log("Insert 100 messages") insertEmailData(t) assertStatsEqual(t, ts.URL+"/api/v1/messages", 100, 100) m, err = fetchMessages(ts.URL + "/api/v1/messages") if err != nil { t.Errorf(err.Error()) } // read first 10 IDs t.Log("Get first 10 IDs") putIDS := []string{} for idx, msg := range m.Messages { if idx == 10 { break } // store for later putIDS = append(putIDS, msg.ID) } assertStatsEqual(t, ts.URL+"/api/v1/messages", 100, 100) // mark first 10 as unread t.Log("Mark first 10 as read") putData := putDataStruct putData.Read = true putData.IDs = putIDS j, err := json.Marshal(putData) if err != nil { t.Errorf(err.Error()) } _, err = clientPut(ts.URL+"/api/v1/messages", string(j)) if err != nil { t.Errorf(err.Error()) } assertStatsEqual(t, ts.URL+"/api/v1/messages", 90, 100) // mark first 10 as read t.Log("Mark first 10 as unread") putData.Read = false j, err = json.Marshal(putData) if err != nil { t.Errorf(err.Error()) } _, err = clientPut(ts.URL+"/api/v1/messages", string(j)) if err != nil { t.Errorf(err.Error()) } assertStatsEqual(t, ts.URL+"/api/v1/messages", 100, 100) // mark all as read putData.Read = true putData.IDs = []string{} j, err = json.Marshal(putData) if err != nil { t.Errorf(err.Error()) } t.Log("Mark all read") _, err = clientPut(ts.URL+"/api/v1/messages", string(j)) if err != nil { t.Errorf(err.Error()) } assertStatsEqual(t, ts.URL+"/api/v1/messages", 0, 100) } func TestAPIv1Search(t *testing.T) { setup() defer storage.Close() r := apiRoutes() ts := httptest.NewServer(r) defer ts.Close() // insert 100 t.Log("Insert 100 messages & tag") insertEmailData(t) assertStatsEqual(t, ts.URL+"/api/v1/messages", 100, 100) // search assertSearchEqual(t, ts.URL+"/api/v1/search", "from-1@example.com", 1) assertSearchEqual(t, ts.URL+"/api/v1/search", "from:from-1@example.com", 1) assertSearchEqual(t, ts.URL+"/api/v1/search", "-from:from-1@example.com", 99) assertSearchEqual(t, ts.URL+"/api/v1/search", "-FROM:FROM-1@EXAMPLE.COM", 99) assertSearchEqual(t, ts.URL+"/api/v1/search", "to:from-1@example.com", 0) assertSearchEqual(t, ts.URL+"/api/v1/search", "from:@example.com", 100) assertSearchEqual(t, ts.URL+"/api/v1/search", "subject:\"Subject line\"", 100) assertSearchEqual(t, ts.URL+"/api/v1/search", "subject:\"SUBJECT LINE 17 END\"", 1) assertSearchEqual(t, ts.URL+"/api/v1/search", "!thisdoesnotexist", 100) assertSearchEqual(t, ts.URL+"/api/v1/search", "-ThisDoesNotExist", 100) assertSearchEqual(t, ts.URL+"/api/v1/search", "thisdoesnotexist", 0) assertSearchEqual(t, ts.URL+"/api/v1/search", "tag:\"Test tag 065\"", 1) assertSearchEqual(t, ts.URL+"/api/v1/search", "tag:\"TEST TAG 065\"", 1) assertSearchEqual(t, ts.URL+"/api/v1/search", "!tag:\"Test tag 023\"", 99) } func TestAPIv1Send(t *testing.T) { setup() defer storage.Close() r := apiRoutes() ts := httptest.NewServer(r) defer ts.Close() jsonData := `{ "From": { "Email": "john@example.com", "Name": "John Doe" }, "To": [ { "Email": "jane@example.com", "Name": "Jane Doe" } ], "Cc": [ { "Email": "manager1@example.com", "Name": "Manager 1" }, { "Email": "manager2@example.com", "Name": "Manager 2" } ], "Bcc": ["jack@example.com"], "Headers": { "X-IP": "1.2.3.4" }, "Subject": "Mailpit message via the HTTP API", "Text": "This is the text body", "HTML": "
Mailpit is awesome!
", "Attachments": [ { "Content": "VGhpcyBpcyBhIHBsYWluIHRleHQgYXR0YWNobWVudA==", "Filename": "Attached File.txt" } ], "ReplyTo": [ { "Email": "secretary@example.com", "Name": "Secretary" } ], "Tags": [ "Tag 1", "Tag 2" ] }` t.Log("Sending message via HTTP API") b, err := clientPost(ts.URL+"/api/v1/send", jsonData) if err != nil { t.Errorf("Expected nil, received %s", err.Error()) } resp := apiv1.SendMessageConfirmation{} if err := json.Unmarshal(b, &resp); err != nil { t.Errorf(err.Error()) return } t.Logf("Fetching response for message %s", resp.ID) msg, err := fetchMessage(ts.URL + "/api/v1/message/" + resp.ID) if err != nil { t.Errorf(err.Error()) } t.Logf("Testing response for message %s", resp.ID) assertEqual(t, `Mailpit message via the HTTP API`, msg.Subject, "wrong subject") assertEqual(t, `This is the text body`, msg.Text, "wrong text") assertEqual(t, `Mailpit is awesome!
`, msg.HTML, "wrong HTML") assertEqual(t, `"John Doe"