Я хочу записать программу, которая посылает электронное письмо с помощью smtplib Python. Я перерыл документ и RFCs, но ничто не мог найти связанным с вложениями. Таким образом я уверен, что существует некоторое высокоуровневое понятие, которое я пропускаю. Может кто-то подсказка меня в о том, как вложения работают в SMTP?
Вы хотите проверить модуль электронной почты
. Он позволяет вам создавать MIME-совместимые сообщения, которые вы затем отправляете с помощью smtplib.
Вот пример, который я вырезал из рабочего приложения, которое мы сделали. Он создает HTML-письмо с вложением Excel.
import smtplib,email,email.encoders,email.mime.text,email.mime.base
smtpserver = 'localhost'
to = ['email@somewhere.com']
fromAddr = 'automated@hi.com'
subject = "my subject"
# create html email
html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
html +='<body style="font-size:12px;font-family:Verdana"><p>...</p>'
html += "</body></html>"
emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
emailMsg['Subject'] = subject
emailMsg['From'] = fromAddr
emailMsg['To'] = ', '.join(to)
emailMsg['Cc'] = ", ".join(cc)
emailMsg.attach(email.mime.text.MIMEText(html,'html'))
# now attach the file
fileMsg = email.mime.base.MIMEBase('application','vnd.ms-excel')
fileMsg.set_payload(file('exelFile.xls').read())
email.encoders.encode_base64(fileMsg)
fileMsg.add_header('Content-Disposition','attachment;filename=anExcelFile.xls')
emailMsg.attach(fileMsg)
# send email
server = smtplib.SMTP(smtpserver)
server.sendmail(fromAddr,to,emailMsg.as_string())
server.quit()
Ну, насадки не обрабатываются никакими особыми способами, это "просто" листья дерева-объекта. Ответы на любые вопросы, касающиеся MIME-совместимых мезастей, можно найти в этом разделе документации по питон-пакету email.
В общем, любой вид вложений (читай: необработанные двоичные данные) может быть представлен с помощью base64.
(or similar) Content-Transfer-Encoding
.
Вот как отправлять письма с прикрепленными zip-файлами и закодированной в utf-8 темой+телом.
Разобраться в этом было не просто из-за отсутствия документации и примеров для данного конкретного случая.
Символы не-ascii в ответах должны быть закодированы, например, ISO-8859-1. Вероятно, существует функция, которая может это сделать.
Совет:
Отправьте себе письмо, сохраните его и изучите содержимое, чтобы понять, как сделать то же самое на Python.
Вот код, для Python 3:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:set ts=4 sw=4 et:
from os.path import basename
from smtplib import SMTP
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
from base64 import encodebytes
def send_email(recipients=["somebody@somewhere.xyz"],
subject="Test subject æøå",
body="Test body æøå",
zipfiles=[],
server="smtp.somewhere.xyz",
username="bob",
password="password123",
sender="Bob <bob@somewhere.xyz>",
replyto="=?ISO-8859-1?Q?M=F8=F8=F8?= <bob@somewhere.xyz>"): #: bool
"""Sends an e-mail"""
to = ",".join(recipients)
charset = "utf-8"
# Testing if body can be encoded with the charset
try:
body.encode(charset)
except UnicodeEncodeError:
print("Could not encode " + body + " as " + charset + ".")
return False
# Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender)
replyto_name, replyto_addr = parseaddr(replyto)
sender_name = str(Header(sender_name, charset))
replyto_name = str(Header(replyto_name, charset))
# Create the message ('plain' stands for Content-Type: text/plain)
try:
msgtext = MIMEText(body.encode(charset), 'plain', charset)
except TypeError:
print("MIMEText fail")
return False
msg = MIMEMultipart()
msg['From'] = formataddr((sender_name, sender_addr))
msg['To'] = to #formataddr((recipient_name, recipient_addr))
msg['Reply-to'] = formataddr((replyto_name, replyto_addr))
msg['Subject'] = Header(subject, charset)
msg.attach(msgtext)
for zipfile in zipfiles:
part = MIMEBase('application', "zip")
b = open(zipfile, "rb").read()
# Convert from bytes to a base64-encoded ascii string
bs = encodebytes(b).decode()
# Add the ascii-string to the payload
part.set_payload(bs)
# Tell the e-mail client that we're using base 64
part.add_header('Content-Transfer-Encoding', 'base64')
part.add_header('Content-Disposition', 'attachment; filename="%s"' %
os.path.basename(zipfile))
msg.attach(part)
s = SMTP()
try:
s.connect(server)
except:
print("Could not connect to smtp server: " + server)
return False
if username:
s.login(username, password)
print("Sending the e-mail")
s.sendmail(sender, recipients, msg.as_string())
s.quit()
return True
def main():
send_email()
if __name__ == "__main__":
main()