Отправка электронной почты не работает, когда я запускаю скрипт, но построчно работает, почему?

У меня есть этот простой скрипт, который я использую для отправки электронной почты со статусом на сервере. Он работает, и он не выдает мне ошибок, но я не получаю никаких писем, и в папке отправленных в Google нет писем. Но если я копирую и вставляю каждую строку за строкой в ​​python в оболочке, он отправляет электронную почту и работает. Ошибок нигде нет. Я даже получаю принятый статус от Google.

ОБНОВЛЕНИЕ: я мог вырезать слишком много кода из примера, и переменная i была случайно удалена. Я добавил это снова. Когда я копирую и вставляю каждую строку в строку cmd python, скрипт работает. Когда я просто запускаю скрипт, он не сообщает об ошибках, но не отправляет электронное письмо.

import smtplib
i = 0
try:
    text = "This is remarkable"
    fromaddr = "<gmail address>"
    toaddr = "<email address>"
    msg = """\
            From: <gmail address>
            To: <email address>
            Subject: Message number %i

            %s
    """ % (i, text)

    server = smtplib.SMTP("smtp.gmail.com:587")
    server.set_debuglevel(1)
    server.ehlo()
    server.starttls()
    server.login("<email>", "<password>")

    ret = server.sendmail(fromaddr, toaddr, msg)
    print "returned : ", ret
    print "message sent"
    i += 1
except:
    print "Now some crazy **** happened"

person Trausti Thor    schedule 08.03.2014    source источник
comment
здесь i не определен, поэтому возникает ошибка. Дайте начальное значение i, тогда скрипт работает нормально   -  person Vipul    schedule 08.03.2014
comment
Вот почему вы не должны заключать все в try... blog.codekills.net/2011/09/29/the-evils-of--except--   -  person jonrsharpe    schedule 08.03.2014
comment
FWIW: Несмотря на то, что вы приняли ответ ниже, я хотел отметить, что текущий код в вашем вопросе (с заменой соответствующих адресов электронной почты и пароля) сработал для меня, запустив его как сценарий. Были некоторые проблемы с форматированием, но я получил его, и никаких исключений не возникло.   -  person martineau    schedule 09.03.2014
comment
Кстати: я исправил проблемы с форматированием в полученном сообщении, используя msg = textwrap.dedent("""\ ... """) % (i, text).   -  person martineau    schedule 09.03.2014
comment
Чтобы избежать многочисленных ошибок с кодировкой сообщений электронной почты, вы можете использовать классы MIMEText, Header из пакета email. Вот полный пример кода   -  person jfs    schedule 09.03.2014


Ответы (3)


i не определено. Вы бы увидели NameError, если бы не обернули try и голый except вокруг всего. У вас должно быть как можно меньше в блоке try, по крайней мере. Также вы можете поймать конкретную ошибку as e. Это также напечатает ошибку, чтобы вы могли понять, в чем проблема.

Итак, код должен быть:

import smtplib

i = 1
text = "This is remarkable"
fromaddr = "<gmail address>"
toaddr = "<email address>"
msg = """\
        From: <gmail address>
        To: <email address>
        Subject: Message number %i

        %s""" % (i, text)

try: 
    server = smtplib.SMTP("smtp.gmail.com:587")
    server.set_debuglevel(1)
    server.ehlo()
    server.starttls()
    server.login("<email>", "<password>")
    ret = server.sendmail(fromaddr, toaddr, msg)
except Exception as e:
    print 'some error occured'
    print e
else:
    print "returned : ", ret
    print "message sent"
    i += 1
person Vipul    schedule 08.03.2014
comment
В try должно быть меньше! Если бы тривиальное форматирование строки было за его пределами, ошибка была бы обнаружена немедленно. Последние несколько строк (print, приращение i) тоже можно переместить в else. - person jonrsharpe; 08.03.2014
comment
да ! вы правы .. не могли бы вы отредактировать код для лучшей обработки исключений! - person Vipul; 08.03.2014
comment
Перехват всех исключений с помощью except Exception: обычно является плохой практикой программирования, особенно когда он (или другой на его месте) не вызывается (повторно) и сценарию разрешено продолжать выполнение. - person martineau; 08.03.2014
comment
Попытка была просто заменой цикла, который у меня был, для подписки паба. Изменения выше работы - person Trausti Thor; 09.03.2014

Ваша переменная счетчика i не определена. try-except не является циклом. Вы должны быть более осторожными с тем, что вы помещаете в блок try. Только операторы переноса, которые, по вашему мнению, могут вызвать исключение, которое вам нужно перехватить. Конечно, ваша строка msg должна быть построена вне обработчика исключений, поскольку она не должна давать сбоев, и если это произойдет, ваш код неверен. Обращения к почтовому серверу могут быть обернуты:

server = smtplib.SMTP(host="smtp.gmail.com", port="587")
server.set_debuglevel(1)
try:
    server.ehlo()
    server.starttls()
    server.login("<email>", "<password>")
    server.sendmail(fromaddr, toaddr, msg)
    print "message sent"

except smtplib.SMTPException as e:
    print "Something went wrong: %s" %str(e)

finally:
    server.close()

Таким образом, вы уменьшили объем кода в блоке try-except.

При перехвате исключений будьте осторожны, чтобы не перехватить больше, чем вы ожидаете. Мы можем определить, какой тип исключений мы ожидаем, а затем предпринять соответствующие действия. Здесь мы просто печатаем его. Блок finally: будет выполнен, даже если возникнет неизвестное исключение, которое мы не поймаем. Обычно здесь мы закрываем соединение с сервером или обработчик файла, поскольку исключение, созданное в блоке try, может оставить соединение с сервером открытым. Здесь необходимо создать экземпляр сервера за пределами блока try, иначе мы пытаемся получить доступ к переменной, которая выйдет за пределы области видимости, если возникнет исключение.

Все методы smtplib.SMTP выдают разные варианты smtplib.SMTPException, поэтому вам следует посмотреть на определение методов, а затем поймать только правильный тип исключения. Все они наследуются от smtplib.SMTPException, поэтому мы можем поймать этот тип, если нам лень.

person Ronny Andersson    schedule 08.03.2014
comment
Это улучшение, но вы по-прежнему перехватываете все исключения с помощью except Exceptions as e:, а затем позволяете программе продолжить работу. Я бы предложил, по крайней мере, повторно вызвать его с помощью простого оператора raise после оператора print и позволить любому потоку управления более высокого уровня обрабатывать его соответствующим образом (включая разрешение интерпретатору Python завершить скрипт, если это не так). - person martineau; 08.03.2014
comment
Да. ОП вообще не проверял исключение, это причина простого оператора печати. Делать это правильно означало бы, что мы должны проверить, какой тип исключений ожидается от класса smtplib.SMTP, а затем перехватить их. Наконец-то мы могли закончить уловом все, что у нас есть. Я согласен, что ловить все, а затем просто продолжать — плохая практика, если только мы этого не хотим. - person Ronny Andersson; 08.03.2014

Я подозреваю очень чувствительные системы фильтрации спама, которые есть у Google, поскольку вы можете получать предупреждения, когда запускаете код построчно без каких-либо проблем. Может быть введение задержки с использованием time.sleep в некоторых местах может дать фильтру спама ощущение, что расположение электронной почты более человеческое, чем автоматизированное.

В дополнение к этому я бы также предложил использовать альтернативный SMTP-сервер любого другого провайдера, и я уверен, что вы уже проверили бы свою папку со спамом....

person Venu Murthy    schedule 10.03.2014