Smtplib и gmail - проблемы с python script

Здесь мой script:

#!/usr/bin/python
import smtplib
msg = 'Hello world.'
server = smtplib.SMTP('smtp.gmail.com',587) #port 465 or 587
server.ehlo()
server.starttls()
server.ehlo()
server.login('[removed_email]','mypass')
server.sendmail('[removed_email]','[removed_email]',msg)
server.close()

Я просто пытаюсь отправить электронное письмо из своей учетной записи gmail. script использует starttls из-за требования Gmail. Я пробовал это на двух веб-хостах: 1and1 и webfaction. 1and1 дает мне ошибку "отказ в соединении", а сообщения webfaction не содержат ошибок, но просто не отправляют электронное письмо. Я не вижу ничего плохого в script, поэтому я думаю, что это может быть связано с веб-хостами. Любые мысли и комментарии будут высоко оценены.

EDIT: я включил режим отладки. Из вывода видно, что он успешно отправил сообщение... Я просто его не получаю.

send: 'ehlo web65.webfaction.com\r\n'
reply: '250-mx.google.com at your service, [174.133.21.84]\r\n'
reply: '250-SIZE 35651584\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-STARTTLS\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250 PIPELINING\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [174.133.21.84]
SIZE 35651584
8BITMIME
STARTTLS
ENHANCEDSTATUSCODES
PIPELINING
send: 'STARTTLS\r\n'
reply: '220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: 2.0.0 Ready to start TLS
send: 'ehlo web65.webfaction.com\r\n'
reply: '250-mx.google.com at your service, [174.133.21.84]\r\n'
reply: '250-SIZE 35651584\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-AUTH LOGIN PLAIN\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250 PIPELINING\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [174.133.21.84]
SIZE 35651584
8BITMIME
AUTH LOGIN PLAIN
ENHANCEDSTATUSCODES
PIPELINING
send: 'AUTH PLAIN *****\r\n'
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted
send: 'mail FROM:<[removed_email]> size=12\r\n'
reply: '250 2.1.0 OK 4sm652580yxq.48\r\n'
reply: retcode (250); Msg: 2.1.0 OK 4sm652580yxq.48
send: 'rcpt TO:<[removed_email]>\r\n'
reply: '250 2.1.5 OK 4sm652580yxq.48\r\n'
reply: retcode (250); Msg: 2.1.5 OK 4sm652580yxq.48
send: 'data\r\n'
reply: '354 Go ahead 4sm652580yxq.48\r\n'
reply: retcode (354); Msg: Go ahead 4sm652580yxq.48
data: (354, 'Go ahead 4sm652580yxq.48')
send: 'Hello world.\r\n.\r\n'
reply: '250 2.0.0 OK 1240421143 4sm652580yxq.48\r\n'
reply: retcode (250); Msg: 2.0.0 OK 1240421143 4sm652580yxq.48
data: (250, '2.0.0 OK 1240421143 4sm652580yxq.48')
</[removed_email]></[removed_email]>
7 ответов

Я думаю, что SMTP-сервер GMail выполняет обратный DNS-поиск по IP-адресу, с которого вы подключаетесь, и отказывается от соединения, если ни один домен не найден. Это делается для того, чтобы спамер не использовал свой SMTP-сервер в качестве открытого реле.


Вы пытались создать правильное сообщение?

from email.MIMEText import MIMEText
msg = MIMEText('body')
msg['Subject'] = 'subject'
msg['From'] = "..."
msg['Reply-to'] = "..."
msg['To'] = "..."


Я не знаю, будет ли OP по-прежнему заботиться об этом ответе, но, оказавшись здесь, чтобы устранить подобную проблему, мы надеемся, что кто-то другой может найти это полезным. Как оказалось, Google изменил способ использования своего SMTP-сервера. Вы хотите проверить пару вещей:

  • Что вы используете тот же адрес, который вы использовали для аутентификации в качестве адреса "from". Если я не ошибаюсь, это было так, что вы могли бы использовать все, что захотите, в поле, но для целей безопасности многие узлы SMTP-хоста (включая google) теперь ограничивают это адресом, который прошел аутентификацию с ними.

  • Разрешить доступ к вашей учетной записи с помощью "менее безопасных приложений" (читайте: приложения, из которых мы не получаем доход). Для этого войдите в свою учетную запись и перейдите сюда: https://www.google.com/settings/security/lesssecureapps

  • Используйте порт 587 с tls. Не совсем уверен, почему, но я никогда не смогу получить порт 465, чтобы играть хорошо.

Надеюсь, это поможет кому-то другому.


Некоторые саморекламы здесь, но я чувствую себя на законных основаниях.

Вам буквально нужен только этот код, чтобы сделать то, что вы написали:

import yagmail
yag = yagmail.SMTP('[removed_email]')
yag.send('[removed_email]', subject = None, contents = 'Hello')

Или один лайнер:

yagmail.SMTP('[removed_email]').send('[removed_email]', None, 'Hello world.')

Хорошо, что я предлагаю использовать keyring для хранения вашего пароля, поэтому у вас никогда не будет риска увидеть ваш пароль в вашем script.

Для пакета/установки посмотрите git или pip, доступный как для Python 2, так и для 3.


спасите себя от головных болей и используйте это:

http://mynthon.net/howto/-/python/python%20-%20logging.SMTPHandler-how-to-use-gmail-smtp-server.txt

Python SMTPHandler с GMail

Сс


Вам нужно будет проверить папку "Отправлено" в GMail, так как там, где сообщение, отправленное из вашей учетной записи в ваш аккаунт, скорее всего, появится.


Я перешел к вышеупомянутой ссылке и имел 3 разных адреса для отправки, но я получил три письма на один адрес и тот, что был адресом №3.

http://mynthon.net/howto/-/python/python%20-%20logging.SMTPHandler-how-to-use-gmail-smtp-server.txt

import logging
import logging.handlers
class TlsSMTPHandler(logging.handlers.SMTPHandler):
def emit(self, record):
 """
 Emit a record.
 Format the record and send it to the specified addressees.
 """
 try:
 import smtplib
 import string # for tls add this line
 try:
 from email.utils import formatdate
 except ImportError:
 formatdate = self.date_time
 port = self.mailport
 if not port:
 port = smtplib.SMTP_PORT
 smtp = smtplib.SMTP(self.mailhost, port)
 msg = self.format(record)
 msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
 self.fromaddr,
 string.join(self.toaddrs, ","),
 self.getSubject(record),
 formatdate(), msg)
 if self.username:
 smtp.ehlo() # for tls add this line
 smtp.starttls() # for tls add this line
 smtp.ehlo() # for tls add this line
 smtp.login(self.username, self.password)
 smtp.sendmail(self.fromaddr, self.toaddrs, msg)
 smtp.quit()
 except (KeyboardInterrupt, SystemExit):
 raise
 except:
 self.handleError(record)
logger = logging.getLogger()
gm = TlsSMTPHandler(("smtp.gmail.com", 587), '[removed_email]', ['[removed_email]', '[removed_email]', '[removed_email]'], 'unable to find Error!', ('[removed_email]', 'mypassword'))
gm.setLevel(logging.ERROR)
logger.addHandler(gm)
try:
 1/0
except:
 logger.exception('It NO work for me!!-')

licensed under cc by-sa 3.0 with attribution.