maddy

Fork https://github.com/foxcpp/maddy

git clone git://git.lin.moe/go/maddy.git

  1/*
  2Maddy Mail Server - Composable all-in-one email server.
  3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
  4
  5This program is free software: you can redistribute it and/or modify
  6it under the terms of the GNU General Public License as published by
  7the Free Software Foundation, either version 3 of the License, or
  8(at your option) any later version.
  9
 10This program is distributed in the hope that it will be useful,
 11but WITHOUT ANY WARRANTY; without even the implied warranty of
 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13GNU General Public License for more details.
 14
 15You should have received a copy of the GNU General Public License
 16along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17*/
 18
 19package smtp
 20
 21import (
 22	"reflect"
 23	"testing"
 24	"time"
 25
 26	"github.com/emersion/go-message/textproto"
 27	"github.com/emersion/go-smtp"
 28	"github.com/foxcpp/maddy/framework/module"
 29)
 30
 31func init() {
 32	msgIDField = func() (string, error) {
 33		return "A", nil
 34	}
 35
 36	now = func() time.Time {
 37		return time.Unix(0, 0)
 38	}
 39}
 40
 41func TestSubmissionPrepare(t *testing.T) {
 42	test := func(hdrMap, expectedMap map[string][]string) {
 43		t.Helper()
 44
 45		hdr := textproto.Header{}
 46		for k, v := range hdrMap {
 47			for _, field := range v {
 48				hdr.Add(k, field)
 49			}
 50		}
 51
 52		endp := testEndpoint(t, "submission", &module.Dummy{}, &module.Dummy{}, nil, nil)
 53		defer func() {
 54			// Synchronize the endpoint initialization.
 55			// Otherwise Close will race with Serve called by setupListeners.
 56			cl, _ := smtp.Dial("127.0.0.1:" + testPort)
 57			cl.Close()
 58
 59			endp.Close()
 60		}()
 61
 62		session, err := endp.NewSession(nil)
 63		if err != nil {
 64			t.Fatal(err)
 65		}
 66
 67		err = session.(*Session).submissionPrepare(&module.MsgMetadata{}, &hdr)
 68		if expectedMap == nil {
 69			if err == nil {
 70				t.Error("Expected an error, got none")
 71			}
 72			t.Log(err)
 73			return
 74		}
 75		if expectedMap != nil && err != nil {
 76			t.Error("Unexpected error:", err)
 77			return
 78		}
 79
 80		resMap := make(map[string][]string)
 81		for field := hdr.Fields(); field.Next(); {
 82			resMap[field.Key()] = append(resMap[field.Key()], field.Value())
 83		}
 84
 85		if !reflect.DeepEqual(expectedMap, resMap) {
 86			t.Errorf("wrong header result\nwant %#+v\ngot  %#+v", expectedMap, resMap)
 87		}
 88	}
 89
 90	// No From field.
 91	test(map[string][]string{}, nil)
 92
 93	// Malformed From field.
 94	test(map[string][]string{
 95		"From": {"<hello@example.org>, \"\""},
 96	}, nil)
 97	test(map[string][]string{
 98		"From": {" adasda"},
 99	}, nil)
100
101	// Malformed Reply-To.
102	test(map[string][]string{
103		"From":     {"<hello@example.org>"},
104		"Reply-To": {"<hello@example.org>, \"\""},
105	}, nil)
106
107	// Malformed CC.
108	test(map[string][]string{
109		"From":     {"<hello@example.org>"},
110		"Reply-To": {"<hello@example.org>"},
111		"Cc":       {"<hello@example.org>, \"\""},
112	}, nil)
113
114	// Malformed Sender.
115	test(map[string][]string{
116		"From":     {"<hello@example.org>"},
117		"Reply-To": {"<hello@example.org>"},
118		"Cc":       {"<hello@example.org>"},
119		"Sender":   {"<hello@example.org> asd"},
120	}, nil)
121
122	// Multiple From + no Sender.
123	test(map[string][]string{
124		"From": {"<hello@example.org>, <hello2@example.org>"},
125	}, nil)
126
127	// Multiple From + valid Sender.
128	test(map[string][]string{
129		"From":       {"<hello@example.org>, <hello2@example.org>"},
130		"Sender":     {"<hello@example.org>"},
131		"Date":       {"Fri, 22 Nov 2019 20:51:31 +0800"},
132		"Message-Id": {"<foobar@example.org>"},
133	}, map[string][]string{
134		"From":       {"<hello@example.org>, <hello2@example.org>"},
135		"Sender":     {"<hello@example.org>"},
136		"Date":       {"Fri, 22 Nov 2019 20:51:31 +0800"},
137		"Message-Id": {"<foobar@example.org>"},
138	})
139
140	// Add missing Message-Id.
141	test(map[string][]string{
142		"From": {"<hello@example.org>"},
143		"Date": {"Fri, 22 Nov 2019 20:51:31 +0800"},
144	}, map[string][]string{
145		"From":       {"<hello@example.org>"},
146		"Date":       {"Fri, 22 Nov 2019 20:51:31 +0800"},
147		"Message-Id": {"<A@mx.example.com>"},
148	})
149
150	// Malformed Date.
151	test(map[string][]string{
152		"From": {"<hello@example.org>"},
153		"Date": {"not a date"},
154	}, nil)
155
156	// Add missing Date.
157	test(map[string][]string{
158		"From":       {"<hello@example.org>"},
159		"Message-Id": {"<A@mx.example.org>"},
160	}, map[string][]string{
161		"From":       {"<hello@example.org>"},
162		"Message-Id": {"<A@mx.example.org>"},
163		"Date":       {"Thu, 1 Jan 1970 00:00:00 +0000"},
164	})
165}