Форум сайта python.su
Требуется отправить письмо с вложением. Почитал документацию, полазил по форуму, попробовал.
Сразу же выяснилось: вся документация в подавляющем большинстве относиться к версии 2Х, тут же появились проблемы по подключению соответствующих модулей и с кодировкой (отдельное спасибо Андрею Светлову за помощь в решении проблем с кодировкой).
в результате получилось следующее:
# -*- coding: utf-8 -*-
from smtplib import SMTP
from email.header import Header, make_header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.application import MIMEApplication
from email.encoders import encode_base64
import os
russian = ‘windows-1251’
msg = MIMEMultipart()
msg = make_header()
msg = make_header()
msg = Header(“прЮвет”, russian)
m = “”“привет от Васи”“”
text = MIMEText(m.encode('cp1251'), ‘plain’, russian)
msg.attach(text)
fp = open(“D:\\Temp\\aa.cdr”, “rb”)
to_attach = MIMEBase(“application”, “octet-stream”)
to_attach.set_payload(fp.read())
encode_base64(to_attach)
to_attach.add_header(“Content-Disposition”, “attachment”, filename=“dfdfd”)
msg.attach(to_attach)
fp.close()
fromaddr = “fromuser@aa.aa.ru”
toaddr = “touser@bb.bb.ru”
connect = SMTP('XX.XX.XX.XX')
connect.set_debuglevel(1)
connect.sendmail(fromaddr, toaddr, msg.as_string())
connect.quit()
В данном примере не работает блок с прикреплением постороннего файла, выдаёт что-то типа
raise TypeError('string payload expected: %s' % type(payload))
eError: string payload expected: <class ‘bytes’>
А хотелось бы прикреплять файлы (как текстовые так и бинарные). в общем прошу помочь :)
Офлайн
при отправке через смтп и при работе через сокеты все надо кодировать в байты, а при приеме декодировать.
Там есть функции decode и encode посмотри примеры в доках.
Вот я тут как-то рзвлекался:
sock.send(str.encode1(mail))
print("Получено от %s:%s:" % addr, mail.decode())
Отредактировано (Янв. 15, 2010 12:34:49)
Офлайн
fp = open("D:\\Temp\\ad.cdr", "rb")
to_attach = MIMEBase("application", "octet-stream")
to_attach.set_payload(fp.read())
encode_base64(to_attach)
to_attach.add_header("Content-Disposition", "attachment", filename="dfdfd")
msg.attach(to_attach)
fp.close()
msg.as_string()
Отредактировано (Янв. 18, 2010 05:45:26)
Офлайн
заменил
connect.sendmail(fromaddr, toaddr, msg.as_string())
connect.sendmail(fromaddr, toaddr, msg.as_string)
File "D:\xxx\mail.py", line 41, in <module>
connect.sendmail(fromaddr, toaddr, smail)
File "C:\program files\Python31\lib\smtplib.py", line 699, in sendmail
esmtp_opts.append("size=%d" % len(msg))
ypeError: object of type 'method' has no len()
Офлайн
Проблему так и не решил
вот ещё интересно:
fp = open("D:\\Temp\\xx.cdr", "rb")
to_attach = MIMEBase("application", "octet-stream")
to_attach.set_payload(fp.read())
encode_base64(to_attach)
to_attach.add_header("Content-Disposition", "attachment", filename="dfdfd")
msg.attach(to_attach)
fp.close()
msg.as_string(
encode_base64(to_attach)
print(encode_base64(to_attach))
Офлайн
Блин, запустил пример на версии 2.5 - всё заработало. Глючный он, питон, и это плохо. Причём пример не отличается от http://docs.python.org/3.1/library/email-examples.html, а это вообще ни в какие ворота не лезет. Посмотрел я по этой ссылке и возникли такие вопросы: почему есть отдельные типы передаваемых данных как картинка, звук и текст, а также просто “MIMEBase”? Для чего всё это? или картинки он как-то по особому передаёт, более эффективно? Тогда почему нет типа по передаче видео например, архивов, исполняемых файлов?
Офлайн
Оставьте пока эти далеко идущие выводы о глючности питона, ладно?
Я правильно понял, что вам нужно отправить письмо с вложениями в python3.1, а у вас не получается?
Могу посмотреть вечером. Сейчас под рукой нет тройки.
Офлайн
Оставьте пока эти далеко идущие выводы о глючности питона, ладно?Буду очень благодарен если если найдёте ошибку, или объясните чего я не учёл. Заранее большое спасибо.
Я правильно понял, что вам нужно отправить письмо с вложениями в python3.1, а у вас не получается?
Могу посмотреть вечером. Сейчас под рукой нет тройки.
Офлайн
Вы не учли того, что в третьем Питоне в отличие от предыдущих read() возвращает bytes, а не string.
Собственно вам об этом и сказали: string payload expected: <class ‘bytes’>
Решение состоит в том, чтобы отдать set_payload то, что он хочет, то есть сконвертить полученые из файла байты в строку. Естественно, после обработки base64. Как-нибудь так, например:
from base64 import b64encode
outer = MIMEMultipart()
fp = open(fname, 'rb')
msg = MIMEBase("application", "octet-stream")
msg.set_payload(str(b64encode(fp.read()), 'ASCII'))
msg.add_header('Content-Disposition', 'attachment', filename=fname)
fp.close()
outer.attach(msg)
print(outer.as_string())
Офлайн
Большое спасибо за разъяснение. Но вообще интересно: есть “encode_base64()”, а есть “b64encode()”, как-то выглядит нелогично… Сам бы наверное не разобрался.
Офлайн