Name no node: mailu's and mesh-mail's test domain becomes example.org (issue 1838)
This commit is contained in:
@@ -17,10 +17,10 @@ import (
|
||||
// The environment mailu gives automx on node-c when the fixtures were captured (files/mailu.env): the mail domain,
|
||||
// the route name for both servers, the ports.
|
||||
var capturedEnvironment = map[string]string{
|
||||
"AMX_MAIL_DOMAINS": "node-c.be",
|
||||
"AMX_IMAP_ADDRESS": "mail.node-c.be",
|
||||
"AMX_MAIL_DOMAINS": "example.org",
|
||||
"AMX_IMAP_ADDRESS": "mail.example.org",
|
||||
"AMX_IMAP_PORT": "143",
|
||||
"AMX_SMTP_ADDRESS": "mail.node-c.be",
|
||||
"AMX_SMTP_ADDRESS": "mail.example.org",
|
||||
"AMX_SMTP_PORT": "587",
|
||||
"AUTOMX_PORT": "4243",
|
||||
}
|
||||
@@ -176,7 +176,7 @@ func TestTheOnlyCorrectedAnswerIsTheImapServersName(t *testing.T) {
|
||||
}
|
||||
for _, c := range corrected {
|
||||
orig := readFile(t, strings.TrimSuffix(c, ".corrected.body")+".body")
|
||||
want := strings.Replace(orig, "<hostname />", "<hostname>mail.node-c.be</hostname>", 1)
|
||||
want := strings.Replace(orig, "<hostname />", "<hostname>mail.example.org</hostname>", 1)
|
||||
if strings.Contains(want, "<hostname />") || want == orig {
|
||||
t.Fatalf("%s: the capture has no single empty hostname to correct", c)
|
||||
}
|
||||
@@ -198,12 +198,12 @@ func TestTheImapServerIsNamedFromTheImapAddress(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rec := httptest.NewRecorder()
|
||||
newHandler(cfg).ServeHTTP(rec, httptest.NewRequest("GET", "/mail/config-v1.1.xml?emailaddress=a@node-c.be", nil))
|
||||
newHandler(cfg).ServeHTTP(rec, httptest.NewRequest("GET", "/mail/config-v1.1.xml?emailaddress=a@example.org", nil))
|
||||
body := rec.Body.String()
|
||||
if !strings.Contains(body, `<incomingServer type="imap"><hostname>imap.example.test</hostname><port>993</port>`) {
|
||||
t.Errorf("incoming server not named from AMX_IMAP_ADDRESS and AMX_IMAP_PORT: %s", body)
|
||||
}
|
||||
if !strings.Contains(body, `<outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port>`) {
|
||||
if !strings.Contains(body, `<outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port>`) {
|
||||
t.Errorf("outgoing server changed: %s", body)
|
||||
}
|
||||
}
|
||||
@@ -213,13 +213,13 @@ func TestEveryDomainOfTheEnvironmentIsServed(t *testing.T) {
|
||||
for k, v := range capturedEnvironment {
|
||||
env[k] = v
|
||||
}
|
||||
env["AMX_MAIL_DOMAINS"] = "node-c.be, example.test"
|
||||
env["AMX_MAIL_DOMAINS"] = "example.org, example.test"
|
||||
cfg, err := configFrom(getenvOf(env))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := newHandler(cfg)
|
||||
for _, d := range []string{"node-c.be", "example.test"} {
|
||||
for _, d := range []string{"example.org", "example.test"} {
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, httptest.NewRequest("GET", "/mail/config-v1.1.xml?emailaddress=a@"+d, nil))
|
||||
if rec.Code != 200 || !strings.Contains(rec.Body.String(), "<domain>"+d+"</domain>") {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>node-c.be</domain><displayName>node-c.be</displayName><displayShortName>node-c.be</displayShortName><incomingServer type="imap"><hostname /><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>example.org</domain><displayName>example.org</displayName><displayShortName>example.org</displayShortName><incomingServer type="imap"><hostname /><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>node-c.be</domain><displayName>node-c.be</displayName><displayShortName>node-c.be</displayShortName><incomingServer type="imap"><hostname>mail.node-c.be</hostname><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>example.org</domain><displayName>example.org</displayName><displayShortName>example.org</displayShortName><incomingServer type="imap"><hostname>mail.example.org</hostname><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
Content-Length: 612
|
||||
Content-Length: 624
|
||||
Content-Type: application/xml
|
||||
Server: Werkzeug/3.1.9 Python/3.9.5
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
GET https://autoconfig.node-c.be/mail/config-v1.1.xml?emailaddress=jochen@node-c.be
|
||||
GET https://autoconfig.example.org/mail/config-v1.1.xml?emailaddress=jochen@example.org
|
||||
User-Agent: Thunderbird
|
||||
Accept: */*
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>node-c.be</domain><displayName>node-c.be</displayName><displayShortName>node-c.be</displayShortName><incomingServer type="imap"><hostname /><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>example.org</domain><displayName>example.org</displayName><displayShortName>example.org</displayShortName><incomingServer type="imap"><hostname /><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>node-c.be</domain><displayName>node-c.be</displayName><displayShortName>node-c.be</displayShortName><incomingServer type="imap"><hostname>mail.node-c.be</hostname><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>example.org</domain><displayName>example.org</displayName><displayShortName>example.org</displayShortName><incomingServer type="imap"><hostname>mail.example.org</hostname><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
Content-Length: 612
|
||||
Content-Length: 624
|
||||
Content-Type: application/xml
|
||||
Server: Werkzeug/3.1.9 Python/3.9.5
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://automx.node-c.be/mail/config-v1.1.xml?emailaddress=jochen@node-c.be
|
||||
GET https://automx.example.org/mail/config-v1.1.xml?emailaddress=jochen@example.org
|
||||
User-Agent: Thunderbird
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>node-c.be</domain><displayName>node-c.be</displayName><displayShortName>node-c.be</displayShortName><incomingServer type="imap"><hostname /><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>example.org</domain><displayName>example.org</displayName><displayShortName>example.org</displayShortName><incomingServer type="imap"><hostname /><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>node-c.be</domain><displayName>node-c.be</displayName><displayShortName>node-c.be</displayShortName><incomingServer type="imap"><hostname>mail.node-c.be</hostname><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.node-c.be</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
<clientConfig version="1.1"><emailProvider id="automx2-1"><identity /><domain>example.org</domain><displayName>example.org</displayName><displayShortName>example.org</displayShortName><incomingServer type="imap"><hostname>mail.example.org</hostname><port>143</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></incomingServer><outgoingServer type="smtp"><hostname>mail.example.org</hostname><port>587</port><socketType>STARTTLS</socketType><username>%EMAILADDRESS%</username><authentication>password-cleartext</authentication></outgoingServer></emailProvider></clientConfig>
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
Content-Length: 612
|
||||
Content-Length: 624
|
||||
Content-Type: application/xml
|
||||
Server: Werkzeug/3.1.9 Python/3.9.5
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://autodiscover.node-c.be/mail/config-v1.1.xml?emailaddress=jochen@node-c.be
|
||||
GET https://autodiscover.example.org/mail/config-v1.1.xml?emailaddress=jochen@example.org
|
||||
User-Agent: Thunderbird
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://autoconfig.node-c.be/mail/config-v1.1.xml?emailaddress=nobody@unknown.example
|
||||
GET https://autoconfig.example.org/mail/config-v1.1.xml?emailaddress=nobody@unknown.example
|
||||
User-Agent: Thunderbird
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://autoconfig.node-c.be/mail/config-v1.1.xml
|
||||
GET https://autoconfig.example.org/mail/config-v1.1.xml
|
||||
User-Agent: Thunderbird
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
GET https://autoconfig.node-c.be/
|
||||
GET https://autoconfig.example.org/
|
||||
User-Agent: Mozilla/5.0
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
GET https://autoconfig.node-c.be/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=jochen@node-c.be
|
||||
GET https://autoconfig.example.org/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=jochen@example.org
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml
|
||||
POST https://autodiscover.example.org/autodiscover/autodiscover.xml
|
||||
User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.14326; Pro)
|
||||
Content-Type: text/xml
|
||||
Accept: */*
|
||||
@@ -6,7 +6,7 @@ Accept: */*
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
|
||||
<Request>
|
||||
<EMailAddress>jochen@node-c.be</EMailAddress>
|
||||
<EMailAddress>jochen@example.org</EMailAddress>
|
||||
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
|
||||
</Request>
|
||||
</Autodiscover>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml
|
||||
POST https://autodiscover.example.org/autodiscover/autodiscover.xml
|
||||
User-Agent: Microsoft Office/16.0
|
||||
Content-Type: text/xml
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml
|
||||
POST https://autodiscover.example.org/autodiscover/autodiscover.xml
|
||||
User-Agent: Microsoft Office/16.0
|
||||
Content-Type: text/xml
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml
|
||||
POST https://autodiscover.example.org/autodiscover/autodiscover.xml
|
||||
User-Agent: Microsoft Office/16.0
|
||||
Content-Type: text/xml
|
||||
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://autodiscover.node-c.be/autodiscover/autodiscover.xml
|
||||
GET https://autodiscover.example.org/autodiscover/autodiscover.xml
|
||||
User-Agent: Microsoft Office/16.0
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
POST https://autodiscover.node-c.be/Autodiscover/Autodiscover.xml
|
||||
POST https://autodiscover.example.org/Autodiscover/Autodiscover.xml
|
||||
User-Agent: Microsoft Office/16.0
|
||||
Content-Type: text/xml
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"><Request><EMailAddress>jochen@node-c.be</EMailAddress><AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema></Request></Autodiscover>
|
||||
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"><Request><EMailAddress>jochen@example.org</EMailAddress><AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema></Request></Autodiscover>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
<html lang=en>
|
||||
<title>Redirecting...</title>
|
||||
<h1>Redirecting...</h1>
|
||||
<p>You should be redirected automatically to the target URL: <a href="https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be">https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be</a>. If not, click the link.
|
||||
<p>You should be redirected automatically to the target URL: <a href="https://automx.example.org/mobileconfig/?emailaddress=jochen@example.org">https://automx.example.org/mobileconfig/?emailaddress=jochen@example.org</a>. If not, click the link.
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
Content-Length: 323
|
||||
Content-Length: 331
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Location: https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be
|
||||
Location: https://automx.example.org/mobileconfig/?emailaddress=jochen@example.org
|
||||
Server: Werkzeug/3.1.9 Python/3.9.5
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
GET https://automx.node-c.be/mobileconfig?emailaddress=jochen@node-c.be
|
||||
GET https://automx.example.org/mobileconfig?emailaddress=jochen@example.org
|
||||
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) Safari
|
||||
Accept: */*
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
GET https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be
|
||||
GET https://automx.example.org/mobileconfig/?emailaddress=jochen@example.org
|
||||
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) Safari
|
||||
Accept: */*
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://automx.node-c.be/mobileconfig/?emailaddress=nobody@unknown.example
|
||||
GET https://automx.example.org/mobileconfig/?emailaddress=nobody@unknown.example
|
||||
User-Agent: Mozilla/5.0 (iPhone)
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
GET https://automx.node-c.be/mobileconfig/
|
||||
GET https://automx.example.org/mobileconfig/
|
||||
User-Agent: Mozilla/5.0 (iPhone)
|
||||
|
||||
+4
-4
@@ -2,9 +2,9 @@ What mailu's autoconfiguration module (automx2 2021.6, container mailu-automx on
|
||||
answers to the requests mail clients make (R4d step AMX-1, issue 1630, ADR 0480).
|
||||
|
||||
Captured 2026-10-21 between 13:58:25 and 13:58:52 (CEST; the Date headers said 11:58 GMT) with the mesh tool
|
||||
node-d/netcheck.netcheck_request, called from node-d, through the names clients use (autoconfig.node-c.be,
|
||||
autodiscover.node-c.be, automx.node-c.be: HTTPS, the mesh's route), no ssh. A redirect is reported, never followed.
|
||||
Mail domain served: node-c.be. Mailbox used: jochen@node-c.be; unknown domain: nobody@unknown.example.
|
||||
node-d/netcheck.netcheck_request, called from node-d, through the names clients use (autoconfig.example.org,
|
||||
autodiscover.example.org, automx.example.org: HTTPS, the mesh's route), no ssh. A redirect is reported, never followed.
|
||||
Mail domain served: example.org. Mailbox used: jochen@example.org; unknown domain: nobody@unknown.example.
|
||||
|
||||
Each capture is four files with the same stem:
|
||||
<stem>.request method and URL, then the request headers sent, then (after a blank line) the body sent
|
||||
@@ -24,7 +24,7 @@ A fixture is not the bytes on the wire in four ways (issue 1701):
|
||||
What the answers show (read, not guessed):
|
||||
- GET /mail/config-v1.1.xml?emailaddress=... answers 200 application/xml on all three names; same body on each.
|
||||
- The incoming (IMAP) server has an EMPTY hostname (<hostname />), port 143, STARTTLS. The outgoing server is
|
||||
mail.node-c.be:587 STARTTLS. Cause (from reading the module, not from the database): automx/files/add-domains:35
|
||||
mail.example.org:587 STARTTLS. Cause (from reading the module, not from the database): automx/files/add-domains:35
|
||||
reads AMX_IMAP_SERVER, files/mailu.env:58 sets AMX_IMAP_ADDRESS, so the IMAP name was never written.
|
||||
A client given this answer cannot find its IMAP server.
|
||||
- POST /autodiscover/autodiscover.xml with a valid request for the served domain answers 500 (the Outlook
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ whole list of where the two differ.
|
||||
server because its setup script read AMX_IMAP_SERVER, which mailu's environment does not set (it sets
|
||||
AMX_IMAP_ADDRESS). The program names it from AMX_IMAP_ADDRESS (and the port from AMX_IMAP_PORT).
|
||||
Fixtures 01, 02 and 03 each have a <stem>.corrected.body: the capture with <hostname /> replaced by
|
||||
<hostname>mail.node-c.be</hostname> and nothing else (a test checks that). Their Content-Length is that file's
|
||||
size, 634, not the captured 612.
|
||||
<hostname>mail.example.org</hostname> and nothing else (a test checks that). Their Content-Length is that file's
|
||||
size, 649, not the captured 624.
|
||||
|
||||
2. The Server header. The capture has "Server: Werkzeug/3.1.9 Python/3.9.5". The program sends no Server header, and
|
||||
Date, which the captured .headers leave out, is sent as net/http sends it.
|
||||
|
||||
@@ -161,8 +161,8 @@ func TestMailSenderAcceptanceAnApprovedSendIsSentOnceAndSaidOnce(t *testing.T) {
|
||||
|
||||
dir := t.TempDir()
|
||||
accountsPath := filepath.Join(dir, "accounts.json")
|
||||
writeFile(t, accountsPath, `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@node-c.be",
|
||||
"incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"},
|
||||
writeFile(t, accountsPath, `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@example.org",
|
||||
"incoming": {"host": "mail.example.org", "port": 993, "security": "tls"},
|
||||
"outgoing": {"host": "127.0.0.1", "port": 1, "security": "tls"}}}}`)
|
||||
writeFile(t, filepath.Join(dir, "mail-credential-mesh.secret"), "the-password\n")
|
||||
|
||||
@@ -209,7 +209,7 @@ func TestMailSenderAcceptanceAnApprovedSendIsSentOnceAndSaidOnce(t *testing.T) {
|
||||
if got.to[0] != "ops@example.org" {
|
||||
t.Fatalf("received: %+v", got)
|
||||
}
|
||||
if !strings.Contains(got.data, "Message-Id: <"+req.ID+"@node-c.be>") {
|
||||
if !strings.Contains(got.data, "Message-Id: <"+req.ID+"@example.org>") {
|
||||
t.Fatalf("the mail's Message-ID does not name the send: %s", got.data)
|
||||
}
|
||||
|
||||
@@ -238,8 +238,8 @@ func TestMailSenderAcceptanceARefusedSignInFailsAfterItsAttemptsAndNothingIsRece
|
||||
|
||||
dir := t.TempDir()
|
||||
accountsPath := filepath.Join(dir, "accounts.json")
|
||||
writeFile(t, accountsPath, `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@node-c.be",
|
||||
"incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"},
|
||||
writeFile(t, accountsPath, `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@example.org",
|
||||
"incoming": {"host": "mail.example.org", "port": 993, "security": "tls"},
|
||||
"outgoing": {"host": "127.0.0.1", "port": 1, "security": "tls"}}}}`)
|
||||
writeFile(t, filepath.Join(dir, "mail-credential-mesh.secret"), "the-wrong-password\n")
|
||||
|
||||
|
||||
@@ -44,14 +44,14 @@ func mustNotBeRefused(t *testing.T, a asks.Ask) {
|
||||
}
|
||||
|
||||
// (1) A recipient that is one of the operator's own mesh-mail accounts (sendTestBundle's "mesh", address
|
||||
// jschoubben@node-c.be) is named by the account's name alone: the ask carries no mail address at all, and
|
||||
// jschoubben@example.org) is named by the account's name alone: the ask carries no mail address at all, and
|
||||
// passes the real content rule. This is the first test issue 868's decision asked for; it fails today
|
||||
// because AskMailSend puts the raw address into the ask.
|
||||
func TestMailSendAskForOwnAccountRecipientCarriesNoAddress(t *testing.T) {
|
||||
b, router, _ := sendTestBundle(t, Server{Host: "127.0.0.1", Port: 25, Security: "tls"})
|
||||
rt := startBundle(t, b.Tools())
|
||||
|
||||
args := map[string]any{"account": "mesh", "to": []any{"jschoubben@node-c.be"},
|
||||
args := map[string]any{"account": "mesh", "to": []any{"jschoubben@example.org"},
|
||||
"subject": "Testing issue 868", "body": "Does the ask reach the operator now?"}
|
||||
text, isErr := rt.call(SendTool, "node-c.triage", args)
|
||||
if isErr {
|
||||
@@ -198,7 +198,7 @@ func TestMailSendAskMatchesADisplayNameRecipientByItsAddress(t *testing.T) {
|
||||
b, router, _ := sendTestBundle(t, Server{Host: "127.0.0.1", Port: 25, Security: "tls"})
|
||||
rt := startBundle(t, b.Tools())
|
||||
|
||||
args := map[string]any{"account": "mesh", "to": []any{"Jochen Schoubben <jschoubben@node-c.be>"},
|
||||
args := map[string]any{"account": "mesh", "to": []any{"Jochen Schoubben <jschoubben@example.org>"},
|
||||
"subject": "Testing a display name", "body": "body"}
|
||||
text, isErr := rt.call(SendTool, "node-c.triage", args)
|
||||
if isErr {
|
||||
|
||||
@@ -12,16 +12,16 @@ import (
|
||||
|
||||
// The first stage's account, as the operator sets the setting `accounts` (ADR 0359 §5): its address and its server,
|
||||
// never a credential; its password is the own secret mail-credential-mesh.
|
||||
const stageOne = `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@node-c.be",
|
||||
"incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"}}}}`
|
||||
const stageOne = `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@example.org",
|
||||
"incoming": {"host": "mail.example.org", "port": 993, "security": "tls"}}}}`
|
||||
|
||||
func TestTheFirstStagesAccountIsReadAndItsSecretNamed(t *testing.T) {
|
||||
got, err := ParseAccounts([]byte(stageOne))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(got) != 1 || got[0].Name != "mesh" || got[0].Kind != KindIMAP || got[0].SignInAs() != "jschoubben@node-c.be" ||
|
||||
got[0].Incoming.Address() != "mail.node-c.be:993" || got[0].Secret() != "mail-credential-mesh" || got[0].Outgoing != nil {
|
||||
if len(got) != 1 || got[0].Name != "mesh" || got[0].Kind != KindIMAP || got[0].SignInAs() != "jschoubben@example.org" ||
|
||||
got[0].Incoming.Address() != "mail.example.org:993" || got[0].Secret() != "mail-credential-mesh" || got[0].Outgoing != nil {
|
||||
t.Fatalf("%+v", got)
|
||||
}
|
||||
if p := secret.Path("/state", got[0].Secret()); p != "/state/mail-credential-mesh.secret" {
|
||||
@@ -34,7 +34,7 @@ func TestTheFirstStagesAccountIsReadAndItsSecretNamed(t *testing.T) {
|
||||
// uses to send through it (novox/hq ADR 0361 §1).
|
||||
func TestASecondIMAPAccountIsConfigurationOnly(t *testing.T) {
|
||||
got, err := ParseAccounts([]byte(`{"accounts": {
|
||||
"mesh": {"kind": "imap", "address": "jschoubben@node-c.be", "incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"}},
|
||||
"mesh": {"kind": "imap", "address": "jschoubben@example.org", "incoming": {"host": "mail.example.org", "port": 993, "security": "tls"}},
|
||||
"gmail": {"kind": "imap", "address": "someone@gmail.com", "incoming": {"host": "imap.gmail.com", "port": 993, "security": "tls"},
|
||||
"outgoing": {"host": "smtp.gmail.com", "port": 465, "security": "tls"}, "folders": ["[Gmail]/Sent Mail"]}}}`))
|
||||
if err != nil {
|
||||
|
||||
@@ -52,7 +52,7 @@ func (m *memMirrorState) Keys() ([]string, error) {
|
||||
// accountsAndStore is one account "mesh", granted no caller (the Mirror reads no grant), with the index given.
|
||||
func accountsAndStore(t *testing.T) ([]Account, *memStore) {
|
||||
t.Helper()
|
||||
return []Account{{Name: "mesh", Kind: KindIMAP, Address: "jschoubben@node-c.be"}}, newMemStore()
|
||||
return []Account{{Name: "mesh", Kind: KindIMAP, Address: "jschoubben@example.org"}}, newMemStore()
|
||||
}
|
||||
|
||||
func mirrorOf(accounts []Account, st *memStore, bucket MirrorState) *Mirror {
|
||||
@@ -147,7 +147,7 @@ func TestMirrorRoundWritesNothingWhenUnchanged(t *testing.T) {
|
||||
func TestMirrorRoundWritesOnlyTheChangedAccountsKey(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
accounts, st := accountsAndStore(t)
|
||||
accounts = append(accounts, Account{Name: "other", Kind: KindIMAP, Address: "other@node-c.be"})
|
||||
accounts = append(accounts, Account{Name: "other", Kind: KindIMAP, Address: "other@example.org"})
|
||||
_ = st.SetState(ctx, AccountState{Account: "mesh", State: AccountCurrent})
|
||||
_ = st.SetState(ctx, AccountState{Account: "other", State: AccountCurrent})
|
||||
addMail(t, st, "mesh", "INBOX", 1, []string{})
|
||||
|
||||
@@ -29,66 +29,66 @@ func searchFixtures() []Message {
|
||||
return []Message{
|
||||
// mesh/INBOX ------------------------------------------------------------------------------------------------
|
||||
{Account: "mesh", Folder: "INBOX", UID: 1, MessageID: "<invoice1@mesh>", Subject: "October invoice",
|
||||
Date: at(9, 0), From: []Person{{Name: "Bob", Address: "bob@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(9, 0), From: []Person{{Name: "Bob", Address: "bob@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{{Bucket: "mail", Key: "a1", Size: 1200, Type: "application/pdf", Name: "invoice.pdf"}},
|
||||
Body: "please settle the invoice, due at month end", Size: 1500},
|
||||
{Account: "mesh", Folder: "INBOX", UID: 2, MessageID: "<renov1@mesh>", Subject: "renovatie plannen",
|
||||
Date: time.Date(2026, 9, 1, 8, 0, 0, 0, time.UTC), From: []Person{{Name: "Alice", Address: "alice@example.org"}},
|
||||
To: []Person{{Address: "bob@example.org"}}, Cc: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
To: []Person{{Address: "bob@example.org"}}, Cc: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{}, Body: "over de renovatie van de keuken", Size: 900},
|
||||
{Account: "mesh", Folder: "INBOX", UID: 3, MessageID: "<renov2@mesh>", Subject: "renovatie herinnering",
|
||||
Date: time.Date(2026, 9, 2, 8, 0, 0, 0, time.UTC), From: []Person{{Name: "Alice", Address: "alice@example.org"}},
|
||||
To: []Person{{Address: "jschoubben@node-c.be"}}, Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{},
|
||||
To: []Person{{Address: "jschoubben@example.org"}}, Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{},
|
||||
Body: "nog een vraag over de renovatie", Size: 800},
|
||||
{Account: "mesh", Folder: "INBOX", UID: 4, MessageID: "<sec1@mesh>", Subject: "security alert",
|
||||
Date: time.Date(2026, 10, 15, 7, 0, 0, 0, time.UTC), From: []Person{{Name: "Carol", Address: "carol@google.com"}},
|
||||
To: []Person{{Address: "jschoubben@node-c.be"}}, Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{},
|
||||
To: []Person{{Address: "jschoubben@example.org"}}, Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{},
|
||||
Body: "someone logged into your account from a new device", Size: 600},
|
||||
{Account: "mesh", Folder: "INBOX", UID: 5, MessageID: "<cal1@mesh>", Subject: "team meeting invite",
|
||||
Date: at(8, 0), From: []Person{{Name: "Dave", Address: "dave@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(8, 0), From: []Person{{Name: "Dave", Address: "dave@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{{Bucket: "mail", Key: "a2", Size: 300, Type: "text/calendar", Name: "meeting.ics"}},
|
||||
Body: "please join the planning meeting", Size: 700},
|
||||
{Account: "mesh", Folder: "INBOX", UID: 6, MessageID: "<reply1@mesh>", InReplyTo: "<sent1@mesh>", Subject: "Re: quick note",
|
||||
Date: at(12, 30), From: []Person{{Name: "Bob", Address: "bob@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(12, 30), From: []Person{{Name: "Bob", Address: "bob@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{}, Body: "sounds good, thanks for the note", Size: 400},
|
||||
// 1229/AC5: from a domain (google.com), has-attachment, name *.pdf and the word "factuur" — in the
|
||||
// subject only (review round 1 finding 3), so Words's "subject or body" is genuinely exercised, not
|
||||
// merely a body match that would pass even with a subject-only bug.
|
||||
{Account: "mesh", Folder: "INBOX", UID: 7, MessageID: "<factuur1@mesh>", Subject: "the factuur for Q3",
|
||||
Date: at(13, 0), From: []Person{{Name: "Erik", Address: "erik@google.com"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(13, 0), From: []Person{{Name: "Erik", Address: "erik@google.com"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{{Bucket: "mail", Key: "a4", Size: 200, Type: "application/pdf", Name: "factuur.pdf"}},
|
||||
Body: "see the attached file, due on receipt", Size: 850},
|
||||
// 1229/AC12: a word with digits and a dash ("4711-882"), matched whole, in the subject only (review
|
||||
// round 1 finding 3).
|
||||
{Account: "mesh", Folder: "INBOX", UID: 8, MessageID: "<order1@mesh>", Subject: "order 4711-882 confirmed",
|
||||
Date: at(14, 0), From: []Person{{Address: "ops@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(14, 0), From: []Person{{Address: "ops@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{}, Body: "your order has shipped", Size: 300},
|
||||
// Control for 1229/AC12: "4711" and "882" appear as separate tokens, never hyphenated together.
|
||||
{Account: "mesh", Folder: "INBOX", UID: 9, MessageID: "<order2@mesh>", Subject: "order 4711 shipped, item 882 noted",
|
||||
Date: at(14, 5), From: []Person{{Address: "ops@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(14, 5), From: []Person{{Address: "ops@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{}, Body: "item 4711 and item 882 are unrelated", Size: 300},
|
||||
// 1229/AC15 (the "any" word list): only "verzekering" is present, not "schade" — in the subject only
|
||||
// (review round 1 finding 3) — with an attachment.
|
||||
{Account: "mesh", Folder: "INBOX", UID: 10, MessageID: "<polis1@mesh>", Subject: "verzekering aanvraag",
|
||||
Date: at(14, 10), From: []Person{{Address: "broker@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: at(14, 10), From: []Person{{Address: "broker@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{{Bucket: "mail", Key: "a5", Size: 150, Type: "application/pdf", Name: "polis.pdf"}},
|
||||
Body: "nieuwe polis aanvraag", Size: 450},
|
||||
|
||||
// mesh/Sent ---------------------------------------------------------------------------------------------------
|
||||
{Account: "mesh", Folder: "Sent", UID: 1, MessageID: "<sentreply1@mesh>", InReplyTo: "<invoice1@mesh>", Subject: "Re: October invoice",
|
||||
Date: at(10, 0), From: []Person{{Address: "jschoubben@node-c.be"}}, To: []Person{{Address: "bob@example.org"}},
|
||||
Date: at(10, 0), From: []Person{{Address: "jschoubben@example.org"}}, To: []Person{{Address: "bob@example.org"}},
|
||||
Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{}, Body: "paid, thank you", Size: 300},
|
||||
{Account: "mesh", Folder: "Sent", UID: 2, MessageID: "<sent1@mesh>", Subject: "quick note",
|
||||
Date: time.Date(2026, 10, 18, 9, 0, 0, 0, time.UTC), From: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: time.Date(2026, 10, 18, 9, 0, 0, 0, time.UTC), From: []Person{{Address: "jschoubben@example.org"}},
|
||||
To: []Person{{Address: "bob@example.org"}}, Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{}, Body: "just checking in", Size: 250},
|
||||
|
||||
// mesh/Junk ---------------------------------------------------------------------------------------------------
|
||||
{Account: "mesh", Folder: "Junk", UID: 1, MessageID: "<junk1@mesh>", Subject: "special offer just for you",
|
||||
Date: time.Date(2026, 10, 10, 6, 0, 0, 0, time.UTC), From: []Person{{Address: "bob@example.org"}},
|
||||
To: []Person{{Address: "jschoubben@node-c.be"}}, Flags: []string{}, Attachments: []AttachmentRef{}, Body: "buy now and save big", Size: 500},
|
||||
To: []Person{{Address: "jschoubben@example.org"}}, Flags: []string{}, Attachments: []AttachmentRef{}, Body: "buy now and save big", Size: 500},
|
||||
{Account: "mesh", Folder: "Junk", UID: 2, MessageID: "<junk2@mesh>", Subject: "you won the lottery",
|
||||
Date: time.Date(2026, 10, 10, 6, 5, 0, 0, time.UTC), From: []Person{{Address: "spam@unknown.com"}},
|
||||
To: []Person{{Address: "jschoubben@node-c.be"}}, Flags: []string{}, Attachments: []AttachmentRef{}, Body: "claim your prize now", Size: 500},
|
||||
To: []Person{{Address: "jschoubben@example.org"}}, Flags: []string{}, Attachments: []AttachmentRef{}, Body: "claim your prize now", Size: 500},
|
||||
|
||||
// gmail/INBOX -------------------------------------------------------------------------------------------------
|
||||
{Account: "gmail", Folder: "INBOX", UID: 1, MessageID: "<gsec1@gmail>", Subject: "security alert for your account",
|
||||
@@ -134,7 +134,7 @@ func searchFixtures() []Message {
|
||||
// mesh/Junk (review round 1 finding 2): someone@example.org, written to only by gmail's Sent, not mesh's.
|
||||
{Account: "mesh", Folder: "Junk", UID: 3, MessageID: "<junk3@mesh>", Subject: "a gmail contact's junk mail",
|
||||
Date: time.Date(2026, 10, 11, 6, 0, 0, 0, time.UTC), From: []Person{{Address: "someone@example.org"}},
|
||||
To: []Person{{Address: "jschoubben@node-c.be"}}, Flags: []string{}, Attachments: []AttachmentRef{}, Body: "unrelated offer", Size: 500},
|
||||
To: []Person{{Address: "jschoubben@example.org"}}, Flags: []string{}, Attachments: []AttachmentRef{}, Body: "unrelated offer", Size: 500},
|
||||
|
||||
// gmail/Junk (review round 1 finding 1): the same someone@example.org, but here it is gmail's own
|
||||
// account, whose "[Gmail]/Sent Mail" did write to this address — so this one must match.
|
||||
@@ -242,7 +242,7 @@ func TestSearchFiltersByCcNotTo(t *testing.T) {
|
||||
eachStore(t, func(t *testing.T, st Store) {
|
||||
ctx := context.Background()
|
||||
addFixtures(t, ctx, st)
|
||||
got, err := st.Search(ctx, Query{Accounts: []string{"mesh"}, Cc: "jschoubben@node-c.be", Limit: 10})
|
||||
got, err := st.Search(ctx, Query{Accounts: []string{"mesh"}, Cc: "jschoubben@example.org", Limit: 10})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -280,7 +280,7 @@ func TestSearchFiltersByCcAndSubjectOrBodyWord(t *testing.T) {
|
||||
eachStore(t, func(t *testing.T, st Store) {
|
||||
ctx := context.Background()
|
||||
addFixtures(t, ctx, st)
|
||||
got, err := st.Search(ctx, Query{Accounts: []string{"mesh"}, Cc: "jschoubben@node-c.be", Words: []string{"renovatie"}, Limit: 10})
|
||||
got, err := st.Search(ctx, Query{Accounts: []string{"mesh"}, Cc: "jschoubben@example.org", Words: []string{"renovatie"}, Limit: 10})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -502,7 +502,7 @@ func TestSearchOrdersBySenderAndSubject(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Both Sent messages share the same sender (jschoubben@node-c.be): the tie-break (account, folder, uid)
|
||||
// Both Sent messages share the same sender (jschoubben@example.org): the tie-break (account, folder, uid)
|
||||
// orders them by uid ascending.
|
||||
sameOrder(t, bySender, "<sentreply1@mesh>", "<sent1@mesh>")
|
||||
|
||||
@@ -755,10 +755,10 @@ func TestSearchWithNoFolderAnswersTheSameMessageIDOncePerAccount(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
for _, m := range []Message{
|
||||
{Account: "mesh", Folder: "Sent", UID: 50, MessageID: "<cross1@shared>", Subject: "cross-account",
|
||||
Date: at1248(9, 0), From: []Person{{Address: "jschoubben@node-c.be"}}, To: []Person{{Address: "me@gmail.example"}},
|
||||
Date: at1248(9, 0), From: []Person{{Address: "jschoubben@example.org"}}, To: []Person{{Address: "me@gmail.example"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{}},
|
||||
{Account: "gmail", Folder: "INBOX", UID: 50, MessageID: "<cross1@shared>", Subject: "cross-account",
|
||||
Date: at1248(9, 1), From: []Person{{Address: "jschoubben@node-c.be"}}, To: []Person{{Address: "me@gmail.example"}},
|
||||
Date: at1248(9, 1), From: []Person{{Address: "jschoubben@example.org"}}, To: []Person{{Address: "me@gmail.example"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{}},
|
||||
} {
|
||||
if err := st.Add(ctx, m, nil); err != nil {
|
||||
|
||||
@@ -85,8 +85,8 @@ func TestTheToolPathSucceedsWithTheSecretsDirectoryAbsent(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
missing := filepath.Join(dir, "never-created")
|
||||
env := Env{Accounts: filepath.Join(dir, "accounts.json"), Grants: filepath.Join(dir, "grants.json"), Secrets: missing}
|
||||
writeFile(t, env.Accounts, `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@node-c.be",
|
||||
"incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"},
|
||||
writeFile(t, env.Accounts, `{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@example.org",
|
||||
"incoming": {"host": "mail.example.org", "port": 993, "security": "tls"},
|
||||
"outgoing": {"host": "h", "port": 465, "security": "tls"}}}}`)
|
||||
writeFile(t, env.Grants, `{"grants": {"mesh": ["triage"]}}`)
|
||||
router, sends, queue := newSendRouter(), newMemSends(), newMemQueue()
|
||||
|
||||
@@ -349,8 +349,8 @@ func sendTestBundle(t *testing.T, outgoing Server) (*Bundle, *sendRouter, *memSe
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
env := Env{Accounts: filepath.Join(dir, "accounts.json"), Grants: filepath.Join(dir, "grants.json"), Secrets: dir}
|
||||
writeFile(t, env.Accounts, fmt.Sprintf(`{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@node-c.be",
|
||||
"incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"},
|
||||
writeFile(t, env.Accounts, fmt.Sprintf(`{"accounts": {"mesh": {"kind": "imap", "address": "jschoubben@example.org",
|
||||
"incoming": {"host": "mail.example.org", "port": 993, "security": "tls"},
|
||||
"outgoing": {"host": %q, "port": %d, "security": %q}}}}`, outgoing.Host, outgoing.Port, outgoing.Security))
|
||||
writeFile(t, env.Grants, `{"grants": {"mesh": ["triage"]}}`)
|
||||
giveSecret(t, dir, Account{Name: "mesh"}, "the-password")
|
||||
@@ -689,7 +689,7 @@ func TestMailSendRefusesAControlCharacterInTheSubjectOrAnAddress(t *testing.T) {
|
||||
// is where SendMail is actually called from.
|
||||
func TestSendUsesTheParsedAddressForRcptAndTheFormattedAddressForTheToHeader(t *testing.T) {
|
||||
fake := newFakeSMTPServer(t)
|
||||
acc := Account{Name: "mesh", Address: "jschoubben@node-c.be", Outgoing: &Server{Host: "127.0.0.1", Port: 25, Security: "tls"}}
|
||||
acc := Account{Name: "mesh", Address: "jschoubben@example.org", Outgoing: &Server{Host: "127.0.0.1", Port: 25, Security: "tls"}}
|
||||
if err := SendMail(fake.dialer(), acc, "the-password", []string{"Ops Team <ops@example.org>"}, "Status", "body", judgedAt, "send-abc123"); err != nil {
|
||||
t.Fatalf("SendMail: %v", err)
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ func classifyTestAccount(addr string) Account {
|
||||
host, portStr, _ := net.SplitHostPort(addr)
|
||||
var port int
|
||||
_, _ = fmt.Sscanf(portStr, "%d", &port)
|
||||
return Account{Name: "mesh", Address: "jschoubben@node-c.be", Outgoing: &Server{Host: host, Port: port, Security: "tls"}}
|
||||
return Account{Name: "mesh", Address: "jschoubben@example.org", Outgoing: &Server{Host: host, Port: port, Security: "tls"}}
|
||||
}
|
||||
|
||||
func outcomeOf(t *testing.T, err error) SendOutcome {
|
||||
@@ -234,8 +234,8 @@ func TestSendMailSaysNotProvenWhenTheConnectionIsLostAfterTheDataWasWritten(t *t
|
||||
// (<send id>@<the account's domain>). Proved both in isolation (composeMessage) and over the wire
|
||||
// (SendMail, with the existing fakeSMTPServer, which keeps the body it received).
|
||||
func TestComposeMessageCarriesTheSendIDInItsMessageID(t *testing.T) {
|
||||
raw := composeMessage("jschoubben@node-c.be", []string{"a@b.c"}, "s", "body", judgedAt, "send-abc123")
|
||||
if !strings.Contains(string(raw), "Message-Id: <send-abc123@node-c.be>") {
|
||||
raw := composeMessage("jschoubben@example.org", []string{"a@b.c"}, "s", "body", judgedAt, "send-abc123")
|
||||
if !strings.Contains(string(raw), "Message-Id: <send-abc123@example.org>") {
|
||||
t.Fatalf("the message does not carry the send id's Message-ID:\n%s", raw)
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ func TestSendMailCarriesTheMessageIDOverTheWire(t *testing.T) {
|
||||
t.Fatalf("SendMail: %v", err)
|
||||
}
|
||||
got := fake.last()
|
||||
if !strings.Contains(got.data, "Message-Id: <send-xyz@node-c.be>") {
|
||||
if !strings.Contains(got.data, "Message-Id: <send-xyz@example.org>") {
|
||||
t.Fatalf("the message sent does not carry the send id's Message-ID:\n%s", got.data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func aBundle(t *testing.T) (*Bundle, *memStore, *memObjects) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := Message{Account: "mesh", Folder: "INBOX", UID: 7, UIDValidity: 1, MessageID: "att@example.org", Subject: "the invoice",
|
||||
Date: judgedAt, From: []Person{{Name: "Bob", Address: "bob@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: judgedAt, From: []Person{{Name: "Bob", Address: "bob@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{ref}, Body: "Please find the invoice attached."}
|
||||
if err := st.Add(ctx, m, addedEvent(m)); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -210,7 +210,7 @@ func TestTheAccountsToolListsOnlyTheAccountsTheCallerIsGranted(t *testing.T) {
|
||||
}
|
||||
}
|
||||
text, _ = rt.call(AccountsTool, "node-c.triage", map[string]any{})
|
||||
if !strings.Contains(text, `"address":"jschoubben@node-c.be"`) || !strings.Contains(text, "Secret-Project") || !strings.Contains(text, "AUTHENTICATIONFAILED") {
|
||||
if !strings.Contains(text, `"address":"jschoubben@example.org"`) || !strings.Contains(text, "Secret-Project") || !strings.Contains(text, "AUTHENTICATIONFAILED") {
|
||||
t.Fatalf("granted: %s", text)
|
||||
}
|
||||
}
|
||||
@@ -284,7 +284,7 @@ func TestMailSearchWithNoFilterAnswersTheNewestGrantedMail(t *testing.T) {
|
||||
env := Env{Accounts: filepath.Join(dir, "accounts.json"), Grants: filepath.Join(dir, "grants.json"), Secrets: dir,
|
||||
Status: filepath.Join(dir, "health.json")}
|
||||
writeFile(t, env.Accounts, `{"accounts": {
|
||||
"mesh": {"kind": "imap", "address": "jschoubben@node-c.be", "incoming": {"host": "mail.node-c.be", "port": 993, "security": "tls"}},
|
||||
"mesh": {"kind": "imap", "address": "jschoubben@example.org", "incoming": {"host": "mail.example.org", "port": 993, "security": "tls"}},
|
||||
"gmail": {"kind": "imap", "address": "me@gmail.example", "incoming": {"host": "imap.gmail.com", "port": 993, "security": "tls"}},
|
||||
"secret": {"kind": "imap", "address": "other@example.org", "incoming": {"host": "mail.example.org", "port": 993, "security": "tls"}}}}`)
|
||||
writeFile(t, env.Grants, `{"grants": {"mesh": ["triage"], "gmail": ["triage"], "secret": ["other"]}}`)
|
||||
@@ -412,12 +412,12 @@ func TestMailSearchEndToEndFiltersAndGroupBySender(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
older := judgedAt.Add(-time.Hour)
|
||||
if err := st.Add(ctx, Message{Account: "mesh", Folder: "INBOX", UID: 1, MessageID: "<a@mesh>", Subject: "from alice",
|
||||
Date: older, From: []Person{{Address: "alice@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: older, From: []Person{{Address: "alice@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{}, Attachments: []AttachmentRef{}, Body: "hi"}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := st.Add(ctx, Message{Account: "mesh", Folder: "INBOX", UID: 2, MessageID: "<b@mesh>", Subject: "from alice again",
|
||||
Date: judgedAt, From: []Person{{Address: "alice@example.org"}}, To: []Person{{Address: "jschoubben@node-c.be"}},
|
||||
Date: judgedAt, From: []Person{{Address: "alice@example.org"}}, To: []Person{{Address: "jschoubben@example.org"}},
|
||||
Flags: []string{"\\Seen"}, Attachments: []AttachmentRef{}, Body: "hi again"}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user