我正在为我的应用程序编写一个电子邮件系统。 只是一封带有附件(pdf 文件)的简单电子邮件,需要在完成一个步骤后发送。
在我可以测试的每个客户端(Linux 上的 Geary、移动端的 Outlook、网络上的 Outlook、我们自己的使用 roundcube 的电子邮件系统)上,我的附件都完美地通过了,我们没有问题。
除了 windows 上的 Outlook 客户端,我们的邮件都是直接收到的,没有附件。
我尝试将我的附件更改为 .png 、 .jpg 甚至 .docx 并且对于所有文件类型,它与上面的问题相同。
我正在使用这个代码:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import base64
FROM = "sender@mail.com"
data = request.data['data']
base64_string = data['file']
base64_string = base64_string.split(',')[1]
attachment_data = base64.b64decode(base64_string)
PASS = ""
SERVER = 'mail.ourhost.be'
TO = "receiver@mail.com"
msg = MIMEMultipart('alternative')
msg['Subject'] = "subject"
msg['From'] = FROM
msg['To'] = TO
html = f"""\
<html style="font-family: Heebo;">
my email content
</html>
"""
part2 = MIMEText(html, 'html')
msg.attach(part2)
# Add the decoded attachment data to the email
part = MIMEBase('application', 'pdf')
part.set_payload((attachment_data))
encoders.encode_base64(part)
filename = f'name.pdf'
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
Windows 上的 Outlook 有什么特别需要注意的吗?
我也有问题,我的部分联系人没有收到附件。
做一些研究我发现了这篇 SO 帖子: SMTPlib 未收到附件
通过比较代码片段,我能辨别出的唯一相关区别是,在问题中......
msg = MIMEMultipart('alternative')
... 被使用,而在工作响应中 MIMEMultipart 被调用而没有参数:
msg = MIMEMultipart()
根据文档 (https://docs.python.org/3/library/email.mime.html) 这将默认为 _subtype='mixed'。
class email.mime.multipart.MIMEMultipart(_subtype='mixed', boundary=None, _subparts=None, *, policy=compat32, **_params)
根据 Mail multipart/alternative vs multipart/mixed 选择的类型取决于您的消息内容。
在您的示例中,您没有使用替代纯文本,因此“混合”(默认)可能是 MIMEMultipart 的正确 _subtype?
msg = MIMEMultipart()
请告诉我这是否能为您解决问题。
致以诚挚的问候!
附言这是我的脚本。实际上,我从 toml 配置文件中读取参数,因为将登录信息硬编码到脚本中是有问题的。我的例子也有一些基本的日志记录和一些功能被分成不同的功能。
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import make_msgid, formatdate
from pathlib import Path
import logging
# configure basic logging
logging.basicConfig(
filename="send_mail.log",
filemode="a",
format="%(name)s - %(levelname)s - %(message)s",
)
def send_mail(sender_email, receiver_email, pdf_pathstring, email_plain_text="Add your message here."):
"""This is a wrapper function to send emails"""
message = create_message(sender_email, receiver_email, pdf_pathstring, email_plain_text)
send_smtp(message, sender_email, receiver_email)
def create_message(sender_email, receiver_email, pdf_pathstring, email_plain_text):
"""This function assembles the different parts of the email, so that it can then be sent by send_smtp"""
# create a MIMEMultipart object
message = MIMEMultipart()
message["Subject"] = "Example_subject"
message["From"] = sender_email
message["To"] = receiver_email
message["Message-ID"] = make_msgid()
message["Date"] = formatdate()
# Turn the email_plain_text into plain MIMEText objects and attach to message
plaintext_part = MIMEText(email_plain_text, "plain")
message.attach(plaintext_part)
# Read in pdf
pdf_path = Path(pdf_pathstring)
filename = pdf_path.name
# Open PDF file in binary mode
with open(pdf_path, "rb") as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
attachment_part = MIMEBase("application", "octet-stream")
attachment_part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(attachment_part)
# Add header as key/value pair to attachment part
attachment_part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",
)
# Add attachment_part to MIMEMultipart message
message.attach(attachment_part)
return message
def send_smtp(message, sender_email, receiver_email):
"""This function creates a smtp_object and sends the mail including the attachments in the message object"""
sender_email = sender_email
password = "************"
smtp_object = smtplib.SMTP_SSL(exampleserver.ch, 465)
smtp_object.ehlo() # listen for server response
smtp_object.login(sender_email, password)
try:
smtp_object.sendmail(sender_email, receiver_email, message.as_string())
logging.warning(f"Message sent to {receiver_email}")
print(f"Message sent to {receiver_email}")
except:
logging.exception(f"Couldn't sent mail to {receiver_email} because of an exception:")
print(f"Couldn't sent mail to {receiver_email} because of an exception.")
smtp_object.quit() # terminate the connection