Форумы сайта 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["From"] = make_header([("Недруг", russian), ("<fromuser@aa.aa.ru>", "us-ascii")])
msg["To"] = make_header([("Друг", russian), ("<touser@bb.bb.ru>", "us-ascii")])
msg["Subject"] = 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())Отредактированно Zubchick (2010-01-15 13: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()Вот этот кусок вроде читает файл как "bytes", потом метод "encode_base64" перекодирует, потом присобачиваем к письму, вроде всё на месте ![]()
Отредактированно Artem (2010-01-18 06:45:26)
Неактивен
заменил
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()помогите пожалуйста, вообще понять не могу в чём проблема...
Неактивен
Проблему так и не решил
вот ещё интересно:
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"
Может проблема где-то здесь?
Неактивен
Блин, запустил пример на версии 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())Это все очень похоже на этот баг: http://bugs.python.org/issue4768
Непонятно, правда, почему оно до сих пор не зафикшено.
Неактивен
Не у двоичного файла, а у того, что получается на выходе b64encode. Кодировка там ASCII, я вроде показал.
Неактивен
Не у двоичного файла, а у того, что получается на выходе b64encode. Кодировка там ASCII, я вроде показал.
Ага, так я и говорю, приходит покорёженный текстовый файл, и естественно уж не рабочий...
Отредактированно Artem (2010-02-01 06:15:40)
Неактивен
Ed написал:
Код:
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)
перед строкой:
msg.set_payload(str(b64encode(fp.read()), 'ASCII'))нужно добавить:
msg.add_header("Content-Transfer-Encoding", "base64")Неактивен
Большое спасибо всем ответившим. Но отправить письмо всё равно не смог. С сервера приходит вместе с уведомлением что не может его правильно обработать. Но здесь возможно проблема в почтовике (microsoft exchange 4). Поставил версию 2.5, на ней проблем нет.
Неактивен
Обращаю ваше внимание на то, что вы сменили
connect.sendmail(fromaddr, toaddr, msg.as_string())
на
connect.sendmail(fromaddr, toaddr, msg.as_string)
Т.е. скобки убрали.
И хочу сказать, что прежде чем пытаться что то писать, надо сначала что нибудь изучить. В этом месте вы вместо результата выполнения метода as_string() передали в функцию сам метод as_string. Азы питона: все есть объект. И даже метод - это тоже объект. Рекомендую прочитать вам книгу для новичков в питоне, а после (если с английским все хорошо) "Div into Python 3", чтобы знать чем 3-ий питон отличается от 2-го (кстати они не совместимы, если это ускользнуло от вашего внимания). И на последок (задело за живое) по своему опыту знаю, что питон постабильнее других будет (если его конечно знать, а не как вы: что-то как-то менять, вдруг заработает)
Неактивен
...если его конечно знать, а не как вы: что-то как-то менять, вдруг заработает...
Ну вообще-то так и было ![]()
Это с одной стороны, а с другой найти с ходу пример для третьего питона не так-то просто, а если нет опыта работы на втором, то понять сразу различие тоже не получится.
Вот последний вариант (который не работает):
# -*- coding: utf-8 -*-
from smtplib import SMTP
from email.message import Message
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 import encoders
from base64 import b64encode
import os
import sys
import mimetypes
russian = 'windows-1251'
msg = MIMEMultipart()
msg["From"] = make_header([("Недруг", russian), ("<from@from.from.ru>", "us-ascii")])
msg["To"] = make_header([("Друг", russian), ("<to@to.to.ru>", "us-ascii")])
msg["Subject"] = 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.add_header("Content-Disposition", "attachment", filename="dfdfd")
to_attach.add_header("Content-Transfer-Encoding", "base64")
to_attach.set_payload(str(b64encode(fp.read()), 'ASCII'))
fp.close()
msg.attach(to_attach)
#print(msg.as_string())
smail=msg.as_string()
fromaddr = "from@from.from.ru"
toaddr = "to@to.to.ru"
connect = SMTP('XX.XX.XX.XX')
connect.set_debuglevel(0)
connect.sendmail(fromaddr, toaddr, smail)
connect.quit()Все замечания вроде устранены, а приходит всё равно с ошибкой. Так что...
Отредактированно Artem (2010-02-09 09:18:42)
Неактивен
Ошибки никакой нет, уходит на раз, просто с почты письмо приходит с оповещением что были ошибки при прочтении и вываливает то что получило как текстовый файл. Никаких кодов не показывается. Я об этом выше писал.
Неактивен