mirror of
https://blitiri.com.ar/repos/chasquid
synced 2026-10-28 15:02:28 +00:00
d74e6e3d2b
Delivery errors can be visible to the end-user via DSN responses, and some of them are not very clear, or are missing useful debugging information (such as the MX). This patch improves the messages by including the MX where appropriate, having explicit errors for cases where no servers are found/allowed, and using less technical language for the common explanations. There are no changes to the behaviour on errors, this change only affects the messages.
137 lines
3.5 KiB
Go
137 lines
3.5 KiB
Go
package courier
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestMDA(t *testing.T) {
|
|
dir := t.ArtifactDir()
|
|
|
|
p := MDA{
|
|
Binary: "tee",
|
|
Args: []string{dir + "/%to_user%"},
|
|
Timeout: 1 * time.Minute,
|
|
}
|
|
|
|
err, _ := p.Deliver("from@x", "to@local", []byte("data"))
|
|
if err != nil {
|
|
t.Fatalf("Deliver: %v", err)
|
|
}
|
|
|
|
data, err := os.ReadFile(dir + "/to")
|
|
if err != nil || !bytes.Equal(data, []byte("data")) {
|
|
t.Errorf("Invalid data: %q - %v", string(data), err)
|
|
}
|
|
}
|
|
|
|
func TestMDATimeout(t *testing.T) {
|
|
p := MDA{"sleep", []string{"1"}, 100 * time.Millisecond}
|
|
|
|
err, permanent := p.Deliver("from", "to@local", []byte("data"))
|
|
if !errors.Is(err, errTimeout) {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if permanent {
|
|
t.Errorf("expected transient, got permanent")
|
|
}
|
|
}
|
|
|
|
func TestMDABadCommandLine(t *testing.T) {
|
|
// Non-existent binary.
|
|
p := MDA{"thisdoesnotexist", nil, 1 * time.Minute}
|
|
err, permanent := p.Deliver("from", "to", []byte("data"))
|
|
if err == nil {
|
|
t.Errorf("unexpected success for non-existent binary")
|
|
}
|
|
if !permanent {
|
|
t.Errorf("expected permanent, got transient")
|
|
}
|
|
|
|
// Incorrect arguments.
|
|
p = MDA{"cat", []string{"--fail_unknown_option"}, 1 * time.Minute}
|
|
err, _ = p.Deliver("from", "to", []byte("data"))
|
|
if err == nil {
|
|
t.Errorf("unexpected success for incorrect arguments")
|
|
}
|
|
}
|
|
|
|
// Test that local delivery failures are considered permanent or not
|
|
// according to the exit code.
|
|
func TestExitCode(t *testing.T) {
|
|
// TODO: This can happen when building under unusual circumstances, such
|
|
// as Debian package building. Are they reasonable enough for us to keep
|
|
// this?
|
|
if _, err := os.Stat("../../test/util/exitcode"); errors.Is(err, fs.ErrNotExist) {
|
|
t.Skipf("util/exitcode not found, running from outside repo?")
|
|
}
|
|
|
|
cases := []struct {
|
|
cmd string
|
|
args []string
|
|
expectPermanent bool
|
|
}{
|
|
{"does/not/exist", nil, true},
|
|
{"../../test/util/exitcode", []string{"1"}, true},
|
|
{"../../test/util/exitcode", []string{"75"}, false},
|
|
}
|
|
for _, c := range cases {
|
|
p := &MDA{c.cmd, c.args, 5 * time.Second}
|
|
err, permanent := p.Deliver("from", "to", []byte("data"))
|
|
if err == nil {
|
|
t.Errorf("%q: pipe delivery worked, expected failure", c.cmd)
|
|
}
|
|
if c.expectPermanent != permanent {
|
|
t.Errorf("%q: permanent expected=%v, got=%v",
|
|
c.cmd, c.expectPermanent, permanent)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSanitize(t *testing.T) {
|
|
cases := []struct{ v, expected string }{
|
|
// These are the same.
|
|
{"thisisfine", "thisisfine"},
|
|
{"ñaca", "ñaca"},
|
|
{"123-456_789", "123-456_789"},
|
|
{"123+456~789", "123+456~789"},
|
|
|
|
// These have problematic characters that get dropped.
|
|
{"with spaces", "withspaces"},
|
|
{"with/slash", "withslash"},
|
|
{"quote';andsemicolon", "quoteandsemicolon"},
|
|
{"a;b", "ab"},
|
|
{`"test"`, "test"},
|
|
|
|
// Interesting cases taken from
|
|
// http://www.user.uni-hannover.de/nhtcapri/bidirectional-text.html
|
|
// We allow them, they're the same on both sides.
|
|
{"١٩٩٩–١٢–٣١", "١٩٩٩–١٢–٣١"},
|
|
|
|
//lint:ignore ST1018 The use of a literal U+200C is intentional.
|
|
{"موزهها", "موزه\u200cها"},
|
|
}
|
|
for _, c := range cases {
|
|
out := sanitizeForMDA(c.v)
|
|
if out != c.expected {
|
|
t.Errorf("%q: expected %q, got %q", c.v, c.expected, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestForward(t *testing.T) {
|
|
p := MDA{"thisdoesnotexist", nil, 1 * time.Minute}
|
|
err, permanent := p.Forward(
|
|
"from", "to", []byte("data"), []string{"server"})
|
|
if err != errForwardNotSupported {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if !permanent {
|
|
t.Errorf("expected permanent, got transient")
|
|
}
|
|
}
|