131 lines
2.9 KiB
Go
131 lines
2.9 KiB
Go
package mailer
|
|
|
|
import (
|
|
"bufio"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSendFailsWhenConfigMissing(t *testing.T) {
|
|
t.Setenv("EMAIL_HOST", "")
|
|
t.Setenv("EMAIL_PORT", "")
|
|
t.Setenv("EMAIL_FROM", "")
|
|
|
|
if err := Send("user@example.com", "subj", "body"); err == nil {
|
|
t.Fatal("expected error for incomplete email config")
|
|
}
|
|
}
|
|
|
|
func TestSendPlainSMTP(t *testing.T) {
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("failed to listen: %v", err)
|
|
}
|
|
defer ln.Close()
|
|
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
conn, err := ln.Accept()
|
|
if err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
r := bufio.NewReader(conn)
|
|
w := bufio.NewWriter(conn)
|
|
write := func(s string) error {
|
|
if _, err := w.WriteString(s); err != nil {
|
|
return err
|
|
}
|
|
return w.Flush()
|
|
}
|
|
|
|
if err := write("220 localhost Simple Mail Transfer Service Ready\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
|
|
for {
|
|
line, err := r.ReadString('\n')
|
|
if err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
cmd := strings.TrimSpace(line)
|
|
|
|
switch {
|
|
case strings.HasPrefix(strings.ToUpper(cmd), "EHLO") || strings.HasPrefix(strings.ToUpper(cmd), "HELO"):
|
|
if err := write("250-localhost\r\n250 AUTH PLAIN\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
case strings.HasPrefix(strings.ToUpper(cmd), "MAIL FROM"):
|
|
if err := write("250 OK\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
case strings.HasPrefix(strings.ToUpper(cmd), "RCPT TO"):
|
|
if err := write("250 OK\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
case strings.HasPrefix(strings.ToUpper(cmd), "DATA"):
|
|
if err := write("354 End data with <CR><LF>.<CR><LF>\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
for {
|
|
d, err := r.ReadString('\n')
|
|
if err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
if strings.TrimSpace(d) == "." {
|
|
break
|
|
}
|
|
}
|
|
if err := write("250 OK queued\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
case strings.HasPrefix(strings.ToUpper(cmd), "QUIT"):
|
|
_ = write("221 Bye\r\n")
|
|
done <- nil
|
|
return
|
|
default:
|
|
if err := write("250 OK\r\n"); err != nil {
|
|
done <- err
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
host, portStr, err := net.SplitHostPort(ln.Addr().String())
|
|
if err != nil {
|
|
t.Fatalf("failed to parse listener address: %v", err)
|
|
}
|
|
if _, err := strconv.Atoi(portStr); err != nil {
|
|
t.Fatalf("invalid test smtp port: %v", err)
|
|
}
|
|
|
|
t.Setenv("EMAIL_HOST", host)
|
|
t.Setenv("EMAIL_PORT", portStr)
|
|
t.Setenv("EMAIL_FROM", "noreply@example.com")
|
|
t.Setenv("EMAIL_HOST_USER", "")
|
|
t.Setenv("EMAIL_HOST_PASSWORD", "")
|
|
t.Setenv("EMAIL_USE_TLS", "false")
|
|
t.Setenv("EMAIL_USE_SSL", "false")
|
|
|
|
if err := Send("user@example.com", "Verify", "Hello"); err != nil {
|
|
t.Fatalf("expected send success, got error: %v", err)
|
|
}
|
|
|
|
if err := <-done; err != nil {
|
|
t.Fatalf("smtp server finished with error: %v", err)
|
|
}
|
|
}
|