6

Trying to write a python script to send an outlook email invite. Used instructions from here: http://www.baryudin.com/blog/sending-outlook-appointments-python.html However, I keep getting a "not supported calendar message.ics" attachemnt with my email. Code is below:

    import random

    import smtplib

    import email.MIMEText
    import email.MIMEBase

    from datetime import datetime
    from email.MIMEMultipart import MIMEMultipart

    import icalendar

    from pytz import timezone

    LOCAL_TZ = timezone("US/Eastern")

    def send_appointment(subject, description):
        start_dt = LOCAL_TZ.localize(datetime(2016, 6, 3, 17, 0, 0))
        end_dt = LOCAL_TZ.localize(datetime(2016, 6, 3, 18, 0, 0))

        cal = icalendar.Calendar()
        cal.add("prodid", "-//My oncall calendar application//test.com")
        cal.add("version", "2.0")
        cal.add("method", "REQUEST")

        event = icalendar.Event()
        event.add("attendee", MY_EMAIL)
        event.add("organizer", MY_EMAIL)
        event.add("status", "confirmed")
        event.add("summary", subject)
        event.add("description", description)
        event.add("location", "my desk")
        event.add("dtstart", start_dt)
        event.add("dtend", end_dt)
        event.add("dtstamp", start_dt)
        event["uid"] = random.random()
        event.add("priority", 5)
        event.add("sequence", 1)
        event.add("created", LOCAL_TZ.localize(datetime.now()))

        alarm = icalendar.Alarm()
        alarm.add("action", "DISPLAY")
        alarm.add("description", "Reminder")
        alarm.add("TRIGGER;RELATED=START", "-PT{0}H".format(1))
        event.add_component(alarm)

        cal.add_component(event)

        msg = MIMEMultipart("alternative")
        msg["Subject"] = subject
        msg["From"] = MY_EMAIL
        msg["To"] = MY_EMAIL
        msg["Content-class"] = "urn:content-classes:calendarmessage"

        msg.attach(email.MIMEText.MIMEText(description))

        filename = "invite.ics"

        part = email.MIMEBase.MIMEBase("text", "calendar", method="REQUEST",                     name=filename)
        part.set_payload(cal.to_ical())
        email.Encoders.encode_base64(part)
        part.add_header("Content-Description", filename)
        part.add_header("Content-class", "urn:content-classes:calendarmessage")
        part.add_header("Filename", filename)
        part.add_header("Path", filename)
        msg.attach(part)

        s = smtplib.SMTP("localhost")
        s.sendmail(MY_EMAIL, MY_EMAIL, msg.as_string())
        s.quit()

    def main():
        send_appointment("test", "desc")

    if __name__=="__main__":
        main()

NOTE: I defined MY_EMAIL but just not putting it here.

The .ics file generated is below.

    BEGIN:VCALENDAR
    VERSION:2.0
    PRODID:-//My oncall calendar application//test.com
    METHOD:REQUEST
    BEGIN:VEVENT
    SUMMARY:test
    DTSTART;TZID=US/Eastern;VALUE=DATE-TIME:20160603T170000
    DTEND;TZID=US/Eastern;VALUE=DATE-TIME:20160603T180000
    DTSTAMP;VALUE=DATE-TIME:20160603T210000Z
    UID:0.669475599056
    SEQUENCE:1
    ATTENDEE:myemail@somewhere.com
    CREATED;VALUE=DATE-TIME:20160603T204723Z
    DESCRIPTION:desc
    LOCATION:my desk
    ORGANIZER:myemail@somewhere.com
    PRIORITY:5
    STATUS:confirmed
    BEGIN:VALARM
    ACTION:DISPLAY
    DESCRIPTION:Reminder
    TRIGGER;RELATED=START:-PT1H
    END:VALARM
    END:VEVENT
    END:VCALENDAR

EDIT: Ok figured out the problem I think. It only understands utc timezone. So if I changed the start and end datetimes to the following then the I get a proper calendar invite.

    start_dt = datetime(2016, 6, 3, 17, 0, 0, tzinfo=pytz.utc)
    end_dt = datetime(2016, 6, 3, 18, 0, 0, tzinfo=pytz.utc)

Not entirely sure why it cannot understand other time zones. Looking at the .ics file, the date time fields look like the following.

    DTSTART;VALUE=DATE-TIME:20160603T170000Z
    DTEND;VALUE=DATE-TIME:20160603T180000Z

as opposed to

    DTSTART;TZID=US/Eastern;VALUE=DATE-TIME:20160603T170000
    DTEND;TZID=US/Eastern;VALUE=DATE-TIME:20160603T180000

The question now is why it cannot handle other timezones but I guess that should be another post.

Anon
  • 101
  • 1
  • 6

2 Answers2

4

Ok figured out the problem I think. It only understands utc timezone. So if I changed the start and end datetimes to the following then the I get a proper calendar invite.

    start_dt = datetime(2016, 6, 3, 17, 0, 0, tzinfo=pytz.utc)
    end_dt = datetime(2016, 6, 3, 18, 0, 0, tzinfo=pytz.utc)

Not entirely sure why it cannot understand other time zones. Looking at the .ics file, the date time fields look like the following.

    DTSTART;VALUE=DATE-TIME:20160603T170000Z
    DTEND;VALUE=DATE-TIME:20160603T180000Z

as opposed to

    DTSTART;TZID=US/Eastern;VALUE=DATE-TIME:20160603T170000
    DTEND;TZID=US/Eastern;VALUE=DATE-TIME:20160603T180000
Anon
  • 101
  • 1
  • 6
0

Not sure if you still need this but I figured it out. See my reply over here. Short answer is that it's not actually the timezone that's giving you problems. I had the same issue you did and made the change you suggested. Outlook did then recognize my ics file but the times were wrong. Maddening. My reply in the other post shows how I fixed it for me...