title: iCalendar appointment is a 'not supported calendar message.ics'
body: <p>Trying to automate sending an Outlook calendar invite via python. I am able to send the email and attach the invite; however, the invite is a 'not supported calendar message.ics'. I have spent the last two weeks trying to figure out how to do this. I even tried using win32com.client; but that package does not enable you to send the email from a separate account as I had <a href="https://stackoverflow.com/a/48543958/9274889">posted about here</a>. </p>
  
  <p>Below is the code I used to generate and send the 'not supported calendar message.ics':</p>
  
  <pre><code># email related imports
  
  import smptlib
  import email
  from email.MIMEMultipart import MIMEMultipart
  from email.MIMEBase import MIMEBase
  from email import Encoders
  
  # calendar related imports
  
  import icalendar
  from icalendar import Calendar, Parameters, Todo
  from icalendar.prop import vDatetime, vCalAddress, vText, vInt, vBoolean, vDDDTypes
  import uuid
  
  #other imports
  
  import pytz
  from datetime import datetime, date, time, timedelta
  
  
  # set people parameters
  
  sender = 'thing1@example.com'
  recipients = 'thing2@example.com'
  
  attendee = vCalAddress(recipients)
  attendee.params['cn'] = vText('Thing 1')
  attendee.params['RSVP'] = vText('TRUE')
  
  organizer = vCalAddress(sender)
  organizer.params['cn'] = vText('Thing 2')
  
  the_sender = vCalAddress(sender)
  the_sender.params['cn'] = vText('Thing 2')
  
  # set timing parameters 
  
  location = 'Home'
  tz = pytz.timezone("US/Pacific") # timezone to use for our dates -- change 
  as needed
  appt_time = tz.localize(datetime(2018, 1, 31, 12, 0))
  duration = 30
  reminder_min = 15
  
  # set info parameters
  
  subject = 'My Cool Event'
  description = 'this better work!'
  summary = 'python calendar invite testing'
  
  
  # create calendar object
  
  cal = icalendar.Calendar()
  cal.add('prodid', vText('-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN'))
  cal.add('version', vInt(2.0))
  cal.add('method', vText('REQUEST'))
  cal.add('X-MS-OLK-FORCEINSPECTOROPEN', vBoolean(True)) # creates one instance of the event
  
  # create the timezone 
  
  tz = icalendar.Timezone()
  tz.add('tzid', vText('Pacific Standard Time'))
  cal.add_component(tz)
  
  # create the calendar event
  
  event = icalendar.Event()
  event.add('method', vText('REQUEST'))
  event.add('tzid', vText('Pacific Standard Time'))
  event.add('attendee', attendee, encode=0)
  event.add('class', vText('PUBLIC'))
  event.add('created', vDDDTypes(datetime.now()))
  event.add('description', vText(description))
  event.add('dtend', vDDDTypes((appt_time + timedelta(minutes = duration))))
  event.add('dtstart', vDDDTypes(appt_time))
  event.add('location', vText(location))
  event.add('from', the_sender)
  event.add('organizer', the_sender)
  event.add('priority', vInt(5))
  event.add('sequence', vInt(0))
  event.add('summary', vText(summary))
  event.add('transp', vText('opaque')) # Specifies whether or not this appointment is intended to be visible in availability searches
  event.add('uid',vText(uuid.uuid4()))
  event.add('X-MICROSOFT-CDO-BUSYSTATUS', vText('BUSY')) # sets the busy status of the appointment to busy
  event.add('X-MICROSOFT-CDO-IMPORTANCE', vInt(1)) # sets the importance of the appointment (0,1,2)
  event.add('X-MICROSOFT-DISALLOW-COUNTER', vBoolean(False))
  event.add('X-MS-OLK-APPTSEQTIME', vDDDTypes(datetime.now()))
  event.add('X-MS-OLK-AUTOFILLLOCATION', vBoolean(False)) # specifies whether the location is being automatically populated with recipients of type RESOURCE.
  event.add('X-MS-OLK-CONFTYPE', vInt(0)) # specifies the type of conferencing that is enabled on the appointment
  
  # set an alarm for a reminder notice
  
  alarm = icalendar.Alarm()
  alarm.add("action", "DISPLAY")
  alarm.add('description', "Reminder")
  alarm.add("TRIGGER;RELATED=START", "-PT{0}M".format(reminder_min))
  event.add_component(alarm)
  cal.add_component(event)
  
  # write calendar event to file
  
  open('PythonCalendarEvent_1.ics', 'w').writelines(cal.to_ical())
  
  # generate message with (Multi-Purpose Internet Mail Extensions)
  
  msg = MIMEMultipart('mixed')
  msg["Subject"] = subject
  msg["From"] = sender
  msg['To'] = recipients
  
  # attach calendar invite to email message
  
  filename = "PythonCalendarEvent_1.ics"
  
  cal_part = MIMEBase('text', 'calendar', **{'method' : 'REQUEST', 'name' : filename})    
  cal_part.set_payload(open(filename,"rb").read())
  cal_part.set_type('text/calendar; charset=UTF-8; method=REQUEST; component = VEVENT')
  email.Encoders.encode_base64(cal_part)
  cal_part.add_header('Content-Type', 'text/calendar')
  cal_part.add_header('charset', 'UTF-8')
  cal_part.add_header('component', 'VEVENT')
  cal_part.add_header('method', 'REQUEST')
  cal_part.add_header('Content-class', 'urn:content-classes:appointment')
  cal_part.add_header('Content-ID', 'calendar_message')
  cal_part.add_header('Content Description', filename)
  cal_part.add_header("Filename", filename)
  cal_part.add_header("Path", filename)
  msg.attach(cal_part)
  
  # send the email at last
  
  s =  smtplib.SMTP(_insert_host_as_string_here_)
  s.sendmail(sender, recipients, msg.as_string())
  s.quit()
  </code></pre>
  
  <p>Another interesting note: if the invite is forwarded, the ics is recognized. For example I generate the email to send to myself and I receive it as a 'not supported calendar message.ics'. If I then forward the invite to my coworker, he sees it as a regular calendar invite. I tested to see if this was just my install; however, he replicated the code and had the same issue--first message was not recognized, but the forwarded invite to me was.</p>
  
  <p>Let me know if I need to clarify anything further.</p>