Sending Outlook appointments with Python

Python allows you to send calendar appointments (invitations / events) directly from your code. It is quite easy to create a new appointment in the standard iCalendar format (ics). You can do it by hand or use a convenient icalendar open source module. In order to convince Outlook, however, to present the iCalendar events as native calendar appointments, you will need to make some effort. Fortunately, other people have already collected all the necessary pieces. Below is a working example for sending Outlook-friendly invitation from Python. In principle, you could use some of the information here to send similar invitation using different API, for example .NET.

Note, that you need to supply the relevant timezone information with your dates, otherwise the result might be different from what you expect.

  1. import email.MIMEText
  2. import email.MIMEBase
  3. from email.MIMEMultipart import MIMEMultipart
  4. import smtplib
  5. import datetime as dt
  6. import icalendar
  7. import pytz
  9. def sendAppointment(self, subj, description):
  10.   # Timezone to use for our dates - change as needed
  11.   tz = pytz.timezone("Europe/London")
  12.   reminderHours = 1
  13.   startHour = 7
  14.   start = tz.localize(dt.datetime.combine(, dt.time(startHour, 0, 0)))
  15.   cal = icalendar.Calendar()
  16.   cal.add('prodid', '-//My calendar application//')
  17.   cal.add('version', '2.0')
  18.   cal.add('method', "REQUEST")
  19.   event = icalendar.Event()
  20.   event.add('attendee', self.getEmail())
  21.   event.add('organizer', "")
  22.   event.add('status', "confirmed")
  23.   event.add('category', "Event")
  24.   event.add('summary', subj)
  25.   event.add('description', description)
  26.   event.add('location', "Room 101")
  27.   event.add('dtstart', start)
  28.   event.add('dtend', tz.localize(dt.datetime.combine(, dt.time(startHour + 1, 0, 0))))
  29.   event.add('dtstamp', tz.localize(dt.datetime.combine(, dt.time(6, 0, 0))))
  30.   event['uid'] = getUniqueId() # Generate some unique ID
  31.   event.add('priority', 5)
  32.   event.add('sequence', 1)
  33.   event.add('created', tz.localize(
  35.   alarm = icalendar.Alarm()
  36.   alarm.add("action", "DISPLAY")
  37.   alarm.add('description', "Reminder")
  38.   #alarm.add("trigger", dt.timedelta(hours=-reminderHours))
  39.   # The only way to convince Outlook to do it correctly
  40.   alarm.add("TRIGGER;RELATED=START", "-PT{0}H".format(reminderHours))
  41.   event.add_component(alarm)
  42.   cal.add_component(event)
  44.   msg = MIMEMultipart("alternative")
  46.   msg["Subject"] = subj
  47.   msg["From"] = "{0}".format(self.creator)
  48.   msg["To"] = self.getEmail()
  49.   msg["Content-class"] = "urn:content-classes:calendarmessage"
  51.   msg.attach(email.MIMEText.MIMEText(description))
  53.   filename = "invite.ics"
  54.   part = email.MIMEBase.MIMEBase('text', "calendar", method="REQUEST", name=filename)
  55.   part.set_payload( cal.to_ical() )
  56.   email.Encoders.encode_base64(part)
  57.   part.add_header('Content-Description', filename)
  58.   part.add_header("Content-class", "urn:content-classes:calendarmessage")
  59.   part.add_header("Filename", filename)
  60.   part.add_header("Path", filename)
  61.   msg.attach(part)
  63.   s = smtplib.SMTP('localhost')
  64.   s.sendmail(msg["From"], [msg["To"]], msg.as_string())
  65.   s.quit()

Cancelling an existing event

You can send a cancel for an existing appointment as well. In order to do this, change method in both places in the code above from REQUEST to CANCEL, and set status</status> to <code>CANCELLED. You must ensure you use the same id as you used to create your original event.

No-response events

If you don't want the appointment participant's Outlook to send you a reply when he or she accepts, you can use the following code:



I would like to use the

I would like to use the script but I am new to python. Could you add and example on how to use it. I am not sure how to specify the sender's email. I tried to setup a structure appointment and add to it the time which seems to work, but not sure how to add the email of the sender that is called using self.getEmail().


Look at line 44:

Look at line 44:

  1. msg["From"] = "{0}".format(self.creator)

Replace the right hand side with a call to your method.

My bad I meant to say the

My bad I meant to say the recipient email not the sender. I am not sure if there is an elegant way I can pass a list of recipients. Based on the code there is self.getEmail(). but I am not sure if getEmail() is something that exists or I have to create it.


Ok, look at line 62 - the

Ok, look at line 62 - the function which sends the e-mail expects a list of strings. So you can pass it in whichever way you like. My version of the script has only one recipient and it is indeed is passed through the class method getEmail(), but you can implement it the most convenient way for your specific case.

More information in the

More information in the documentation for smtplib and MIME* modules

Add new comment

Subscribe to Comments for "Sending Outlook appointments with Python"