iCalendar约会是“不支持的日历message.ics" [英] iCalendar appointment is a 'not supported calendar message.ics'

查看:152
本文介绍了iCalendar约会是“不支持的日历message.ics"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试通过python自动发送Outlook日历邀请.我可以发送电子邮件并附加邀请;但是,邀请是不支持的日历message.ics".最近两个星期,我一直在努力弄清楚该如何做.我什至尝试使用win32com.client;但是该软件包无法像我在在此处发布所述那样,从单独的帐户发送电子邮件.

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 posted about here.

下面是我用于生成和发送不支持的日历消息.ics"的代码:

Below is the code I used to generate and send the 'not supported calendar message.ics':

# 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()

另一个有趣的注意事项:如果转发了邀请,则将识别ics.例如,我生成了要发送给自己的电子邮件,然后将其作为不支持的日历message.ics"接收.如果我随后将邀请转发给我的同事,他将其视为常规日历邀请.我测试了一下这是否只是我的安装;但是,他复制了代码并遇到了相同的问题-无法识别第一条消息,但是转发给我的邀请被接受了.

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.

让我知道是否需要进一步澄清.

Let me know if I need to clarify anything further.

推荐答案

我一直在为此苦苦挣扎,但是我发现了一种可以避免该问题的hack ...

I struggled with this FOREVER but I figured out a hack that avoids the problem...

问题在于,TZ信息在执行to_ical()函数时会被icalendar破坏.

The problem is that the TZ info is getting mangled by icalendar when it does its to_ical() function.

就我们的示例而言,假设您在创建日期并将其提供给icalendar时将时区设置为"America/New_York",最终将生成如下所示的DTSTART/DTEND:

For the sake of our example, let's say that your timezone is 'America/New_York' when you create your dates and then feed them to icalendar, it eventually generates DTSTART/DTEND that look like this:

DTSTART; TZID = EDT; VALUE = DATE-TIME:20180622T123000 DTEND; TZID = EDT; VALUE = DATE-TIME:20180622T133000

DTSTART;TZID=EDT;VALUE=DATE-TIME:20180622T123000 DTEND;TZID=EDT;VALUE=DATE-TIME:20180622T133000

请注意,它已方便地"将"America/New_York"替换为"EDT". Outlook认为这不是真的.

Note that it has "conveniently" replaced 'America/New_York' with 'EDT'. Outlook does not think this is a real thing.

这是我用来修复它的代码.而不是使用raw:

Here's the code I used to fix it. Instead of using the raw:

open('PythonCalendarEvent_1.ics', 'w').writelines(cal.to_ical())

改为使用此:

import re
tzname = 'America/New_York'
ical_string = cal.to_ical().decode('utf-8')
ical_string = re.sub(r"TZID=[^;]*", 'TZID='+tzname, ical_string)
ical_bytes = ical_string.encode('utf-8')
open('PythonCalendarEvent_1.ics', 'w').writelines(ical_bytes)

如果这不能解决您的问题,我将清理所有功能并将其发布...

If this doesn't fix your problem I'll clean up my full function and post it...

这篇关于iCalendar约会是“不支持的日历message.ics"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆