使用Python发送时,Office365邮件加密会删除电子邮件附件

时间:2018-05-16 18:17:30

标签: python-3.x smtp office365

我有一个python3 def,它通过office 365帐户发送一条html消息。我们要求使用Office365邮件加密(OME)发送邮件。这为用户提供了一个html附件,使他们可以在线查看电子邮件之前通过office 365登录。我们为将要发送邮件的电子邮件帐户上发送的所有邮件启用了OME。以下是一些观察结果:

  1. 当通过启用OME的帐户通过python def发送时,查看加密邮件时没有附件。
  2. 当通过普通帐户通过python def发送时,附件会按预期显示在电子邮件中
  3. 使用office365网站或Outlook手动通过启用OME的帐户发送电子邮件时,附件会按预期显示在电子邮件中
  4. 电子邮件代码包括附加HTML的图像,并且在正常和加密的邮件中都可以正常显示。
  5. 我打赌我错过了一些随机标题或其他东西 - 有谁知道发生了什么事?这是python代码:

    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.")
    

1 个答案:

答案 0 :(得分:0)

想出来: 我正在比较手动发送和发送的电子邮件源文件与我的python代码,我注意到Content-Type标头是不同的。 python代码使用了&multi39 / multi&related',而手动发送使用了&multi39 / multi&mixed'。这最终成了问题。我将msgRoot = MIMEMultipart('related')更改为msgRoot = MIMEMultipart(),这解决了这个问题。

奇怪的是,python代码发送的非加密电子邮件仍然可以通过附件正确显示 - 只有安全的电子邮件才能与“多部分/相关”相匹配。内容类型。我在一些使用&multi 39 / multipart / related'的示例代码上构建了我的代码,这就是我将其包含在原始代码中的原因。