通过 python 发送时附件不显示在 Outlook 中

Posted

技术标签:

【中文标题】通过 python 发送时附件不显示在 Outlook 中【英文标题】:Attachments don't show up in Outlook when sending via python 【发布时间】:2013-04-24 23:28:16 【问题描述】:

我们正在尝试发送带有附件的电子邮件,但由于某种原因,使用 Outlook 的人无法看到这些附件。

如果他们将电子邮件转发给使用 gmail 的人,它会在 gmail 中显示正常。 如果 gmail 用户将电子邮件转发给 Outlook 用户,它会显示在 Outlook 中(可能是因为 gmail 重建了邮件)。

这是我们用来发送电子邮件的代码:

def send_email(headers=, attachments=[], body=):
    ADDRESS_HEADERS = set(['from', 'to', 'cc', 'bcc', 'reply-to'])
    msg = MIMEMultipart('alternative')
    msg.preamble = "You need a MIME-aware email client to read this email.\n"

    def add_headers():
        def encode_address(v):
            (name, address) = parseaddr(v)
            name = str(Header(unicode(name), 'utf-8'))
            address = address.encode('ascii')
            return formataddr((name, address))

        for key, value in headers.iteritems():
            if not isinstance(value, list):
                value = [value]
            if key.lower() in ADDRESS_HEADERS:
                value = map(encode_address, value)
            msg[key.title()] = u';'.join(value)

    def set_body():
        msg.attach(MIMEText(body.get('text', ''), 'plain', _charset='utf-8'))
        if 'html' in body:
            msg.attach(MIMEText(body['html'], 'html', _charset='utf-8'))

    def attach_file(attachment):
        maintype, subtype = attachment['mimetype'].split("/", 1)
        part = MIMEBase(maintype, subtype)
        filename = attachment['filename']
        name = attachment.get('name', os.path.basename(filename))
        with open(filename, 'rb') as f:
            part.set_payload(f.read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment', filename=name)
        msg.attach(part)

    add_headers()
    map(attach_file, attachments)
    set_body()
    composed = msg.as_string()

    p = subprocess.Popen("sendmail -t", shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    (stdout, stderr) = p.communicate(composed)
    if p.returncode != 0:
        raise IOError(u'\n\n'.format(stdout, stderr).strip())

由于电子邮件实现的碎片化,很难找到任何相关信息。

我们附加的文件是 mime 类型为 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 的 excel 文件

我正在尝试查找有关正在使用的 Outlook 版本的更多信息。

【问题讨论】:

【参考方案1】:

我也有这个问题。您可以通过更改以下行来解决它

msg = MIMEMultipart('alternative') 

msg = MIMEMultipart("multipart")

【讨论】:

【参考方案2】:

这在使用 win32com.client

时非常简单

一旦你创建了你的 SendEmail 对象,它就非常简单了。

import win32com.client
outlook_obj = win32com.client.Dispatch ("Outlook Application")
sendEmail_obj = outlook_obj.CreateItem( 0x0 )

创建一个字符串列表,每个字符串都是您要附加到当前 SendEmail 对象的文件的完整路径(即“C:/User/SubFolder/Filename.pdf”)。

在添加相关字符串后,如收件人的电子邮件地址、主题和正文,如下所示:

sendEmail_obj.To ( "RecipientsEmail@gmail.com" )
sendEmail_obj.Subject ( "Subject Title String" )
sendEmail_obj.Body ("Dear Friend:\n \t I wanted to...") 

您的附件路径字符串项目列表应分别代表您要附加的项目的完整文件系统路径。让我们将此路径字符串列表称为附件路径列表。

for CurrentAttachmentPath in attachment_pathlist : 
    sendEmail_obj.Attachments.Add ( CurrentAttachmentPath )

这应该准备好所有的附件以供发送。然后剩下的就是……

sendEmail_obj.Send()

【讨论】:

【参考方案3】:

您可以尝试两件事。首先,将 mimetype 设置为标准的 bag-of-bits,无论您真正发送的是什么类型,我都有更好的可靠性:

part = MIMEBase('application', "octet-stream")

其次,看看这样更改附件标题是否有帮助:

part.add_header('Content-Disposition', 'attachment; filename="%s"' % name) 

像这样设置标题对我们发送到 Outlook 有效。这是使用电子邮件版本“4.0.3”。不知道你用的是什么版本。如您所知,它们有很多。

【讨论】:

part.add_header('Content-Disposition', 'attachment', filename=name) 应该和你写的一样。我会尝试概括 mime 类型。 我在使用part = MIMEBase('application', 'vnd.openxmlformats-officedocument.spreadsheetml.sheet') 时也遇到了问题。 IMO part = MIMEBase('application', "octet-stream") 最适合任何类型

以上是关于通过 python 发送时附件不显示在 Outlook 中的主要内容,如果未能解决你的问题,请参考以下文章

通过 Codeigniter 发送带附件的电子邮件时出错

python 3 smtplib:当gnupg处于活动状态时,二进制附件在烧瓶中编码不正确

使用python发送带有(docx)附件的邮件

PHP - 发送带附件的电子邮件不显示邮件内容

通过 Gmail API 发送 Excel 文件,但附件已损坏

用Python实现带附件发送邮件的功能