1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package smtpconn2021import (22 "context"23 "strings"24 "testing"2526 "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)3233func doTestDelivery(t *testing.T, conn *C, from string, to []string, opts smtp.MailOptions) error {34 t.Helper()3536 if err := conn.Mail(context.Background(), from, opts); err != nil {37 return err38 }39 for _, rcpt := range to {40 if err := conn.Rcpt(context.Background(), rcpt, smtp.RcptOptions{}); err != nil {41 return err42 }43 }4445 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}5051func TestSMTPUTF8(t *testing.T) {52 type test struct {53 clientSender string54 clientRcpt string5556 serverUTF8 bool57 serverSender string58 serverRcpt string5960 expectUTF8 bool61 expectErr *exterrors.SMTPError62 }63 check := func(case_ test) {64 t.Helper()6566 be, srv := testutils.SMTPServer(t, "127.0.0.1:"+testPort)67 srv.EnableSMTPUTF8 = case_.serverUTF868 defer srv.Close()69 defer testutils.CheckSMTPConnLeak(t, srv)7071 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()8182 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 return91 } else if case_.expectErr != nil {92 t.Error("Unexpected success")93 }9495 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 }100101 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}