Search code examples
pythonexchange-servermimertficalendar

Sending to Exchange: How to Disable Disable Lossy Conversion of HTML to RTF?


I have a python script which sends a multipart email with text, html, and ics attachments. The idea is that a modern email client will render the HTML part and offer to add the event to the user's calendar.

Code looks like:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from icalendar import Calendar, Event, UTC, vText, vCalAddress
# ... set up calendar invite, render text and html templates ...
msg = MIMEMultipart('alternative')
msg_text = MIMEText(body_text, 'plain', 'utf-8')
msg_html = MIMEText(body_html, 'html', 'utf-8')
meeting = MIMEText(cal.as_string(), 'calendar;method=REQUEST', 'utf-8')
meeting.set_param('method', 'REQUEST')
meeting.set_param('name', 'meeting.ics')
meeting.add_header('Content-class', 'urn:content-classes:calendarmessage')
# ... set up various message attributes: to/from/subject ...
msg.add_header('Content-class', 'urn:content-classes:calendarmessage')
msg.attach(msg_text)
msg.attach(msg_html)
msg.attach(meeting)
s = smtplib.SMTP(smtp_server)
s.sendmail(sender, send_to, msg.as_string())

This works: I get the message, it is displayed as HTML, and I can easily add the event to my calendar in Outlook and Mac Mail. However, the HTML is broken. Here is the telltale in the HTML:

<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from rtf -->

Here is what I know so far:

  • If I drop the calendar attachment, the HTML makes it through without conversion.
  • I can only get the calendar invite to work if I attach it to the message last.

So, something about having the calendar invite attached causes Exchange to mess up my HTML message. Is there maybe a header I can add to the message or the HTML to ask Microsoft to pretty please not convert my HTML to RTF?


Solution

  • Outlook only works with RTF when it comes to appointments, tasks and contacts. If a meeting invitation comes with an HTML body, it gets converted to RTF.

    UPDATE: as of Outlook 2016, this is no longer the case: Outlook now natively supports HTML for the appointments and tasks. HTML is stored in PR_HTML (or RTF-wrapped HTML in PR_RTF_COMPRERSSED), and you can specify the format just like with regular email messages. It is still not exposed on the Outlook Object Model level unfortunately - there is no AppointmentItem.HTMLBody property yet.