Files
hermes-skills/skills/email/email-workflows/references/icloud-caldav-config.md
T

2.3 KiB

iCloud CalDAV Configuration

Setup

  1. Generate app-specific password at appleid.apple.com → Security → App-Specific Passwords
  2. Select "Mail" or "Calendar" service
  3. Save the 16-char password (format: xxxx-xxxx-xxxx-xxxx) to /root/.config/himalaya/g-germainebrown-icloud-calendar.pass
  4. Set file permissions: chmod 600 /root/.config/himalaya/g-germainebrown-icloud-calendar.pass

Himalaya Config

Add to /root/.config/himalaya/config.toml:

[accounts.germaine-calendar]
backend.type = "caldav"
backend.host = "https://caldav.icloud.com"
backend.login = "g@germainebrown.com"
backend.auth.type = "password"
backend.auth.cmd = "cat /root/.config/himalaya/g-germainebrown-icloud-calendar.pass"

Verification Test

import requests
with open('/root/.config/himalaya/g-germainebrown-icloud-calendar.pass') as f:
    pw = f.read().strip()
body = '''<?xml version="1.0" encoding="utf-8"?>
<d:propfind xmlns:d="DAV:">
  <d:prop>
    <d:displayname/>
    <d:current-user-principal/>
  </d:prop>
</d:propfind>'''
r = requests.request('PROPFIND', 'https://caldav.icloud.com/',
    auth=('g@germainebrown.com', pw),
    headers={'Content-Type': 'application/xml; charset=utf-8'},
    data=body, timeout=15)
# 207 = Multi-Status (auth OK). 401 = auth failed.

iCloud Calendar Home Discovery

body = '''<?xml version="1.0" encoding="utf-8"?>
<d:propfind xmlns:d="DAV:" xmlns:cal="urn:ietf:params:xml:ns:caldav">
  <d:prop>
    <cal:calendar-home-set/>
  </d:prop>
</d:propfind>'''
r = requests.request('PROPFIND', 'https://caldav.icloud.com/1079451706/principal/',
    auth=('g@germainebrown.com', pw),
    headers={'Depth': '0'}, data=body, timeout=15)

Returns: p{xx}-caldav.icloud.com:443/1079451706/calendars/

Pitfalls

  • Apple revokes old app-specific passwords when generating new ones. Always update the .pass file after regeneration.
  • The IMAP-style login test (p02-imap.mail.me.com:993) uses a different auth path than CalDAV. A failed IMAP login does NOT mean the password is wrong — use the PROPFIND test against caldav.icloud.com instead.
  • App-specific passwords expire when the Apple ID password is changed or the app is revoked.
  • Himalaya CalDAV (noted here) is experimental — the calendar subcommand may not exist. Use direct Python requests for CalDAV operations.