Как я отправляю вложения с помощью SMTP?

Я хочу записать программу, которая посылает электронное письмо с помощью smtplib Python. Я перерыл документ и RFCs, но ничто не мог найти связанным с вложениями. Таким образом я уверен, что существует некоторое высокоуровневое понятие, которое я пропускаю. Может кто-то подсказка меня в о том, как вложения работают в SMTP?

21
задан Jason Baker 27 December 2009 в 14:31
поделиться

4 ответа

Вы хотите проверить модуль электронной почты . Он позволяет вам создавать MIME-совместимые сообщения, которые вы затем отправляете с помощью smtplib.

.
11
ответ дан 29 November 2019 в 06:29
поделиться

Вот пример, который я вырезал из рабочего приложения, которое мы сделали. Он создает 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()
19
ответ дан 29 November 2019 в 06:29
поделиться

Ну, насадки не обрабатываются никакими особыми способами, это "просто" листья дерева-объекта. Ответы на любые вопросы, касающиеся MIME-совместимых мезастей, можно найти в этом разделе документации по питон-пакету email.

В общем, любой вид вложений (читай: необработанные двоичные данные) может быть представлен с помощью base64. (or similar) Content-Transfer-Encoding.

3
ответ дан 29 November 2019 в 06:29
поделиться

Вот как отправлять письма с прикрепленными 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()
3
ответ дан 29 November 2019 в 06:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: