betterbird: an account's own aliases and identities that do not send by SMTP share no outgoing server, and the pins name their vendors on purpose (review 36, review 35 of mesh-controller #251)
mesh/merge-gate pass: builds betterbird, sent nowhere; no bus step; 1 wait(s) for a person; every machine composes with the change as it did without (4 of …
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery failed: its walk failed, carrying its own commit: a gate on a first machine (what it carried put back), a build, a machine

The shared-server check refused an adopted account for its own alias, and
counted Owl's, local folders' and feeds' identities as users of the default
server, though they never send by SMTP. The controller now judges an
upstream pin's host like any name, so each pin declares its vendor.
This commit is contained in:
jochen
2026-10-12 14:49:21 +02:00
parent 263c86d2e5
commit 15983e2f96
3 changed files with 59 additions and 5 deletions
@@ -483,3 +483,36 @@ func TestACredentialRefusalNamesNoAccount(t *testing.T) {
t.Fatalf("%v", err)
}
}
func TestAnAccountsOwnAliasesAndNonMailIdentitiesDoNotShareItsOutgoingServer(t *testing.T) {
f := newFake(t)
f.profileWithAccounts()
f.noPackage()
links(t, nil)
f.declare("// none")
os.RemoveAll(filepath.Join(f.Root, "proc", "4000"))
// account1 has an alias identity on smtp1; smtp1 is the default server; Owl's account and local folders
// have identities that name no outgoing server.
prefs := strings.Replace(f.read(profileDir+"/prefs.js"), `"mail.account.account1.identities", "id1"`, `"mail.account.account1.identities", "id1,id1b"`, 1)
prefs = strings.Replace(prefs, `"mail.account.account2.server", "server2");`, `"mail.account.account2.server", "server2");`+"\n"+
`user_pref("mail.account.account2.identities", "id2");`, 1) +
`user_pref("mail.identity.id1b.useremail", "alias@mail.example.org");` + "\n" +
`user_pref("mail.identity.id1b.smtpServer", "smtp1");` + "\n" +
`user_pref("mail.identity.id2.useremail", "local@mail.example.org");` + "\n" +
`user_pref("mail.smtp.defaultserver", "smtp1");` + "\n"
f.write(profileDir+"/prefs.js", prefs)
f.declareAccounts(adoptable)
if err := f.Prepare(); err != nil {
t.Fatalf("an account's own alias, and identities that do not send by SMTP, are no sharing: %v", err)
}
// An identity of another mail account naming no server does use the default one.
f.write(profileDir+"/prefs.js", strings.Replace(prefs, `"account1,account3,account2"`, `"account1,account3,account2,account6"`, 1)+
`user_pref("mail.account.account6.server", "server6");`+"\n"+
`user_pref("mail.account.account6.identities", "id6");`+"\n"+
`user_pref("mail.identity.id6.useremail", "six@mail.example.org");`+"\n"+
`user_pref("mail.server.server6.type", "pop3");`+"\n")
os.Remove(filepath.Join(f.Root, testHome, recordFile))
if err := f.Prepare(); err == nil || !strings.Contains(err.Error(), "also used by identity id6") {
t.Fatalf("%v", err)
}
}
@@ -148,10 +148,23 @@ func resolveAccounts(accounts map[string]Account, prefs map[string]string, rec m
// ADR 0317 §2 adopts the outgoing server the identity names and leaves the lists as they are, so the module
// does not give the identity a server of its own; it refuses, with the remedy.
func refuseSharedOutgoing(resolved []resolvedAccount, prefs map[string]string, have []profileAccount) []resolvedAccount {
// Every identity of an adopted or created account is its own, its aliases too (review 36).
accountOf := map[string]profileAccount{}
kindOf := map[string]string{}
for _, a := range have {
accountOf[a.Key] = a
for _, id := range a.Identities {
kindOf[id] = a.Kind
}
}
ours := map[string]bool{}
for _, r := range resolved {
if r.How != refused {
ours[r.Keys.Identity] = true
if r.How == refused {
continue
}
ours[r.Keys.Identity] = true
for _, id := range accountOf[r.Keys.Account].Identities {
ours[id] = true
}
}
defaultServer := unquote(prefs["mail.smtp.defaultserver"])
@@ -163,7 +176,9 @@ func refuseSharedOutgoing(resolved []resolvedAccount, prefs map[string]string, h
}
seen[id] = true
server := unquote(prefs["mail.identity."+id+".smtpServer"])
if server == "" {
// Only a mail account's identity sends through the default server when it names none: Owl's, local
// folders and feeds do not send by SMTP (review 36).
if server == "" && (kindOf[id] == "imap" || kindOf[id] == "pop3") {
server = defaultServer
}
if server != "" {
+8 -2
View File
@@ -125,7 +125,10 @@
"url": "https://www.betterbird.eu/downloads/LinuxArchive/betterbird-153.4.0esr-bb10.en-US.linux-x86_64.tar.xz",
"sha256": "38dd24890a66b4cf9a45bc24e15192e00c26b929e1bb8df7974c16a4539129e2",
"version": "153.4.0esr-bb10",
"within": "betterbird"
"within": "betterbird",
"names-on-purpose": {
"www.betterbird.eu": "Betterbird's project publishes its Linux release there; the build seat fetches it once, by its pinned sha256 (novox/hq ADR 0316 §2)"
}
},
{
"name": "owl",
@@ -133,7 +136,10 @@
"url": "https://www.beonex.com/owl/owl.xpi",
"sha256": "a54cc3d52113b34f97942ee19190947dee23561e2217f18db3d80ac023991221",
"version": "1.5.6.1",
"file": "owl.xpi"
"file": "owl.xpi",
"names-on-purpose": {
"www.beonex.com": "Owl's vendor publishes its xpi there; the build seat fetches it once, by its pinned sha256 (novox/hq ADR 0316 §6)"
}
},
{
"name": "distribution",