Портал Python-программистов

Форумы сайта python.su

Вы не зашли.

Объявление

Официальная wiki коммунити: wiki.python.su обсуждение

Официальная джаббер конференция коммунити: pythonua@conference.jabber.ru (всегда 20-35 онлайн участников). Настройки

КОД ОБОРАЧИВАТЬ В ТЕГИ [code][/code]

#1 2010-01-15 13:01:00

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

Отправка писем в 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["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'>

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

Неактивен

 

#2 2010-01-15 13:32:03

Zubchick
Питонер
Зарегистрирован: 2009-07-08
Сообщений: 437
Профиль  Вебсайт

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

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

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

Код:

sock.send(str.encode1(mail))

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

Отредактированно Zubchick (2010-01-15 13:34:49)

Неактивен

 

#3 2010-01-18 06:40:14

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

Re: Отправка писем в 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" перекодирует, потом присобачиваем к письму, вроде всё на месте sad

Отредактированно Artem (2010-01-18 06:45:26)

Неактивен

 

#4 2010-01-20 11:51:50

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

Re: Отправка писем в 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 2010-01-26 11:41:25

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

Re: Отправка писем в 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 2010-01-28 11:07:48

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

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

Неактивен

 

#7 2010-01-28 13:02:45

Ed
Питонер
Откуда: Helsinki, Finland
Зарегистрирован: 2008-12-13
Сообщений: 590
Профиль

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

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


---
The Zen of Python: There should be one-- and preferably only one --obvious way to do it.

Неактивен

 

#8 2010-01-28 13:08:50

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

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

Буду очень благодарен если если найдёте ошибку, или объясните чего я не учёл. Заранее большое спасибо.

Неактивен

 

#9 2010-01-29 00:20:33

Ed
Питонер
Откуда: Helsinki, Finland
Зарегистрирован: 2008-12-13
Сообщений: 590
Профиль

Re: Отправка писем в 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
Непонятно, правда, почему оно до сих пор не зафикшено.


---
The Zen of Python: There should be one-- and preferably only one --obvious way to do it.

Неактивен

 

#10 2010-01-29 05:25:49

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

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

Неактивен

 

#11 2010-01-29 09:15:18

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

Хм-м-м...
Работать - то работает только по почте приходит всякая ерунда.
Получается я должен указать у "str" кодировку, а какая у двоичного файла кодировка?

Неактивен

 

#12 2010-01-29 12:45:13

Ed
Питонер
Откуда: Helsinki, Finland
Зарегистрирован: 2008-12-13
Сообщений: 590
Профиль

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

Не у двоичного файла, а у того, что получается на выходе b64encode. Кодировка там ASCII, я вроде показал.


---
The Zen of Python: There should be one-- and preferably only one --obvious way to do it.

Неактивен

 

#13 2010-02-01 06:15:21

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

Не у двоичного файла, а у того, что получается на выходе b64encode. Кодировка там ASCII, я вроде показал.

Ага, так я и говорю, приходит покорёженный текстовый файл, и естественно уж не рабочий...

Отредактированно Artem (2010-02-01 06:15:40)

Неактивен

 

#14 2010-02-01 10:14:45

pyuser
Питонер
Откуда: г. Чита
Зарегистрирован: 2007-05-13
Сообщений: 244
Профиль

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

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())

приатаченный файл действительно не похож на исходный sad
Вы же сами указали на решение (http://bugs.python.org/issue4768)
перед строкой:

Код:

msg.set_payload(str(b64encode(fp.read()), 'ASCII'))

нужно добавить:

Код:

msg.add_header("Content-Transfer-Encoding", "base64")

Неактивен

 

#15 2010-02-08 05:54:15

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

Большое спасибо всем ответившим. Но отправить письмо всё равно не смог. С сервера приходит вместе с уведомлением что не может его правильно обработать. Но здесь возможно проблема в почтовике (microsoft exchange 4). Поставил версию 2.5, на ней проблем нет.

Неактивен

 

#16 2010-02-08 14:14:50

dartNNN
Питонер
Зарегистрирован: 2009-12-08
Сообщений: 115
Профиль

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

Обращаю ваше внимание на то, что вы сменили
connect.sendmail(fromaddr, toaddr, msg.as_string())
на
connect.sendmail(fromaddr, toaddr, msg.as_string)
Т.е. скобки убрали.
И хочу сказать, что прежде чем пытаться что то писать, надо сначала что нибудь изучить. В этом месте вы вместо результата выполнения метода as_string() передали в функцию сам метод as_string. Азы питона: все есть объект. И даже метод - это тоже объект. Рекомендую прочитать вам книгу для новичков в питоне, а после (если с английским все хорошо) "Div into Python 3", чтобы знать чем 3-ий питон отличается от 2-го (кстати они не совместимы, если это ускользнуло от вашего внимания). И на последок (задело за живое) по своему опыту знаю, что питон постабильнее других будет (если его конечно знать, а не как вы: что-то как-то менять, вдруг заработает)


И зачем я дурак на 3-ем питоне пишу?

Неактивен

 

#17 2010-02-09 09:17:44

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

...если его конечно знать, а не как вы: что-то как-то менять, вдруг заработает...

Ну вообще-то так и было smile
Это с одной стороны, а с другой найти с ходу пример для третьего питона не так-то просто, а если нет опыта работы на втором, то понять сразу различие тоже не получится.

Вот последний вариант (который не работает):

Код:

# -*- 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)

Неактивен

 

#18 2010-02-09 18:32:56

dartNNN
Питонер
Зарегистрирован: 2009-12-08
Сообщений: 115
Профиль

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

Вобщем я запустил твой код в паре с денвером и все сработало как часы.
PS: А че за ошибка то? Гуглить по ней не пробовал?


И зачем я дурак на 3-ем питоне пишу?

Неактивен

 

#19 2010-02-11 05:00:46

Artem
Питонер
Зарегистрирован: 2009-12-30
Сообщений: 21
Профиль

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

Ошибки никакой нет, уходит на раз, просто с почты письмо приходит с оповещением что были ошибки при прочтении и вываливает то что получило как текстовый файл. Никаких кодов не показывается. Я об этом выше писал.

Неактивен

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson

Board footer

Реклама: