nutrition docker file fix

This commit is contained in:
2026-09-30 14:58:30 +05:30
parent c49f5372a5
commit d0804ae84f
8 changed files with 430 additions and 112 deletions

158
utils/mail_test.go Normal file
View File

@@ -0,0 +1,158 @@
package utils
import (
"bufio"
"net"
"strings"
"testing"
"nearle/config"
)
/*
Sending the invitation.
These run against a fake SMTP server on a local port rather than a mock, because
the thing worth testing is the conversation: Go's `net/smtp` decides on its own
whether to hand over a password, and the question is what this code does when a
relay does not offer encryption.
*/
// smtpStub answers just enough of the protocol to get to the interesting part.
// `offerTLS` is the switch the tests turn.
func smtpStub(t *testing.T, offerTLS bool) string {
t.Helper()
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("listen: %v", err)
}
t.Cleanup(func() { _ = listener.Close() })
go func() {
for {
conn, err := listener.Accept()
if err != nil {
return
}
go func() {
defer conn.Close()
reader := bufio.NewReader(conn)
write := func(line string) { _, _ = conn.Write([]byte(line + "\r\n")) }
write("220 stub ESMTP")
for {
line, err := reader.ReadString('\n')
if err != nil {
return
}
switch verb := strings.ToUpper(strings.TrimSpace(line)); {
case strings.HasPrefix(verb, "EHLO"):
write("250-stub")
if offerTLS {
write("250-STARTTLS")
}
write("250 AUTH PLAIN LOGIN")
case strings.HasPrefix(verb, "QUIT"):
write("221 bye")
return
default:
// Anything else is past the point these tests reach.
write("250 ok")
}
}
}()
}
}()
return listener.Addr().String()
}
func mailerFor(t *testing.T, address string, username string) Mailer {
t.Helper()
host, portText, err := net.SplitHostPort(address)
if err != nil {
t.Fatalf("splitting %q: %v", address, err)
}
port := 0
for _, digit := range portText {
port = port*10 + int(digit-'0')
}
mailer, err := NewMailer(config.MailConfig{
Host: host, Port: port,
Username: username,
Password: "a-password-that-must-not-cross-the-wire",
FromAddress: "care@nearledaily.com", FromName: "Nearle",
ConsoleURL: "https://app.nearledaily.com",
})
if err != nil {
t.Fatalf("building the mailer: %v", err)
}
if mailer == nil {
t.Fatal("no mailer from a configured sender")
}
return mailer
}
func TestAPasswordIsNeverSentToARelayWithNoTLS(t *testing.T) {
// The downgrade this guards. An attacker between us and the relay can strip
// STARTTLS from the greeting; "carry on unencrypted" is the wrong answer,
// and we are about to send a real Google app password.
mailer := mailerFor(t, smtpStub(t, false), "care@nearledaily.com")
err := mailer.Send("owner@rmart.example", "Set your Nearle password", "link")
if err == nil {
t.Fatal("sent credentials to a relay offering no encryption")
}
if !strings.Contains(err.Error(), "TLS") {
// The reason has to name the connection. Reported as a credential
// refusal it sends somebody to check the password, which is fine.
t.Errorf("the failure does not name the real problem: %v", err)
}
if strings.Contains(err.Error(), "a-password-that-must-not-cross-the-wire") {
t.Error("the password is in the error message")
}
}
func TestARelayWithNoCredentialsIsLeftAlone(t *testing.T) {
// A relay that authenticates by network rather than by password is usually
// a local MTA on the same host, where there is no wire to protect. It must
// not be refused for want of TLS it does not need.
mailer := mailerFor(t, smtpStub(t, false), "")
// The stub accepts the envelope and the body, so this gets past the point
// the guard above would have stopped at. Whether the stub completes the
// whole conversation is not the question — being refused for TLS is.
err := mailer.Send("owner@rmart.example", "Set your Nearle password", "link")
if err != nil && strings.Contains(err.Error(), "does not offer TLS") {
t.Fatalf("refused an unauthenticated relay over TLS: %v", err)
}
}
func TestAnUnconfiguredMailerIsNilRatherThanBroken(t *testing.T) {
// A deployment with no mail still boots and still onboards; the outcome
// says `invited: false` with the reason. See config.MailConfig.Why.
mailer, err := NewMailer(config.MailConfig{})
if err != nil {
t.Fatalf("an unconfigured mailer reported an error: %v", err)
}
if mailer != nil {
t.Fatal("built a mailer with no host")
}
}
func TestABadRecipientIsNamedRatherThanDialled(t *testing.T) {
// A merchant's primary email is typed by whoever onboarded them, so a typo
// is ordinary. It should be refused by name, before any connection.
mailer := mailerFor(t, smtpStub(t, true), "care@nearledaily.com")
err := mailer.Send("not an email", "Set your Nearle password", "link")
if err == nil {
t.Fatal("accepted an address that is not one")
}
if !strings.Contains(err.Error(), "not a valid email address") {
t.Errorf("unhelpful message: %v", err)
}
}