fix: accept a pasted JMAP session URL as the server address #971

This commit is contained in:
Linus Rath
2026-09-24 18:40:43 +02:00
parent ab845783ab
commit bd42206686
2 changed files with 21 additions and 5 deletions
@@ -50,6 +50,21 @@ describe('normalizeServerUrl', () => {
expect(normalizeServerUrl('mail.example.com/jmap')).toBe('https://mail.example.com');
});
it('strips a pasted session URL with its query or fragment (#971)', () => {
expect(normalizeServerUrl('https://mail.example.com/jmap/session')).toBe('https://mail.example.com');
expect(normalizeServerUrl('mail.example.com/jmap/session/')).toBe('https://mail.example.com');
expect(normalizeServerUrl('https://mail.example.com/.well-known/jmap?x=1#top')).toBe(
'https://mail.example.com',
);
expect(normalizeServerUrl('https://mail.example.com/?x=1')).toBe('https://mail.example.com');
});
it('keeps a base path prefix in front of the session suffix', () => {
expect(normalizeServerUrl('https://example.com/mail/jmap/session')).toBe('https://example.com/mail');
expect(normalizeServerUrl('https://example.com/mail/.well-known/jmap')).toBe('https://example.com/mail');
expect(normalizeServerUrl('https://example.com/mail')).toBe('https://example.com/mail');
});
it('keeps an explicit http scheme and port', () => {
expect(normalizeServerUrl('http://localhost:8080')).toBe('http://localhost:8080');
});
+6 -5
View File
@@ -34,8 +34,8 @@ const EMAIL_RE = /^[^\s@]+@([^\s@]+\.[^\s@]+)$/;
/**
* Accept what people actually type — `mail.example.com`, `example.com/`,
* `https://mail.example.com/.well-known/jmap` — and return the base URL the
* JMAP client expects, or null if it can't be one.
* `https://mail.example.com/.well-known/jmap`, `…/jmap/session` — and return
* the base URL the JMAP client expects, or null if it can't be one.
*/
export function normalizeServerUrl(input: string): string | null {
let value = input.trim();
@@ -57,11 +57,12 @@ export function normalizeServerUrl(input: string): string | null {
if (/^http:\/\//i.test(value) && !isLocalHost(value)) return null;
// Someone pasting the endpoint they found in the webmail's settings gets the
// same result as someone typing the address they use in the browser.
// same result as someone typing the address they use in the browser. Only
// the session or API suffix goes, so a base path prefix survives (#971).
value = value
.replace(/[?#].*$/, '')
.replace(/\/+$/, '')
.replace(/\/\.well-known\/jmap$/i, '')
.replace(/\/jmap$/i, '')
.replace(/\/(?:jmap\/session|\.well-known\/jmap|jmap)$/i, '')
.replace(/\/+$/, '');
const host = value.slice(value.indexOf('://') + 3).split('/')[0];