diff --git a/src/features/relays/RelaysPage.tsx b/src/features/relays/RelaysPage.tsx index b044772..7aaec7d 100644 --- a/src/features/relays/RelaysPage.tsx +++ b/src/features/relays/RelaysPage.tsx @@ -288,6 +288,7 @@ interface General { description: string; address: string; linkPort: string; + mxPreference: string; enabled: boolean; sendThrough: boolean; inboundOnly: boolean; @@ -299,6 +300,7 @@ function general(relay: Relay): General { description: relay.description, address: relay.address, linkPort: String(relay.linkPort), + mxPreference: String(relay.mxPreference ?? 10), enabled: relay.enabled, sendThrough: relay.sendThrough, inboundOnly: relay.inboundOnly, @@ -354,6 +356,13 @@ function SettingsDialog({ } patch.linkPort = Number(g.linkPort); } + if (g.mxPreference !== startGeneral.mxPreference) { + if (!/^\d+$/.test(g.mxPreference) || Number(g.mxPreference) > 65535) { + setInvalid('mxPreference'); + return; + } + patch.mxPreference = Number(g.mxPreference); + } for (const flag of ['enabled', 'sendThrough', 'inboundOnly'] as const) { if (g[flag] !== startGeneral[flag]) patch[flag] = g[flag]; } @@ -443,9 +452,20 @@ function SettingsDialog({

{t('relays.s.receiving', 'Taking mail in')}

- - {input('hostname', { placeholder: 'mx1.example.com' })} - +
+ + {input('hostname', { placeholder: 'mx1.example.com' })} + + + setG({ ...g, mxPreference: e.target.value })} + /> + +
{input('smtpListen', { placeholder: '[::]:25' })} diff --git a/src/features/relays/model.test.ts b/src/features/relays/model.test.ts index 9f2ff20..909f028 100644 --- a/src/features/relays/model.test.ts +++ b/src/features/relays/model.test.ts @@ -69,6 +69,7 @@ function relay(extra: Partial = {}): Relay { enabled: true, sendThrough: false, inboundOnly: false, + mxPreference: 10, settings: SETTINGS, joinState: 'joined', links: [link('1')], diff --git a/src/features/relays/model.ts b/src/features/relays/model.ts index 85f4987..2782a2b 100644 --- a/src/features/relays/model.ts +++ b/src/features/relays/model.ts @@ -63,6 +63,8 @@ export interface Relay { enabled: boolean; sendThrough: boolean; inboundOnly: boolean; + /** Absent from servers before RL-25. */ + mxPreference?: number; settings: RelaySettings; joinState: 'waiting' | 'expired' | 'joined'; joinExpiresAt?: string | null; diff --git a/src/help/texts.ts b/src/help/texts.ts index d02f190..336d255 100644 --- a/src/help/texts.ts +++ b/src/help/texts.ts @@ -25,13 +25,15 @@ export const FIELD_HELP: Record = { 'The relay’s host name or IP address, as this server dials it for the link. A WireGuard address keeps the link off the internet.', 'inbuxa:Relay.linkPort': 'The port the relay listens on for this server’s link. 443 unless you chose another.', 'inbuxa:Relay.enabled': - 'Turn off to drop the link: the relay closes port 25 and keeps what it holds until it’s turned back on.', + 'Turn off to stop this server linking to it. The relay keeps the mail it holds and goes on taking mail in, held until it’s turned back on.', 'inbuxa:Relay.sendThrough': 'Send all outgoing mail through relays instead of straight from this server. Mail waits here while no relay is linked.', 'inbuxa:Relay.inboundOnly': 'The relay takes mail in but sends none, for instance while its address is new to other providers or not in your SPF record yet.', 'inbuxa:Relay.hostname': - 'The relay’s public name: what it says when other servers connect, and the name on its certificate. Needs an A record and matching reverse DNS.', + 'The relay’s public name: what it says when other servers connect, and the name on its certificate. Needs an A record and matching reverse DNS. Where this server publishes a domain’s DNS, it’s in the MX and SPF records.', + 'inbuxa:Relay.mxPreference': + 'Where this server publishes a domain’s DNS, the relay’s MX preference: senders try the lowest first. Give relays the same number to share the mail.', 'inbuxa:Relay.smtpListen': 'The addresses the relay takes mail on, usually [::]:25 for every address on port 25.', 'inbuxa:Relay.maxMessageSize': 'The largest message the relay accepts, in either direction.', 'inbuxa:Relay.maxRecipients': 'How many recipients one message may have at the relay.', diff --git a/src/i18n/en.json b/src/i18n/en.json index c22b59a..bbdbfb8 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2388,7 +2388,8 @@ "spoolMaxBytes": "Spool size (GB)", "outboundRetry": "Waits between attempts", "outboundExpiry": "Give up after", - "outboundTls": "Encryption" + "outboundTls": "Encryption", + "mxPreference": "MX preference" }, "cancel": "Cancel", "addGo": "Add",