Этот код работает и отправляет мне электронное письмо просто отлично:
import smtplib
#SERVER = "localhost"
FROM = 'monty@python.com'
TO = ["jon@mycompany.com"] # must be a list
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP('myserver')
server.sendmail(FROM, TO, message)
server.quit()
Однако, если я попытаюсь обернуть его в такую функцию:
def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
import smtplib
"""this is some test documentation in the function"""
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
и позвонив, я получаю следующие ошибки:
Traceback (most recent call last):
File "C:/Python31/mailtest1.py", line 8, in <module>
sendmail.sendMail(sender,recipients,subject,body,server)
File "C:/Python31\sendmail.py", line 13, in sendMail
server.sendmail(FROM, TO, message)
File "C:\Python31\lib\smtplib.py", line 720, in sendmail
self.rset()
File "C:\Python31\lib\smtplib.py", line 444, in rset
return self.docmd("rset")
File "C:\Python31\lib\smtplib.py", line 368, in docmd
return self.getreply()
File "C:\Python31\lib\smtplib.py", line 345, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
Может кто-нибудь помочь мне понять, почему?
Ответы:
Я рекомендую вам использовать стандартные пакеты
email
иsmtplib
вместе отправлять электронную почту. Пожалуйста, посмотрите на следующий пример (воспроизведенный из документации Python ). Обратите внимание, что если следовать этому подходу, «простая» задача действительно проста, а более сложные задачи (например, присоединение двоичных объектов или отправка простых / HTML многокомпонентных сообщений) выполняются очень быстро.Для отправки электронной почты нескольким получателям вы также можете следовать примеру в документации по Python :
Как вы можете видеть, заголовок
To
вMIMEText
объекте должна быть строка , состоящая из адресов электронной почты , разделенных запятыми. С другой стороны, вторым аргументомsendmail
функции должен быть список строк (каждая строка является адресом электронной почты).Итак, если у вас есть три адреса электронной почты:
person1@example.com
,person2@example.com
иperson3@example.com
, вы можете сделать следующее (очевидные разделы опущены):",".join(to)
часть составляет одну строку из списка, разделенных запятыми.Из ваших вопросов я понимаю, что вы не прошли учебник по Python - это ОБЯЗАТЕЛЬНО, если вы хотите получить что-нибудь в Python - документация в основном превосходна для стандартной библиотеки.
источник
", ".join(["a@example.com", "b@example.net"])
with
:with open(textfile, 'rb') as fp:
. Явное закрытие может быть отброшено, так какwith
блок закроет файл, даже если в нем произойдет ошибка.Ну, вы хотите получить ответ, который был бы современным и современным.
Вот мой ответ:
Когда мне нужно отправить почту в python, я использую mailgun API, который доставляет много головной боли при пересылке почты. У них есть замечательное приложение / API, которое позволяет отправлять 10000 электронных писем в месяц бесплатно.
Отправка электронного письма будет выглядеть так:
Вы также можете отслеживать события и многое другое, см. Краткое руководство .
Я надеюсь, что вы найдете это полезным!
источник
Я хотел бы помочь вам с отправкой электронных писем, посоветовав пакет yagmail (я сопровождающий, извините за рекламу, но я чувствую, что это действительно может помочь!).
Весь код для вас будет:
Обратите внимание, что я предоставляю значения по умолчанию для всех аргументов, например, если вы хотите отправить себе, вы можете опустить
TO
, если вы не хотите тему, вы также можете опустить ее.Кроме того, цель также состоит в том, чтобы действительно легко прикрепить HTML-код или изображения (и другие файлы).
Где вы размещаете содержимое, вы можете сделать что-то вроде:
Ух, как легко отправлять вложения! Это заняло бы как 20 строк без yagmail;)
Кроме того, если вы настроите его один раз, вам больше никогда не придется вводить пароль (и хранить его безопасно). В вашем случае вы можете сделать что-то вроде:
что гораздо лаконичнее!
Я бы пригласил вас взглянуть на github или установить его напрямую
pip install yagmail
.источник
yagmail
не Gmail? Я пытаюсь использовать для моего собственного сервера SMTP.Attachment
класс; это все то же самое. Если они могут изменить ваш код, то они могут делать что угодно в любом случае (с / без root, это то же самое при отправке электронной почты) Это мне кажется типичным «это удобно / волшебно, поэтому должно быть менее безопасно». Мне любопытно, какую реальную угрозу вы видите?Есть проблема с отступами. Код ниже будет работать:
источник
SERVER
переменная, которая передается в функцию - это учетные данные пользователя.email
делает это достаточно хорошо (особенно начиная с версии 3.6), хотя все еще требует некоторого понимания того, что вы делаете.Вот пример на Python
3.x
, намного проще, чем2.x
:вызвать эту функцию:
ниже может только для китайского пользователя:
Если вы используете 126/163, 网易 邮箱, вам нужно установить «客户 端 授权 密码», как показано ниже:
ссылка: https://stackoverflow.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples
источник
Делая отступ в своем коде в функции (что нормально), вы также делали отступ строки необработанного сообщения. Но начальный пробел подразумевает свертывание (конкатенацию) строк заголовка, как описано в разделах 2.2.3 и 3.2.3 RFC 2822 - Формат интернет-сообщения :
В функциональной форме вашего
sendmail
вызова все строки начинаются с пробела и поэтому «развернуты» (объединены), и вы пытаетесь отправитьКроме наш разум говорит,
smtplib
не будет пониматьTo:
иSubject:
заголовки больше, потому что эти имена распознаются только в начале строки. Вместо этогоsmtplib
примет очень длинный адрес электронной почты отправителя:Это не сработает, и поэтому приходит ваше исключение.
Решение простое: просто сохраните
message
строку, как это было раньше. Это можно сделать с помощью функции (как предложил Zeeshan) или сразу в исходном коде:Теперь разворачивание не происходит и вы отправляете
что работает, и что было сделано вашим старым кодом.
Обратите внимание, что я также сохранял пустую строку между заголовками и телом для размещения раздела 3.5 RFC (который требуется) и помещал включение вне функции в соответствии с руководством по стилю Python PEP-0008 (которое является необязательным).
источник
Это, вероятно, вкладки в ваше сообщение. Распечатайте сообщение, прежде чем передать его sendMail.
источник
Убедитесь, что вы предоставили разрешение отправителю и получателю отправлять электронную почту и получать электронную почту из неизвестных источников (внешних источников) в учетной записи электронной почты.
источник
msg
не является действительным SMTP-сообщением и просто исчезнет в эфире, если ваш почтовый сервер его примет.Думал, что я вставлю свои две части здесь, так как я только что понял, как это работает.
Похоже, что у вас нет порта, указанного в настройках соединения с SERVER, это немного повлияло на меня, когда я пытался подключиться к своему SMTP-серверу, который не использует порт по умолчанию: 25.
В соответствии с документацией smtplib.SMTP ваш запрос / ответ на ehlo или helo должен автоматически обрабатываться, поэтому вам не нужно об этом беспокоиться (но это может быть чем-то, что может подтвердить, если ничего не получится).
Еще один вопрос: разрешены ли SMTP-соединения на самом SMTP-сервере? Для некоторых сайтов, таких как GMAIL и ZOHO, вы должны войти и активировать соединения IMAP в учетной записи электронной почты. Ваш почтовый сервер может не разрешать SMTP-подключения, которые не приходят от 'localhost', возможно? Что-то, чтобы посмотреть.
Последнее, что вы можете попробовать установить соединение по TLS. Большинство серверов сейчас требуют такой тип аутентификации.
Вы увидите, что я забил два поля TO в своем письме. Элементы словаря msg ['TO'] и msg ['FROM'] позволяют отображать правильную информацию в заголовках самого письма, которое видно на принимающей стороне письма в полях «Кому / От» (вы здесь можно даже добавить поле «Ответить». Сами поля «TO» и «FROM» - это то, что требуется серверу. Я знаю, что некоторые почтовые серверы отклоняют электронную почту, если у них нет соответствующих заголовков электронной почты.
Это код, который я использовал в функции, которая работает для отправки по электронной почте содержимого файла * .txt с использованием моего локального компьютера и удаленного SMTP-сервера (ZOHO, как показано):
источник
Стоит отметить, что модуль SMTP поддерживает диспетчер контекста, поэтому нет необходимости вручную вызывать quit (), это гарантирует, что он вызывается всегда, даже если есть исключение.
источник
Что касается вашего кода, то, похоже, в этом нет ничего принципиально неправильного, за исключением того, что неясно, как вы на самом деле вызываете эту функцию. Все, что я могу думать, это то, что когда ваш сервер не отвечает, вы получите эту ошибку SMTPServerDisconnected. Если вы посмотрите функцию getreply () в smtplib (отрывок ниже), вы получите представление.
посмотрите пример на https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py , где также используется вызов функции для отправки электронного письма, если это то, что вы пытаетесь сделать (подход DRY).
источник