I have a python3 def that sends an html message via an office 365 account. We have a requirement that the message be sent with Office365 message encryption (OME). This gives the user an html attachment makes them log in via office 365 before viewing the email online. We have enabled OME for all messages sent on the email account that will be sending the message. Here are some observations:
I bet I am missing some random header or something - does anyone know what is going on? Here is the python code:
def sendHTMLEmail(
emaillist,
subject,
body,
altBody,
logger,
mailuser,
mailpassword,
fileAttachments=None,
embeddedImages=None
):
"""
Send an html-enabled email to a number of recipients. This method includes the options of embedding images in the email,
attaching files to the email, and providing alternative plain text in case of an error rendering the HTML.
# Arguments
emaillist (list[string]): List of email addresses to send to
subject (string): Subject line of the email
body (string): Body of the email. This can be plain text or HTML, depending on the email.
altBody (string): Alternate body text of the email. This will be displayed if the HTML cannot be rendered.
logger (JvpyLog): optional logger override parameter
mailuser (string): SMTP username to send the mail as
mailpassword (string): login password of the SMTP user
fileAttachments (list[string]): list of fully qualified filenames to attach to the email
embeddedImages (list[dict]): list of embeddedImage dicts specifying images to be embedded in the HTML boddy of the email
# Special Types
###### embeddedImages [dict]:
```python
{
filename (string): fully qualified filename of the image
imageid (string): unique id for the image. This will be refrernced in the HTML body of the email and repaced by the actual image.
}
```
"""
logger.info("Sending email to the following recipients: " + str(emaillist))
# Define these once; use them twice!
strFrom = mailuser
strTo = ", ".join(emaillist)
# Create the root message and fill in the from, to, and subject headers
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = subject
msgRoot['From'] = strFrom
msgRoot['To'] = strTo
msgRoot.preamble = 'This is a multi-part message in MIME format.'
# Encapsulate the plain and HTML versions of the message body in an
# 'alternative' part, so message agents can decide which they want to display.
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)
msgText = MIMEText(altBody)
msgAlternative.attach(msgText)
# We reference the image in the IMG SRC attribute by the ID we give it below
msgText = MIMEText(body, 'html')
msgAlternative.attach(msgText)
# embed images if populated
if embeddedImages is not None:
for image in embeddedImages:
logger.info("Embedding Image: " + str(image['filename']) + " as content id: " + str(image['imageid']))
fp = open(image['filename'], 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# Define the image's ID as referenced above
msgImage.add_header('Content-ID', image['imageid'])
msgRoot.attach(msgImage)
# add attachements if populated
if fileAttachments is not None:
for filename in fileAttachments:
logger.info("Attaching File: " + str(filename))
part = MIMEApplication(
open(filename,"rb").read(),
Name=os.path.basename(filename)
)
part['Content-Disposition'] = 'attachment; filename="{0}"'.format(os.path.basename(filename))
## add mimetype based on the file extension
mimetype = mimetypes.types_map["." + os.path.basename(filename).lower().split(".")[1]]
part['Content-Type'] = mimetype + '; name="{0}"'.format(os.path.basename(filename))
msgRoot.attach(part)
# Send the email (this example assumes SMTP authentication is required)
server = smtplib.SMTP('smtp.office365.com', 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login(mailuser, mailpassword)
server.sendmail(strFrom, emaillist, msgRoot.as_string())
server.quit()
logger.info("email sent.")
Figured it out: I was comparing the email source files from a manual send and a send with my python code, and I noticed that the Content-Type header was different. The python code used 'multipart/related', while the manual send used 'multipart/mixed'. This ended up being the problem. I changed msgRoot = MIMEMultipart('related')
to msgRoot = MIMEMultipart()
, and this resolved the issue.
The strange thing is that non-encrypted emails sent by the python code still displayed properly with an attachment - it was only secure emails that didn't play nice with the 'multipart/related' Content type. I built my code on some sample code that used 'multipart/related', so that is why I included it in my original code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.