odysseus-dev/odysseus · error · Error
Unsubscribe failed
Error message
Unsubscribe failed
What it means
Thrown when POST of the unsubscribe request (method_index 0 = reply-based List-Unsubscribe) returns success=false. The button re-enables and restores its method label, and the toast shows the server's error or the generic 'Unsubscribe failed'.
Source
Thrown at static/js/emailLibrary.js:1759
btn.disabled = true;
btn.textContent = 'Sending…';
try {
const r = await fetch(emailApiUrl('/api/email/unsubscribe/execute', {
account_id: state._libAccountId || undefined,
}), {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
uid: c.uid,
folder: c.folder || state._libFolder || 'INBOX',
account_id: state._libAccountId || '',
method_index: 0,
move_to_spam: false,
}),
});
const d = await r.json().catch(() => ({}));
if (!d.success) throw new Error(d.error || 'Unsubscribe failed');
btn.textContent = 'Sent';
_markUnsubscribeCardDone(modal, idx);
showToast('Unsubscribe email sent');
_showUnsubscribeCleanupPrompt(modal, [c]);
} catch (err) {
console.error(err);
btn.disabled = false;
btn.textContent = _unsubscribeMethodLabel(c.recommended_method);
showToast(err?.message || 'Unsubscribe failed');
}
});
});
} catch (err) {
console.error(err);
finishScanStatus?.('Failed to scan email headers');
}
}
View on GitHub (pinned to f9235ebbf1)
Solutions
- Read d.error in the response body (Network tab) — it names whether parsing or sending failed
- Verify the account has working outgoing/SMTP credentials
- Use the cleanup fallback (mark as spam / delete) when the sender's unsubscribe flow is broken
- Refresh the list and retry if the UID was stale
Defensive patterns
Strategy: fallback
Validate before calling
if (!c.list_unsubscribe && !c.recommended_method) { showToast('No unsubscribe method available — use mark-as-spam'); return; } Try / catch
try { const d = await r.json().catch(() => ({})); if (!d.success) throw new Error(d.error || 'Unsubscribe failed'); ... } catch (err) { btn.disabled = false; btn.textContent = _unsubscribeMethodLabel(c.recommended_method); showToast(err?.message || 'Unsubscribe failed'); } Prevention
- Always keep the spam/delete cleanup path as the fallback when unsubscribe sending fails (as the follow-up prompt does)
- Verify SMTP credentials for the account before offering send-based unsubscribe
- Restore the button label in catch so retries are possible
- Parse List-Unsubscribe headers defensively — mailto: is frequently absent/malformed
When it happens
Trigger: Clicking Send on an unsubscribe card: the message's List-Unsubscribe mailto can't be parsed or sent (missing/invalid header, SMTP relay refuses the sender), the UID/folder pair no longer resolves, or the account's outgoing credentials are missing.
Common situations: mailto unsubscribe address missing from the header; provider blocks programmatic sends to that address; message moved/expunged so uid lookup fails; account configured for receive-only without SMTP.
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/c54b6725ccc740a9.
Report an issue: GitHub.