Skip to content

RSVP Links

Invitation emails contain Accept/Maybe/Decline links that point to calendars.<domain>/rsvp/. These are Django server-rendered pages, not part of the single-page app.

URL Format

https://calendars.<domain>/rsvp/?t=<signed-token>

The token contains the event UID, attendee email, and action, signed with TimestampSigner.

Reverse Proxy

The RSVP endpoint must be proxied through Caddy to the Django backend:

reverse_proxy /rsvp/* 172.29.0.30:8000 {
    header_up Host {host}
    header_up X-Forwarded-Proto https
}

Without this, /rsvp/ serves the static frontend (index.html), which loads the calendar app instead of the RSVP page.

APP_URL

The APP_URL setting controls the base URL used in invitation emails:

APP_URL=https://calendars.<domain>

If not set, RSVP links are generated with an empty base:

Wrong: /rsvp/?t=...
Correct: https://calendars.<domain>/rsvp/?t=...

Flow

  1. Organizer creates event with attendee
  2. CalDAV IMip plugin sends callback to Django
  3. Django generates HTML email with RSVP links
  4. Django submits email via Messages API → Brevo
  5. Attendee clicks Accept/Maybe/Decline
  6. Django RSVP view processes the action
  7. Django updates CalDAV attendee PARTSTAT via internal CalDAV client
  8. Organizer's refresh shows updated status

Thunderbird Integration

Thunderbird's native Accept/Decline sends an iMIP reply email. This reply reaches the Messages inbox but does NOT auto-update the calendar. The attendee must click the email link for the organizer to see the status change.