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 smtpconn
 20
 21import (
 22	"context"
 23	"strings"
 24	"testing"
 25
 26	"github.com/emersion/go-message/textproto"
 27	"github.com/emersion/go-smtp"
 28	"github.com/foxcpp/maddy/framework/config"
 29	"github.com/foxcpp/maddy/framework/exterrors"
 30	"github.com/foxcpp/maddy/internal/testutils"
 31)
 32
 33func doTestDelivery(t *testing.T, conn *C, from string, to []string, opts smtp.MailOptions) error {
 34	t.Helper()
 35
 36	if err := conn.Mail(context.Background(), from, opts); err != nil {
 37		return err
 38	}
 39	for _, rcpt := range to {
 40		if err := conn.Rcpt(context.Background(), rcpt, smtp.RcptOptions{}); err != nil {
 41			return err
 42		}
 43	}
 44
 45	hdr := textproto.Header{}
 46	hdr.Add("B", "2")
 47	hdr.Add("A", "1")
 48	return conn.Data(context.Background(), hdr, strings.NewReader("foobar\n"))
 49}
 50
 51func TestSMTPUTF8(t *testing.T) {
 52	type test struct {
 53		clientSender string
 54		clientRcpt   string
 55
 56		serverUTF8   bool
 57		serverSender string
 58		serverRcpt   string
 59
 60		expectUTF8 bool
 61		expectErr  *exterrors.SMTPError
 62	}
 63	check := func(case_ test) {
 64		t.Helper()
 65
 66		be, srv := testutils.SMTPServer(t, "127.0.0.1:"+testPort)
 67		srv.EnableSMTPUTF8 = case_.serverUTF8
 68		defer srv.Close()
 69		defer testutils.CheckSMTPConnLeak(t, srv)
 70
 71		c := New()
 72		c.Log = testutils.Logger(t, "target.smtp")
 73		if _, err := c.Connect(context.Background(), config.Endpoint{
 74			Scheme: "tcp",
 75			Host:   "127.0.0.1",
 76			Port:   testPort,
 77		}, false, nil); err != nil {
 78			t.Fatal(err)
 79		}
 80		defer c.Close()
 81
 82		err := doTestDelivery(t, c, case_.clientSender, []string{case_.clientRcpt},
 83			smtp.MailOptions{UTF8: true})
 84		if err != nil {
 85			if case_.expectErr == nil {
 86				t.Error("Unexpected failure")
 87			} else {
 88				testutils.CheckSMTPErr(t, err, case_.expectErr.Code, case_.expectErr.EnhancedCode, case_.expectErr.Message)
 89			}
 90			return
 91		} else if case_.expectErr != nil {
 92			t.Error("Unexpected success")
 93		}
 94
 95		be.CheckMsg(t, 0, case_.serverSender, []string{case_.serverRcpt})
 96		if be.Messages[0].Opts.UTF8 != case_.expectUTF8 {
 97			t.Errorf("expectUTF8 = %v, SMTPUTF8 = %v", case_.expectErr, be.Messages[0].Opts.UTF8)
 98		}
 99	}
100
101	check(test{
102		clientSender: "test@тест.example.org",
103		clientRcpt:   "test@example.invalid",
104		serverSender: "test@xn--e1aybc.example.org",
105		serverRcpt:   "test@example.invalid",
106	})
107	check(test{
108		clientSender: "test@example.org",
109		clientRcpt:   "test@тест.example.invalid",
110		serverSender: "test@example.org",
111		serverRcpt:   "test@xn--e1aybc.example.invalid",
112	})
113	check(test{
114		clientSender: "тест@example.org",
115		clientRcpt:   "test@example.invalid",
116		serverUTF8:   false,
117		expectErr: &exterrors.SMTPError{
118			Code:         550,
119			EnhancedCode: exterrors.EnhancedCode{5, 6, 7},
120			Message:      "SMTPUTF8 is unsupported, cannot convert sender address",
121		},
122	})
123	check(test{
124		clientSender: "test@example.org",
125		clientRcpt:   "тест@example.invalid",
126		serverUTF8:   false,
127		expectErr: &exterrors.SMTPError{
128			Code:         553,
129			EnhancedCode: exterrors.EnhancedCode{5, 6, 7},
130			Message:      "SMTPUTF8 is unsupported, cannot convert recipient address",
131		},
132	})
133	check(test{
134		clientSender: "test@тест.org",
135		clientRcpt:   "test@example.invalid",
136		serverSender: "test@тест.org",
137		serverRcpt:   "test@example.invalid",
138		serverUTF8:   true,
139		expectUTF8:   true,
140	})
141	check(test{
142		clientSender: "test@example.org",
143		clientRcpt:   "test@тест.example.invalid",
144		serverSender: "test@example.org",
145		serverRcpt:   "test@тест.example.invalid",
146		serverUTF8:   true,
147		expectUTF8:   true,
148	})
149	check(test{
150		clientSender: "тест@example.org",
151		clientRcpt:   "test@example.invalid",
152		serverSender: "тест@example.org",
153		serverRcpt:   "test@example.invalid",
154		serverUTF8:   true,
155		expectUTF8:   true,
156	})
157	check(test{
158		clientSender: "test@example.org",
159		clientRcpt:   "тест@example.invalid",
160		serverSender: "test@example.org",
161		serverRcpt:   "тест@example.invalid",
162		serverUTF8:   true,
163		expectUTF8:   true,
164	})
165}