mirror of
https://github.com/foxcpp/maddy.git
synced 2025-04-05 14:07:38 +03:00
343 lines
9 KiB
Go
343 lines
9 KiB
Go
package smtp
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/emersion/go-smtp"
|
|
"github.com/foxcpp/go-mockdns"
|
|
"github.com/foxcpp/maddy/framework/exterrors"
|
|
"github.com/foxcpp/maddy/framework/module"
|
|
"github.com/foxcpp/maddy/internal/testutils"
|
|
)
|
|
|
|
func TestSMTPUTF8_MangleStatusMessage(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, []module.Check{
|
|
&testutils.Check{
|
|
ConnRes: module.CheckResult{
|
|
Reason: &exterrors.SMTPError{
|
|
Code: 523,
|
|
Message: "Hey 凱凱",
|
|
},
|
|
Reject: true,
|
|
},
|
|
},
|
|
}, nil)
|
|
endp.deferServerReject = false
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = cl.Mail("sender@example.org", nil)
|
|
if err == nil {
|
|
t.Fatal("Expected an error, got none")
|
|
}
|
|
smtpErr, ok := err.(*smtp.SMTPError)
|
|
if !ok {
|
|
t.Fatal("Non-SMTPError returned")
|
|
}
|
|
|
|
if smtpErr.Code != 523 {
|
|
t.Fatal("Wrong SMTP code:", smtpErr.Code)
|
|
}
|
|
if !strings.HasPrefix(smtpErr.Message, "Hey ??") {
|
|
t.Fatal("Wrong SMTP message:", smtpErr.Message)
|
|
}
|
|
}
|
|
|
|
func TestSMTP_RejectNonASCIIFrom(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
endp.deferServerReject = false
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = submitMsg(t, cl, "ѣ@example.org", []string{"rcpt@example.com"}, testMsg)
|
|
|
|
smtpErr, ok := err.(*smtp.SMTPError)
|
|
if !ok {
|
|
t.Fatal("Non-SMTPError returned")
|
|
}
|
|
if smtpErr.Code != 550 {
|
|
t.Fatal("Wrong SMTP code:", smtpErr.Code)
|
|
}
|
|
if smtpErr.EnhancedCode != (smtp.EnhancedCode{5, 6, 7}) {
|
|
t.Fatal("Wrong SMTP ench. code:", smtpErr.EnhancedCode)
|
|
}
|
|
}
|
|
|
|
func TestSMTPUTF8_NormalizeCaseFoldFrom(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
endp.deferServerReject = false
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = submitMsgOpts(t, cl, "foo@E\u0301.example.org", []string{"rcpt@example.com"}, &smtp.MailOptions{
|
|
UTF8: true,
|
|
}, testMsg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(tgt.Messages) != 1 {
|
|
t.Fatal("Expected a message, got", len(tgt.Messages))
|
|
}
|
|
msg := tgt.Messages[0]
|
|
testutils.CheckMsgID(t, &msg, "foo@é.example.org", []string{"rcpt@example.com"}, "")
|
|
}
|
|
|
|
func TestSMTP_RejectNonASCIIRcpt(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
endp.deferServerReject = false
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = submitMsg(t, cl, "x@example.org", []string{"ѣ@example.org"}, testMsg)
|
|
|
|
smtpErr, ok := err.(*smtp.SMTPError)
|
|
if !ok {
|
|
t.Fatal("Non-SMTPError returned")
|
|
}
|
|
if smtpErr.Code != 553 {
|
|
t.Fatal("Wrong SMTP code:", smtpErr.Code)
|
|
}
|
|
if smtpErr.EnhancedCode != (smtp.EnhancedCode{5, 6, 7}) {
|
|
t.Fatal("Wrong SMTP ench. code:", smtpErr.EnhancedCode)
|
|
}
|
|
}
|
|
|
|
func TestSMTPUTF8_NormalizeCaseFoldRcpt(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
endp.deferServerReject = false
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = submitMsgOpts(t, cl, "x@example.org", []string{"foo@E\u0301.example.org"}, &smtp.MailOptions{
|
|
UTF8: true,
|
|
}, testMsg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(tgt.Messages) != 1 {
|
|
t.Fatal("Expected a message, got", len(tgt.Messages))
|
|
}
|
|
msg := tgt.Messages[0]
|
|
testutils.CheckMsgID(t, &msg, "x@example.org", []string{"foo@é.example.org"}, "")
|
|
}
|
|
|
|
func TestSMTPUTF8_NoMangleStatusMessage(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, []module.Check{
|
|
&testutils.Check{
|
|
ConnRes: module.CheckResult{
|
|
Reason: &exterrors.SMTPError{
|
|
Code: 523,
|
|
Message: "Hey 凱凱",
|
|
},
|
|
Reject: true,
|
|
},
|
|
},
|
|
}, nil)
|
|
endp.deferServerReject = false
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = cl.Mail("sender@example.org", &smtp.MailOptions{
|
|
UTF8: true,
|
|
})
|
|
if err == nil {
|
|
t.Fatal("Expected an error, got none")
|
|
}
|
|
smtpErr, ok := err.(*smtp.SMTPError)
|
|
if !ok {
|
|
t.Fatal("Non-SMTPError returned")
|
|
}
|
|
|
|
if smtpErr.Code != 523 {
|
|
t.Fatal("Wrong SMTP code:", smtpErr.Code)
|
|
}
|
|
if !strings.HasPrefix(smtpErr.Message, "Hey 凱凱") {
|
|
t.Fatal("Wrong SMTP message:", smtpErr.Message)
|
|
}
|
|
}
|
|
|
|
func TestSMTPUTF8_Received_EHLO_ALabel(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
if err := cl.Hello("凱凱.invalid"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = submitMsg(t, cl, "sender@example.org", []string{"rcpt1@example.com", "rcpt2@example.com"}, testMsg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(tgt.Messages) != 1 {
|
|
t.Fatal("Expected a message, got", len(tgt.Messages))
|
|
}
|
|
msg := tgt.Messages[0]
|
|
msgID := testutils.CheckMsgID(t, &msg, "sender@example.org", []string{"rcpt1@example.com", "rcpt2@example.com"}, "")
|
|
|
|
receivedPrefix := `from xn--y9qa.invalid (mx.example.org [127.0.0.1]) by mx.example.com (envelope-sender <sender@example.org>) with ESMTP id ` + msgID
|
|
|
|
if !strings.HasPrefix(msg.Header.Get("Received"), receivedPrefix) {
|
|
t.Error("Wrong Received contents:", msg.Header.Get("Received"))
|
|
}
|
|
}
|
|
|
|
func TestSMTPUTF8_Received_rDNS_ALabel(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
endp.resolver.(*mockdns.Resolver).Zones["1.0.0.127.in-addr.arpa."] = mockdns.Zone{
|
|
PTR: []string{"凱凱.invalid."},
|
|
}
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = submitMsg(t, cl, "sender@example.org", []string{"rcpt1@example.com", "rcpt2@example.com"}, testMsg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(tgt.Messages) != 1 {
|
|
t.Fatal("Expected a message, got", len(tgt.Messages))
|
|
}
|
|
msg := tgt.Messages[0]
|
|
msgID := testutils.CheckMsgID(t, &msg, "sender@example.org", []string{"rcpt1@example.com", "rcpt2@example.com"}, "")
|
|
|
|
receivedPrefix := `from mx.example.org (xn--y9qa.invalid [127.0.0.1]) by mx.example.com (envelope-sender <sender@example.org>) with ESMTP id ` + msgID
|
|
|
|
if !strings.HasPrefix(msg.Header.Get("Received"), receivedPrefix) {
|
|
t.Error("Wrong Received contents:", msg.Header.Get("Received"))
|
|
}
|
|
}
|
|
|
|
func TestSMTPUTF8_Received_rDNS_ULabel(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
endp.resolver.(*mockdns.Resolver).Zones["1.0.0.127.in-addr.arpa."] = mockdns.Zone{
|
|
PTR: []string{"凱凱.invalid."},
|
|
}
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
err = submitMsgOpts(t, cl, "sender@example.org", []string{"rcpt1@example.com", "rcpt2@example.com"}, &smtp.MailOptions{
|
|
UTF8: true,
|
|
}, testMsg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(tgt.Messages) != 1 {
|
|
t.Fatal("Expected a message, got", len(tgt.Messages))
|
|
}
|
|
msg := tgt.Messages[0]
|
|
msgID := testutils.CheckMsgID(t, &msg, "sender@example.org", []string{"rcpt1@example.com", "rcpt2@example.com"}, "")
|
|
|
|
receivedPrefix := `from mx.example.org (凱凱.invalid [127.0.0.1]) by mx.example.com (envelope-sender <sender@example.org>) with UTF8ESMTP id ` + msgID
|
|
|
|
if !strings.HasPrefix(msg.Header.Get("Received"), receivedPrefix) {
|
|
t.Error("Wrong Received contents:", msg.Header.Get("Received"))
|
|
}
|
|
}
|
|
|
|
func TestSMTPUTF8_Received_EHLO_ULabel(t *testing.T) {
|
|
tgt := testutils.Target{}
|
|
endp := testEndpoint(t, "smtp", nil, &tgt, nil, nil)
|
|
defer endp.Close()
|
|
defer testutils.WaitForConnsClose(t, endp.serv)
|
|
|
|
cl, err := smtp.Dial("127.0.0.1:" + testPort)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer cl.Close()
|
|
|
|
if err := cl.Hello("凱凱.invalid"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = submitMsgOpts(t, cl, "sender@example.org", []string{"rcpt@example.com"}, &smtp.MailOptions{
|
|
UTF8: true,
|
|
}, testMsg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(tgt.Messages) != 1 {
|
|
t.Fatal("Expected a message, got", len(tgt.Messages))
|
|
}
|
|
msg := tgt.Messages[0]
|
|
msgID := testutils.CheckMsgID(t, &msg, "sender@example.org", []string{"rcpt@example.com"}, "")
|
|
|
|
// Also, 'with UTF8ESMTP'.
|
|
receivedPrefix := `from 凱凱.invalid (mx.example.org [127.0.0.1]) by mx.example.com (envelope-sender <sender@example.org>) with UTF8ESMTP id ` + msgID
|
|
|
|
if !strings.HasPrefix(msg.Header.Get("Received"), receivedPrefix) {
|
|
t.Error("Wrong Received contents:", msg.Header.Get("Received"))
|
|
}
|
|
}
|