如何从outlook.office365.com接收iCalendar(.ics或.ical)会议邀请,以便可以解析它们并将其添加到日历(例如remind + wyrd)?
我花了很长时间努力寻找答案,但没有找到任何答案,所以我想知道我是否错过了一些非常微不足道的东西。
我在 Fedora 20 (Heisenbug) 上使用 Mutt 1.5.22 和 OfflineIMAP 6.5.5。
有许多脚本可用于将 iCalendar 消息解析为可导入日历的格式。这是不是我的问题。我的问题是我什至没有收到 iCalendar 消息,所以我没有什么可解析的。
会议邀请以 Base64 编码的文本/html 消息形式到达我的收件箱。这是不是多部分消息,并且有没有附件。邮件正文包含指向 Microsoft Outlook Web Access (OWA) 的链接。除了将我带到 WebMail 之外,点击该链接似乎没有做任何事情。电子邮件正文的其余部分包含会议邀请的说明。
我尝试转发邀请和将邀请作为附件转发,但这些都不影响消息的格式。
我检查了邮件的标题,但没有发现任何重要的内容。我将它们复制在这里,以防它们对任何人有意义:
Received: from [...] by [...] with Microsoft SMTP Server (TLS) id
[...] via Mailbox Transport; [timestamp]
Received: from [...] by [...] with Microsoft SMTP Server (TLS) id
[...]; [timestamp]
Received: from [...] by [...] with Microsoft SMTP Server (TLS) id
[...]; [timestamp]
Received: from [...] by [...] with mapi id [...]; [timestamp]
From: [meeting organiser]
To: [meeting attendees]
Subject: [meeting subject]
Thread-Topic: [meeting subject]
Thread-Index: [...]
Sender: [sender on behalf of meeting organiser]
Date: [timestamp]
Message-ID: <[...]>
Accept-Language: en-US
Content-Language: en-US
X-MS-Exchange-Organization-AuthAs: Internal
X-MS-Exchange-Organization-AuthMechanism: 03
X-MS-Exchange-Organization-AuthSource: [...]
X-MS-Has-Attach:
X-MS-Exchange-Organization-SCL: -1
X-MS-TNEF-Correlator:
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: base64
MIME-Version: 1.0
我还检查了 WebMail 中邮件的标题。还有更多标题(有些与 tnef 相关),但同样,似乎没有任何内容与日历或邀请相关。
我将“会议邀请”的标题与普通电子邮件的标题进行了比较。唯一的区别是普通电子邮件包含一个额外的标头:“X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply”。
我的 .offlineimaprc 的文件夹过滤器设置为不同步日历文件夹。这是因为每次 OfflineIMAP 尝试同步时,在同步日历文件夹时都会遇到一百多个相同错误的实例:“错误:IMAP 服务器“远程”没有 UID 为“[...]”的消息”。
使用 Python 的 imaplib 检查 Calendar 文件夹:
>>> import imaplib
>>> i = imaplib.IMAP4_SSL("outlook.office365.com", 993)
>>> i.login("[email protected]", "PASSWORD")
('OK', ['LOGIN completed.'])
>>> i.select("Calendar")
('OK', ['159'])
>>> i.fetch(159, "(RFC822)")
('OK', [None])
>>> i.fetch(159, "(RFC822)")
我第二次调用 fetch 时,它返回一条消息:“服务器无法检索以下消息。该消息尚未删除。您可以使用 Outlook 或 Outlook Web App 查看它。您也可以联系发件人查明消息内容。”
在 WebMail 中,我看到日历文件夹(可通过“日历”选项卡访问)具有可见性权限外部组织。目前设置为“不共享”。其他选项包括“仅限可用性”、“有限详细信息”或“完整详细信息”。将权限设置为“完整详细信息”,然后向自己发送会议邀请不会对会议邀请的格式产生任何影响。
作为未接收 iCalendar 消息的解决方法,我使用 Lightning 插件打开 Thunderbird。不知何故,Lightning 插件知道如何接收会议邀请。这些消息仍然显示为 text/html,但 Thunderbird 的状态栏中有一个链接。单击它会打开一个提示,询问是否拒绝或接受邀请。
有人知道为什么来自 Outlook 365 的会议邀请以简单的文本/html 消息而不是 iCalendar 消息的形式到达吗?有什么我可以做的吗?如果 Lightning 插件可以处理邀请,则必须有一个解决方案,例如使用 Microsoft Exchange Web Services (EWS)。如果解决方案需要我编写一个工具,那就这样吧。如果能朝着正确的方向推动,我们将不胜感激。
答案1
SEoF 提供的链接是一个很好的建议。在我看来,这篇博文并不完整,但它确实让我走上了正确的道路。我进行了更多挖掘,并得出了让 Office 365 以 iCalendar (.ics) 格式向我发送会议邀请的完整步骤列表。
请注意,我不是管理员,我不需要联系任何人来授予我任何权限。唯一需要注意的是您需要访问 Windows 盒子。通过 Windows 更改设置后,您可以返回使用之前使用的任何操作系统。我作为普通用户使用 Windows 7 自行执行了以下操作:
- 从以下位置下载并安装 Microsoft .NET Framework 4.5http://www.microsoft.com/en-us/download/details.aspx?id=30653。
- 从以下位置下载并安装 Windows Management Framework 4.0 (Windows6.1-KB2819745-x64-MultiPkg.msu)http://www.microsoft.com/en-us/download/details.aspx?id=40855。
- 以管理员身份运行 PowerShell。
- 设置-ExecutionPolicy -ExecutionPolicy RemoteSigned
- $UserCredential = 获取凭证
- 输入您的电子邮件地址和密码。
- $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUrihttps://outlook.office365.com/powershell-liveid/-凭据 $UserCredential -身份验证基本 -AllowRedirection
- $ImportResults = 导入-PSSession $Session
- 获取 CASMailbox-identity[电子邮件受保护]|格式列表
- 设置 CASMailbox-identity[电子邮件受保护]-PopUseProtocolDefaults:$FALSE -ImapUseProtocolDefaults:$FALSE -PopForceICalForCalendarRetrievalOption:$TRUE -ImapForceICalForCalendarRetrievalOption:$TRUE
- 删除-PSSession $Session
- 设置-ExecutionPolicy -ExecutionPolicy 受限
现在,我的 Linux 上的 mutt 正在检索 iCalendar (.ics) 格式的会议邀请。
答案2
您可以对其进行设置,以便 Office 365/Outlook 通过 Web 界面发送 iCalendar 格式的邀请。
- 登录您的 Office 365 帐户
- 打开邮件应用程序 (Outlook)
- 点击右上角的齿轮图标(设置)
- 在搜索框中输入“imap”
- 选择“Pop 和 IMAP”
- 在底部为 POP 和/或 IMAP 选择“以 iCalendar 格式发送活动邀请”。
- 点击“保存”
您现在应该会收到 iCalendar 格式的所有邀请。
答案3
不完全是OP所要求的,但如果允许第3方逻辑,那么看看很棒的交换库(Python)。获取未来 3 个月事件的快速 py3 示例(请注意,重复项目已扩展):
import arrow # not required, but highly recommended lib for time processing
import base64
from tzlocal import get_localzone
from subprocess import call
from exchangelib import DELEGATE, Account, Credentials, EWSDateTime
CREDENTIALS = Credentials(username='[email protected]', password='topsecret')
ACCOUNT = Account(primary_smtp_address='[email protected]', credentials=CREDENTIALS,
autodiscover=True, access_type=DELEGATE)
def sanitize(p):
'''some .ical files didn't have proper end:vcalendar closure'''
end = 'END:VCALENDAR\n'
s = base64.b64decode(p).decode().replace("\r\n", "\n")
if not s.endswith(end):
s += end
return s
tz = get_localzone()
now = arrow.now()
upper_limit = now.replace(months=+3)
items = ACCOUNT.calendar.view(
start=tz.localize(EWSDateTime(now.year, now.month, now.day)),
end=tz.localize(EWSDateTime(upper_limit.year, upper_limit.month, upper_limit.day)),
)
cals = [] # list of .ical files' contents
for item in items:
cals.append(sanitize(item.mime_content))