Search code examples
pythonicalendarmeeting-request

Unable to set uid for ics by concatenating string variable


When I concatentate the uid with a string variable the meeting invitation ics attachment does not get created properly, but when I hardcode an entire string

"UID: hardcoded string"

This creates the meeting invitation ics attachment correctly. I do not know how to get around this. I do not want to use getuniqueid() function, since I want to be able to cancel the meeting invitation request as well.

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os, datetime

def meeting_invitation(toAddr, body, datetimeStrP, method, uid):
    CRLF = "\r\n"
    attendees = toAddr
    organizer = "ORGANIZER;CN=organiser:mailto:do.not.reply"+CRLF+" @engr.orst.edu"
    fro = "<do.not.reply@me.com>"

    ddtstart = datetimeStrP
    dtoff = datetime.timedelta(hours = 8) # Correct -8 hour UTC offset correction
    dur = datetime.timedelta(minutes = 15)
    ddtstart = ddtstart + dtoff
    dtend = ddtstart + dur
    dtstamp = datetime.datetime.now().strftime("%Y%m%dT%H%M%SZ")
    dtstart = ddtstart.strftime("%Y%m%dT%H%M%SZ")
    dtend = dtend.strftime("%Y%m%dT%H%M%SZ")

    if method == "REQUEST":
        status = "CONFIRMED"
    elif method == "CANCEL":
        status = "CANCELLED"

    description = "DESCRIPTION: Meeting invitation "+CRLF
    attendee = ""
    for att in attendees:
        attendee += "ATTENDEE;CUTYPE=INDIVIDUAL;" \
                    "ROLE=REQ-PARTICIPANT;" \
                    "PARTSTAT=ACCEPTED;" \
                    "RSVP=TRUE"+CRLF+" ;" \
                    "CN="+att+";" \
                    "X-NUM-GUESTS=0:"+CRLF+" " \
                    "mailto:"+att+CRLF
    ical = "BEGIN:VCALENDAR"+CRLF+\
           "PRODID:pyICSParser"+CRLF+\
           "VERSION:2.0"+CRLF+\
           "CALSCALE:GREGORIAN"+CRLF
    ical+="METHOD:"+method+CRLF+\
          "BEGIN:VEVENT"+CRLF+\
          "DTSTART:"+dtstart+CRLF+\
          "DTEND:"+dtend+CRLF+\
          "DTSTAMP:"+dtstamp+CRLF+organizer+CRLF
    ical+= "UID:"+uid+CRLF
    ical+= "UID:%s" %(uid)+CRLF
    # ical['uid']=uid+CRLF
    ical+= attendee+\
           "CREATED:"+dtstamp+CRLF+\
           description+\
           "LAST-MODIFIED:"+dtstamp+CRLF+\
           "LOCATION:"+CRLF+\
           "SEQUENCE:0"+CRLF+\
           "STATUS:"+status+CRLF
    ical+= "SUMMARY: Meeting invitation "+ddtstart.strftime("%Y%m%d @ %H:%M")+CRLF+\
           "TRANSP:OPAQUE"+CRLF+\
           "END:VEVENT"+CRLF+\
           "END:VCALENDAR"+CRLF

    eml_body = body
    msg = MIMEMultipart('mixed')
    msg['Reply-To']=fro
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = "Advising Meeting "+ status #+ dtstart
    msg['From'] = fro
    msg['To'] = ",".join(attendees)

    part_email = MIMEText(eml_body, "plain")
    part_cal = MIMEText(ical,'calendar;method='+method)

    msgAlternative = MIMEMultipart('alternative')
    msg.attach(msgAlternative)

    ical_atch = MIMEBase('application/ics',' ;name="%s"'%("invite.ics"))
    ical_atch.set_payload(ical)
    Encoders.encode_base64(ical_atch)
    ical_atch.add_header('Content-Disposition', 'attachment; filename="%s"'%("invite.ics"))

    eml_atch = MIMEBase('text/plain','')
    Encoders.encode_base64(eml_atch)
    eml_atch.add_header('Content-Transfer-Encoding', "")

    msgAlternative.attach(part_email)
    msgAlternative.attach(part_cal)

    mailServer = smtplib.SMTP('mail.server', 587)
    mailServer.sendmail(fro, attendees, msg.as_string())
    mailServer.close()

Solution

  • Discovered it was a Gmail issue when I was testing, but it works on Outlook, where it will actually be used to send meeting invitations.