Meeting Invitations: answering an invitation from SnappyMail without ever building iTIP
SnappyMail can display an
.icsattachment — theics-viewerplugin does it well. But nothing can act on one: the invitation has to be re-entered into the calendar by hand. This plugin adds the missing step. It is published under the AGPL.
What it does
When a message carries a text/calendar part whose method is REQUEST, the plugin shows the meeting summary, organiser, time and location, with three buttons: Accept, Tentative, Decline. Choosing one sets your ATTENDEE;PARTSTAT and PUTs the event into your calendar.
That’s it. And that is deliberately all.
The reply to the organiser is not built here
The central design point. Under RFC 6638 the CalDAV server owns scheduling: storing the event in your own calendar with your PARTSTAT set makes the server generate and deliver the METHOD:REPLY itself, and mark the ORGANIZER with SCHEDULE-STATUS.
The direct consequence: the plugin constructs no iTIP and has no SMTP path. No reply is composed, sent or queued here.
That is the correct way to do it, and it is also the safest: the attack surface of a webmail plugin that composes and sends messages on the user’s behalf is in a different league from one that issues an authenticated PUT into that user’s calendar.
Verified against Cyrus IMAP: a PUT carrying PARTSTAT=ACCEPTED comes back with SCHEDULE-STATUS=1.1 on the organiser — the reply did go out.
Requires a CalDAV server with scheduling enabled. On Cyrus that is caldav_allowscheduling, plus imipnotifier for delivery by mail.
Configuration
Admin → Plugins → invitations:
| Setting | Example |
|---|---|
| CalDAV URL template | https://dav.example.com/dav/calendars/user/{user}/Default/ |
| DAV default domain | example.com — addresses in this domain use the local part only; empty means always the full address |
| Verify the DAV server certificate | on |
{user}, {email}, {login} and {domain} are substituted per account. Nothing is hardcoded: with no template configured the plugin declines to act rather than guess a URL. Authentication reuses the account’s own IMAP credentials.
Cancellations and revisions: the detail that decides it
This is where an invitations plugin is judged. Answering an old mail must not resurrect a meeting.
SEQUENCE orders revisions of the same UID (RFC 5545 §3.8.7.4). Before answering, the plugin compares the invitation against the copy already in the calendar and refuses one that has been superseded: accepting an old mail after a reschedule cannot bring back the old time. A newer revision replaces the stored copy, as it should.
METHOD:CANCEL is recognised: the meeting is shown as cancelled and a single button removes it from the calendar. A cancellation for an event that was never accepted is not an error.
The subtlety: a cancellation is also recorded. Deleting the event removes the very copy the SEQUENCE check compares against; without that record the original invitation mail could still be accepted afterwards — the meeting would come back, and the organiser would get a reply telling them you had accepted a cancelled meeting. A later revision is still allowed through: that is the organiser reinstating the meeting, rather than a stale mail being answered twice. Records expire once the meeting has finished.
Notes and limits
Owned, and listed in the README:
METHOD:REPLYis another attendee answering: no action needed here.- The invitation is matched against your account address and your configured identities, so an invitation sent to an alias is recognised.
- The event is stored without
METHOD: a calendar holds events, not scheduling messages. - Details are read from the
VEVENTonly.VTIMEZONEcarries its ownDTSTARTper transition rule — reading the first one in the document shows a date like 1905 instead of the meeting. The kind of trap you only see by hitting it.
Licence
AGPL-3.0-or-later, the same licence as SnappyMail, which this plugin loads into. Releases up to and including v1.2.0 were published under MIT; that grant is irrevocable for those copies — anyone who obtained the plugin under MIT keeps it under MIT.
→ https://github.com/FathiBenNasr/snappymail-invitations
On the organiser’s side, sending invitations from the calendar is handled by our CalDAV fork.
Running Cyrus, Postfix or Sendmail and want a self-hosted webmail with calendars and contacts? See our services or let’s talk. And follow us on GitHub.