Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 15, 2010 12:01:00

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Требуется отправить письмо с вложением. Почитал документацию, полазил по форуму, попробовал.
Сразу же выяснилось: вся документация в подавляющем большинстве относиться к версии 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’>

А хотелось бы прикреплять файлы (как текстовые так и бинарные). в общем прошу помочь :)



Офлайн

#2 Янв. 15, 2010 12:32:03

Zubchick
От:
Зарегистрирован: 2009-07-08
Сообщения: 613
Репутация: +  0  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

при отправке через смтп и при работе через сокеты все надо кодировать в байты, а при приеме декодировать.
Там есть функции decode и encode посмотри примеры в доках.

Вот я тут как-то рзвлекался:

sock.send(str.encode1(mail))

print("Получено от %s:%s:" % addr, mail.decode())



Отредактировано (Янв. 15, 2010 12:34:49)

Офлайн

#3 Янв. 18, 2010 05:40:14

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

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()
Вот этот кусок вроде читает файл как “bytes”, потом метод “encode_base64” перекодирует, потом присобачиваем к письму, вроде всё на месте :(



Отредактировано (Янв. 18, 2010 05:45:26)

Офлайн

#4 Янв. 20, 2010 10:51:50

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

заменил

connect.sendmail(fromaddr, toaddr, msg.as_string())
на
connect.sendmail(fromaddr, toaddr, msg.as_string)
(убрал скобки в 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()
помогите пожалуйста, вообще понять не могу в чём проблема…



Офлайн

#5 Янв. 26, 2010 10:41:25

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Проблему так и не решил
вот ещё интересно:

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))
То вываливает: “None”
Может проблема где-то здесь?



Офлайн

#6 Янв. 28, 2010 10:07:48

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Блин, запустил пример на версии 2.5 - всё заработало. Глючный он, питон, и это плохо. Причём пример не отличается от http://docs.python.org/3.1/library/email-examples.html, а это вообще ни в какие ворота не лезет. Посмотрел я по этой ссылке и возникли такие вопросы: почему есть отдельные типы передаваемых данных как картинка, звук и текст, а также просто “MIMEBase”? Для чего всё это? или картинки он как-то по особому передаёт, более эффективно? Тогда почему нет типа по передаче видео например, архивов, исполняемых файлов?



Офлайн

#7 Янв. 28, 2010 12:02:45

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Оставьте пока эти далеко идущие выводы о глючности питона, ладно?
Я правильно понял, что вам нужно отправить письмо с вложениями в python3.1, а у вас не получается?
Могу посмотреть вечером. Сейчас под рукой нет тройки.



Офлайн

#8 Янв. 28, 2010 12:08:50

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Оставьте пока эти далеко идущие выводы о глючности питона, ладно?
Я правильно понял, что вам нужно отправить письмо с вложениями в python3.1, а у вас не получается?
Могу посмотреть вечером. Сейчас под рукой нет тройки.
Буду очень благодарен если если найдёте ошибку, или объясните чего я не учёл. Заранее большое спасибо.



Офлайн

#9 Янв. 28, 2010 23:20:33

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Вы не учли того, что в третьем Питоне в отличие от предыдущих 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())
Это все очень похоже на этот баг: http://bugs.python.org/issue4768
Непонятно, правда, почему оно до сих пор не зафикшено.



Офлайн

#10 Янв. 29, 2010 04:25:49

Artem
От:
Зарегистрирован: 2009-12-30
Сообщения: 24
Репутация: +  -1  -
Профиль   Отправить e-mail  

Отправка писем в 3-ем питоне

Большое спасибо за разъяснение. Но вообще интересно: есть “encode_base64()”, а есть “b64encode()”, как-то выглядит нелогично… Сам бы наверное не разобрался.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version