Skip to content

Add Apple iCloud adapter - #272

Open
pavsap wants to merge 3 commits into
inovex:mainfrom
pavsap:feat/apple-adapter
Open

Add Apple iCloud adapter#272
pavsap wants to merge 3 commits into
inovex:mainfrom
pavsap:feat/apple-adapter

Conversation

@pavsap

@pavsap pavsap commented Sep 5, 2025

Copy link
Copy Markdown

Overview

This PR adds support for Apple iCloud calendars via the CalDAV protocol, enabling users to sync their iCloud calendars with CalendarSync.

Features

  • Apple CalDAV adapter with basic authentication (Apple ID + app-specific password)
  • Dynamic calendar discovery - users can specify friendly names like "primary" instead of UUIDs
  • Full event synchronization - create, read, update, delete calendar events
  • iCalendar parsing using github.com/emersion/go-ical
  • Seamless integration with existing adapter architecture

Configuration Example

source:
  adapter:
    type: apple
    calendar: "primary"  # or any calendar name like "Work", "Family"
    oAuth:
      clientId: "user@icloud.com"
      clientKey: "app-specific-password"

Implementation Details

  • Uses CalDAV protocol (RFC 4791) with Apple's iCloud CalDAV endpoints
  • Reuses existing OAuth config fields for simplicity (clientId=Apple ID, clientKey=app-specific-password)
  • Implements dynamic principal and calendar UUID resolution
  • Supports both friendly names and direct UUID specification
  • Full iCalendar format support for event properties

Setup Requirements

  • Apple ID account
  • App-specific password generated from Apple ID settings (not regular iCloud password)
  • Calendar access permissions

Testing

☑️ Authentication with Apple ID + app-specific password
☑️ Calendar discovery and name resolution
☑️ Event reading from iCloud calendars
☑️ Integration with existing CalendarSync architecture

Recent Updates

☑️ Fixed CalDAV event creation (resolved 400 Bad Request errors)
☑️ Added thread-safe calendar resolution caching for performance
☑️ Fixed Google->Apple sync functionality

- Implement CalDAV client for Apple iCloud calendars
- Support basic auth with Apple ID + app-specific passwords
- Dynamic calendar discovery and friendly name resolution
- Full CRUD operations for calendar events
- iCalendar parsing using go-ical library
- Seamless integration with existing adapter pattern
- Fix CalDAV PUT request paths using resolved principal/calendar IDs
- Add required If-None-Match header for new event creation
- Implement thread-safe calendar resolution caching with sync.Once
- Combine CreateEvent/UpdateEvent methods to reduce duplication
- Resolve Google->Apple sync 400 Bad Request errors
- Generate consistent SyncID from iCal UID for better event matching
- Add 412 Precondition Failed error handling in CreateEvent
- Gracefully fallback to update operation when event already exists

This resolves conflicts in bidirectional sync scenarios where the same
logical event exists in both calendars with different UIDs, preventing
CalDAV 412 errors while maintaining sync functionality.
@mmisiewicz

Copy link
Copy Markdown

I would love to make use of this. I tried the Zep adapter as mentioned in #227 but no luck there.

@pavsap

pavsap commented Oct 7, 2025

Copy link
Copy Markdown
Author

@mmisiewicz, just copy my branch and compile it from source with make build

Use the compiled ./bin/calendarsync as you normally would.

Cron runs the daily bidirectional sync between my Primary (Apple) calendar and Work (Google Workspace) calendar.

@mmisiewicz

Copy link
Copy Markdown

Can confirm it's working great for me and I'd love to see this merged!

@pavsap

pavsap commented Jan 8, 2026

Copy link
Copy Markdown
Author

@MichaelEischer why is this one not moving?

Comment on lines +64 to +68
if err := c.SetupAuth(ctx, credentials, storage, bindPort); err != nil {
return nil, err
}
} else if c, ok := client.(port.OAuth2Adapter); ok {
if err := c.SetupOauth2(ctx, credentials, storage, bindPort); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given it's the same arguments, wouldn't it be simpler/smaller change to keep the same SetupOauth2 method/interface?

@frittentheke

Copy link
Copy Markdown
Collaborator

@pavsap sorry about the delay. Would you maybe rebase and revisit this PR once more?
Do you have a testing setup in mind that I could easily leverage without being an active Apple Calendar user?

@pavsap

pavsap commented Jul 23, 2026

Copy link
Copy Markdown
Author

@frittentheke No worries, thanks for getting back. I'll rebase onto the current main and revisit the PR in my spare time.

As for testing, I don't have a setup right now, but I'll think about how to test this without an active Apple Calendar account and report back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants