calendar-invite: strip METHOD from ICS before CalDAV storage

CalDAV servers (Migadu) reject ICS files with METHOD:REQUEST/REPLY
as it's an iTIP email concept, not a storage property. Strip it
when saving to local calendar, for both send and reply flows.
This commit is contained in:
Yanxin Lu
2026-03-18 14:54:33 -07:00
parent b8ba4adec5
commit 4e3c6acab6

View File

@@ -74,6 +74,17 @@ def _build_calendar_email(from_addr, to_addr, subject, body, ics_bytes, method="
return msg.as_string() return msg.as_string()
def _strip_method(ics_bytes):
"""Remove METHOD property from ICS for CalDAV storage.
CalDAV servers reject METHOD (it's an iTIP/email concept, not a storage one).
"""
cal = Calendar.from_ical(ics_bytes)
if "method" in cal:
del cal["method"]
return cal.to_ical()
def _parse_iso_datetime(dt_str): def _parse_iso_datetime(dt_str):
"""Parse ISO 8601 datetime string to a datetime object.""" """Parse ISO 8601 datetime string to a datetime object."""
# Handle both 2026-03-20T14:00:00 and 2026-03-20T14:00 # Handle both 2026-03-20T14:00:00 and 2026-03-20T14:00
@@ -167,10 +178,10 @@ def cmd_send(args):
_send_email(email_str, args.account) _send_email(email_str, args.account)
print(f"Calendar invite sent to: {args.to}") print(f"Calendar invite sent to: {args.to}")
# Save to local calendar # Save to local calendar (without METHOD for CalDAV compatibility)
if CALENDAR_DIR.is_dir(): if CALENDAR_DIR.is_dir():
dest = CALENDAR_DIR / f"{uid}.ics" dest = CALENDAR_DIR / f"{uid}.ics"
dest.write_bytes(ics_bytes) dest.write_bytes(_strip_method(ics_bytes))
print(f"Saved to local calendar: {dest}") print(f"Saved to local calendar: {dest}")
_sync_calendar() _sync_calendar()
@@ -344,8 +355,8 @@ def cmd_reply(args):
if CALENDAR_DIR.is_dir(): if CALENDAR_DIR.is_dir():
dest = CALENDAR_DIR / f"{uid}.ics" dest = CALENDAR_DIR / f"{uid}.ics"
if partstat in ("ACCEPTED", "TENTATIVE"): if partstat in ("ACCEPTED", "TENTATIVE"):
# Save the original event to local calendar # Save the original event to local calendar (without METHOD for CalDAV)
dest.write_bytes(ics_path.read_bytes()) dest.write_bytes(_strip_method(ics_path.read_bytes()))
print(f"Saved to local calendar: {dest}") print(f"Saved to local calendar: {dest}")
elif partstat == "DECLINED" and dest.is_file(): elif partstat == "DECLINED" and dest.is_file():
dest.unlink() dest.unlink()