git » chasquid » commit 905161c

test: Add a test for Exim interactions

author Alberto Bertogli
2016-07-21 21:21:48 UTC
committer Alberto Bertogli
2016-09-12 03:06:56 UTC
parent aac2d3c06190e92fe85023d9f079e451030f3930

test: Add a test for Exim interactions

This patch adds a new test which makes chasquid send and receive email to/from
Exim.

To make it work we need to add two testing flags to the SMTP courier, which is
not ideal but doesn't muddle the code much.

The test is not very portable, and assumes an exim binary is available, but
does not have to be installed in the system. It includes a helper script to
fetch one from the Debian archives.

internal/courier/smtp.go +12 -2
internal/courier/smtp_test.go +2 -2
test/t-exim/.gitignore +3 -0
test/t-exim/config/chasquid.conf +5 -0
test/t-exim/config/domains/srv-chasquid/users +2 -0
test/t-exim/config/exim4.in +62 -0
test/t-exim/content +4 -0
test/t-exim/get-exim4-debian.sh +27 -0
test/t-exim/hosts +2 -0
test/t-exim/msmtprc +14 -0
test/t-exim/run.sh +57 -0

diff --git a/internal/courier/smtp.go b/internal/courier/smtp.go
index 423cb50..cf2e199 100644
--- a/internal/courier/smtp.go
+++ b/internal/courier/smtp.go
@@ -2,6 +2,7 @@ package courier
 
 import (
 	"crypto/tls"
+	"flag"
 	"net"
 	"net/smtp"
 	"time"
@@ -19,7 +20,12 @@ var (
 
 	// Port for outgoing SMTP.
 	// Tests can override this.
-	smtpPort = "25"
+	smtpPort = flag.String("testing__outgoing_smtp_port", "25",
+		"port to use for outgoing SMTP connections, ONLY FOR TESTING")
+
+	// Bypass the MX lookup, for testing purposes.
+	bypassMX = flag.Bool("testing__bypass_mx_lookup", false,
+		"bypass MX lookup, ONLY FOR TESTING")
 
 	// Fake MX records, used for testing only.
 	fakeMX = map[string]string{}
@@ -45,7 +51,7 @@ func (s *SMTP) Deliver(from string, to string, data []byte) error {
 	insecure := false
 
 retry:
-	conn, err := net.DialTimeout("tcp", mx+":"+smtpPort, smtpDialTimeout)
+	conn, err := net.DialTimeout("tcp", mx+":"+*smtpPort, smtpDialTimeout)
 	if err != nil {
 		return tr.Errorf("Could not dial: %v", err)
 	}
@@ -117,6 +123,10 @@ func lookupMX(domain string) (string, error) {
 		return v, nil
 	}
 
+	if *bypassMX {
+		return domain, nil
+	}
+
 	mxs, err := net.LookupMX(domain)
 	if err != nil {
 		return "", err
diff --git a/internal/courier/smtp_test.go b/internal/courier/smtp_test.go
index 46e21c9..b90a7ba 100644
--- a/internal/courier/smtp_test.go
+++ b/internal/courier/smtp_test.go
@@ -70,7 +70,7 @@ func TestSMTP(t *testing.T) {
 	host, port, _ := net.SplitHostPort(addr)
 
 	fakeMX["to"] = host
-	smtpPort = port
+	*smtpPort = port
 
 	s := &SMTP{}
 	err := s.Deliver("me@me", "to@to", []byte("data"))
@@ -130,7 +130,7 @@ func TestSMTPErrors(t *testing.T) {
 		host, port, _ := net.SplitHostPort(addr)
 
 		fakeMX["to"] = host
-		smtpPort = port
+		*smtpPort = port
 
 		s := &SMTP{}
 		err := s.Deliver("me@me", "to@to", []byte("data"))
diff --git a/test/t-exim/.gitignore b/test/t-exim/.gitignore
new file mode 100644
index 0000000..88be49f
--- /dev/null
+++ b/test/t-exim/.gitignore
@@ -0,0 +1,3 @@
+
+# Packages, so fetches via get-exim4-* don't add cruft.
+*.deb
diff --git a/test/t-exim/config/chasquid.conf b/test/t-exim/config/chasquid.conf
new file mode 100644
index 0000000..1302399
--- /dev/null
+++ b/test/t-exim/config/chasquid.conf
@@ -0,0 +1,5 @@
+address: ":1025"
+monitoring_address: ":1099"
+
+mail_delivery_agent_bin: "test-mda"
+mail_delivery_agent_args: "%user%@%domain%"
diff --git a/test/t-exim/config/domains/srv-chasquid/users b/test/t-exim/config/domains/srv-chasquid/users
new file mode 100644
index 0000000..bd031fe
--- /dev/null
+++ b/test/t-exim/config/domains/srv-chasquid/users
@@ -0,0 +1,2 @@
+#chasquid-userdb-v1
+user SCRYPT@n:14,r:8,p:1,l:32,r00XqNmRkV505R2X6KT8+Q== aAiBBIVNNzmDXwxLLdJezFuxGtc2/wcHsy3FiOMAH4c=
diff --git a/test/t-exim/config/exim4.in b/test/t-exim/config/exim4.in
new file mode 100644
index 0000000..7623b43
--- /dev/null
+++ b/test/t-exim/config/exim4.in
@@ -0,0 +1,62 @@
+CONFDIR = ${EXIMDIR}
+
+spool_directory = CONFDIR/spool
+exim_path = CONFDIR/exim4
+
+# No need to keep anything on the environment.
+# This is the default, but exim emits a warning if it's not set
+# (https://www.exim.org/static/doc/CVE-2016-1531.txt).
+keep_environment = 
+
+# Disable TLS for now.
+tls_advertise_hosts =
+
+# Run as the current user.
+# TODO: obviously do not hard-code it!
+exim_group = ${USER}
+exim_user = ${USER}
+
+# Listen on a non-privileged port.
+daemon_smtp_port = 2025
+
+# ACLs to let anyone send mail (for testing, obviously).
+acl_smtp_rcpt = acl_check_rcpt
+acl_smtp_data = acl_check_data
+
+begin acl
+acl_check_rcpt:
+  accept
+
+acl_check_data:
+  accept
+
+
+# Forward all incoming email to chasquid (running on :1025 in this test).
+begin routers
+
+rewritedst:
+  driver = redirect
+  data = someone@srv-chasquid
+
+forwardall:
+  driver = accept
+  transport = tochasquid
+
+begin transports
+
+tochasquid:
+  driver = smtp
+
+  # exim4 will by default detect and special-case deliveries to localhost;
+  # this avoids that behaviour and tells it to go ahead anyway.
+  allow_localhost
+  hosts_override
+
+  # chasquid will be listening on localhost:1025
+  hosts = localhost
+  port = 1025
+
+  # Add headers to help debug failures.
+  delivery_date_add
+  envelope_to_add
+  return_path_add
diff --git a/test/t-exim/content b/test/t-exim/content
new file mode 100644
index 0000000..76a8b16
--- /dev/null
+++ b/test/t-exim/content
@@ -0,0 +1,4 @@
+Subject: Prueba desde el test
+
+Crece desde el test el futuro
+Crece desde el test
diff --git a/test/t-exim/get-exim4-debian.sh b/test/t-exim/get-exim4-debian.sh
new file mode 100755
index 0000000..c5cbcb2
--- /dev/null
+++ b/test/t-exim/get-exim4-debian.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# This script downloads the exim4 binary from Debian's package.
+# It assumes "apt" is functional, which means it's not very portable, but
+# given the nature of these tests that's acceptable for now.
+
+set -e
+. $(dirname ${0})/../util/lib.sh
+
+init
+
+# Download and extract the package in .exim-bin
+apt download exim4-daemon-light
+dpkg -x exim4-daemon-light_*.deb $PWD/.exim-bin/
+
+# Create a symlink to .exim4, which is the directory we will use to store
+# configuration, spool, etc.
+# The configuration template will look for it here.
+mkdir -p .exim4
+ln -sf $PWD/.exim-bin/usr/sbin/exim4 .exim4/
+
+# Remove the setuid bit, if there is one - we don't need it and may cause
+# confusion and/or security troubles.
+chmod -s .exim-bin/usr/sbin/exim4
+
+success
+
diff --git a/test/t-exim/hosts b/test/t-exim/hosts
new file mode 100644
index 0000000..a338cd2
--- /dev/null
+++ b/test/t-exim/hosts
@@ -0,0 +1,2 @@
+srv-chasquid localhost
+srv-exim localhost
diff --git a/test/t-exim/msmtprc b/test/t-exim/msmtprc
new file mode 100644
index 0000000..d5e75c1
--- /dev/null
+++ b/test/t-exim/msmtprc
@@ -0,0 +1,14 @@
+account default
+
+host srv-chasquid
+port 1025
+
+tls on
+tls_trust_file config/domains/srv-chasquid/cert.pem
+
+from user@srv-chasquid
+
+auth on
+user user@srv-chasquid
+password secretpassword
+
diff --git a/test/t-exim/run.sh b/test/t-exim/run.sh
new file mode 100755
index 0000000..a9803dc
--- /dev/null
+++ b/test/t-exim/run.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# This test checks that we can send and receive mail to/from exim4.
+#
+# Setup:
+#   - chasquid listening on :1025.
+#   - exim listening on :2025.
+#   - hosts "srv-chasquid" and "srv-exim" pointing back to localhost.
+#   - exim configured to accept all email and forward it to
+#     someone@srv-chasquid.
+#
+# Test:
+#   msmtp --> chasquid --> exim --> chasquid --> local delivery
+#
+#   msmtp will auth as user@srv-chasquid to chasquid, and send an email with
+#   recipient someone@srv-exim.
+#
+#   chasquid will deliver the mail to exim.
+#
+#   exim will deliver the mail back to chasquid (after changing the
+#   destination to someone@chasquid).
+#
+#   chasquid will receive the email from exim, and deliver it locally.
+
+set -e
+. $(dirname ${0})/../util/lib.sh
+
+init
+
+# Create a temporary directory for exim4 to use, and generate the exim4
+# config based on the template.
+mkdir -p .exim4
+EXIMDIR="$PWD/.exim4" envsubst < config/exim4.in > .exim4/config
+
+generate_certs_for srv-chasquid
+
+# Launch chasquid at port 1025 (in config).
+# Use outgoing port 2025 which is where exim will be at.
+# Bypass MX lookup, so it can find srv-exim (via our host alias).
+chasquid -v=2 --log_dir=.logs --config_dir=config \
+	--testing__outgoing_smtp_port=2025 \
+	--testing__bypass_mx_lookup &
+
+wait_until_ready 1025
+
+# Launch exim at port 2025
+.exim4/exim4 -bd -d -C "$PWD/.exim4/config" > .exim4/log 2>&1 &
+wait_until_ready 2025
+
+# msmtp will use chasquid to send an email to someone@srv-exim.
+run_msmtp someone@srv-exim < content
+
+wait_for_file .mail/someone@srv-chasquid
+
+mail_diff content .mail/someone@srv-chasquid
+
+success