Effortless Event Management with ICS Files: Sync, Code, and Schedule

Shivani Agrawal
Simform Engineering
4 min readOct 31, 2023

A mini guide to working with ICS files and managing events

In this comprehensive blog post, we’ll delve into the world of ICS (iCalendar) files and how you can leverage their potential using Python.

From understanding the basics of ICS files to creating, parsing, and manipulating them, we’ll cover it all.

What is an ICS File?

An iCalendar (ICS) file is a standard format for sharing calendar and scheduling information. It’s a simple, text-based format used to describe events, appointments, tasks, and other time-related details.

Think of it as a universal language for sharing and managing schedules across different email apps and platforms.

Let’s take a peek at what an ICS file looks like:

BEGIN:VCALENDAR
METHOD:REQUEST
BEGIN:VEVENT
SUMMARY:Python Meetup
DTSTART;TZID=Asia/Calcutta:20230922T160000
DTEND;TZID=Asia/Calcutta:20230922T170000
UID:6e75b362–3202–11ee-971c-0242ac110002
ATTENDEE;ROLE=CHAIR:testmoderator@example.com
ATTENDEE;ROLE=REQ-PARTICIPANT:testparticipant@example.com
DESCRIPTION:This is example ics file.
ORGANIZER:testorganizer@example.com
STATUS:confirmed
END:VEVENT
END:VCALENDAR

Now, let’s break down the elements:

  • BEGIN:VCALENDAR and END:VCALENDAR: These tags define the start and end of the calendar data.
  • METHOD:REQUEST: This indicates that the event represents a scheduling request, such as an invitation to a meeting.
  • BEGIN:VEVENT and END:VEVENT: These tags enclose information about a specific event within the calendar.
  • UID: A unique identifier for the event.
  • SUMMARY: The title or summary of the event.
  • DESCRIPTION: A detailed description of the event.
  • DTSTART and DTEND: The start and end times of the event.
  • ATTENDEE: Specifies the email address of the attendee who should receive the email reminder. CHAIR is for moderator, and PARTICIPANT for participants. REQ shows this is a required attendee.
  • ORGANIZER: Specifies the email address of the event organizer.

“This is a simplified ICS file, but they can include more complex event recurrence rules, participant lists, and additional attributes based on your needs.”

Content provided above can be generated by creating a file with an ‘.ics’ extension, such as ‘event.ics,’ and importing it into your preferred calendar application.

While this method offers a straightforward approach to creating ICS files, manually writing the entire file can be error-prone and tedious. Typos and inaccuracies can easily slip in, potentially causing issues during the import process.

That’s where Python and libraries like iCalendar come to the rescue. This library simplifies the process of generating ICS files by providing convenient functions that take a few parameters and effortlessly generate the file for you.

With the help of these ‘magic’ functions, you can significantly streamline the creation of ICS files, reducing the risk of errors and ensuring a smoother import experience into your calendar application.”

To illustrate this solution, we’ve developed an event management demo application that efficiently organizes events and sends email invitations with attached ICS files.

In our implementation, we’ve included an ‘ICSGenerator’ class to handle ICS data generation. Here’s an example of the code:

import email
from email.mime.base import MIMEBase
import uuid

from icalendar import Calendar, Event
from decouple import config


class ICSGenerator:
"""
ICSGenerator class generates an ics file.
"""
filename = "event_invite.ics"

def __init__(self, **event_info):
self.cal = Calendar()
self.event = Event()
self.event_info = event_info

@property
def calendar_dict(self):
return {"prodid": "ICS Blog Test", "version": "2.0", "method": "REQUEST"}

@property
def event_dict(self):
return {
"summary": self.event_info.get("subject"),
"organizer": config("ORGANIZER_EMAIL"),
"description": self.event_info.get("description"),
"dtstart": self.event_info.get("start_time"),
"dtend": self.event_info.get("end_time"),
"sequence": 1,
"uid": uuid.uuid4(),
"status": "confirmed",
"attendee;ROLE=REQ-PARTICIPANT": self.event_info.get("attendee_emails"),
"attendee;ROLE=CHAIR": self.event_info.get("mod"),
}

def _add(self, component, cal_data: dict):
"""component: event or cal"""
for key, value in cal_data.items():
component.add(key, value)

def set_ics_data(self):
self._add(self.cal, self.calendar_dict)
self._add(self.event, self.event_dict)
self.cal.add_component(self.event)

def get_ics_content(self):
self.set_ics_data()
print(self.event)
part = MIMEBase("text", "calendar", method="REQUEST", name=self.filename)
part.set_payload(self.cal.to_ical())
email.encoders.encode_base64(part)
part.add_header("Content-Description", self.filename)
part.add_header("Content-class", "urn:content-classes:calendarmessage")
part.add_header("Filename", self.filename)
part.add_header("Path", self.filename)
return part

“In this code snippet, we generate ICS file data and send it as a calendar attachment using the ‘Mimebase’ class. The ‘icalendar’ library’s ‘Calendar’ and ‘Event’ classes simplify the conversion of JSON data into an ICS file, which can be easily attached to your emails.

To explore this functionality further, you can refer to the full code in our GitHub repository.

Additionally, you can configure Alarm as reminders for scheduled meetings within an ICS file using the following format:

BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:Reminder
TRIGGER;RELATED=START:-PT15M
END:VALARM

Some briefing about the parameters:

  • BEGIN:VALARM and END:VALARM: These tags define the start and end of the alarm data.
  • ACTION:DISPLAY: It triggers a visible action or message to alert the user.
  • TRIGGER This parameter specifies the trigger condition
  • RELATED=START: It indicates that the trigger is related to the event’s start time.
  • PT15M: This ISO 8601 time duration is set to “minus 15 minutes,” which triggers 15 minutes before the event’s start time.

Here is the code example to create Alarm:

def set_alarm(self, event):
"""
Set a Reminder Alarm before the meeting.
"""
alarm = Alarm()
alarm.add("action", "DISPLAY")
alarm.add("description", "Reminder")
if self.send_reminder_before in [0, 5, 15, 30]:
alarm.add("TRIGGER;RELATED=START", "-PT{0}M".format(self.send_reminder_before))
if self.send_reminder_before == 60:
alarm.add("TRIGGER;RELATED=START", "-PT1H")
if self.send_reminder_before == 120:
alarm.add("TRIGGER;RELATED=START", "-PT2H")
if self.send_reminder_before == 720:
alarm.add("TRIGGER;RELATED=START", "-PT12H")
if self.send_reminder_before == 1440:
alarm.add("TRIGGER;RELATED=START", "-P1D")
if self.send_reminder_before == 10080:
alarm.add("TRIGGER;RELATED=START", "-P1W")

Conclusion

This blog has provided you with a fundamental understanding of ICS files and their role in event management. Whether you prefer using Python libraries or creating ICS files from scratch, you now have the knowledge to seamlessly integrate ICS calendar events into your code.

If you’d like to explore the full code and try it out for yourself, visit our GitHub repository.

Demo Links:

iCalendar
RFC specifications

For more updates on the latest development trends, follow the Simform Engineering.

Follow Us: Twitter | LinkedIn

--

--