2012-09-23 8 views
6

Używam smtplib i wysyłam wiadomości e-mail z powiadomieniem z mojej aplikacji. Jednak zauważyłem, że czasami (szczególnie gdy jest dużo czasu bezczynności między wysyłaniem poczty), pojawia się błąd SMTPServerDisconnected.python. Czy mogę sprawdzić, czy serwer SMTP jest odłączony (aby ponownie połączyć?)

Chyba są 2 rozwiązania dla tego (wiem, żaden z nich, choć)

  1. wydłużyć czas bezczynności pomiędzy wysyłanie maili
  2. reconnect gdy połączenie jest w dół.

Myślę, że drugie rozwiązanie wydaje się bardziej eleganckie. Ale jak mogę to zrobić?

edit: dodaję kod

from smtplib import SMTP 
smtp = SMTP() 
smtp.connect('smtp.server.com') 
smtp.login('username','password') 

def notifyUser(): 
    smtp.sendmail(from_email, to_email, msg.as_string()) 
+0

Czy używasz 'SMTP.sendmail' do wysyłania e-maili? To powinno obejmować wszystkie komendy niższego poziomu zaczynające się od 'connect'. A może chcesz otworzyć sesję SMTP i użyć jej ponownie dla kilku e-maili? –

+0

Dodałem kod, o który prosiłeś. Nadzieję, że nieco bardziej wyjaśnia to pytanie. :-) – xpanta

Odpowiedz

4

Jeśli Twój przypadek użycia jest wysłanie jednej wiadomości na raz, rozwiązanie, które wydaje się najbardziej poprawna do mnie, byłoby stworzenie nowej sesji SMTP dla każdego komunikat:

from smtplib import SMTP 

smtp = SMTP('smtp.server.com') 

def notifyUser(smtp, smtp_user, smtp_password, from_email, to_email, msg): 
    smtp.login(smtp_user, smtp_password) 
    smtp.sendmail(from_email, to_email, msg.as_string()) 
    smtp.quit() 

Jeśli serwer SMTP nie wymaga, aby uwierzytelnić się (to częsty przypadek), to można dodatkowo uprościć:

from smtplib import SMTP 

smtp = SMTP('smtp.server.com') 

def notifyUser(smtp, from_email, to_email, msg): 
    smtp.sendmail(from_email, to_email, msg.as_string()) 
    smtp.quit() 

Jeśli często jest więcej niż jeden komunikat do wysłania na raz, i chcesz zoptymalizować ten przypadek, ponownie wykorzystując tę ​​samą sesję SMTP dla grupy wiadomości (można uprościć, jak wyżej, jeśli nie musisz się logować na serwer SMTP):

from smtplib import SMTP 

smtp = SMTP('smtp.server.com') 

def notifyUsers(smtp, smtp_user, smtp_password, from_to_msgs): 
    """ 
    :param from_to_msgs: iterable of tuples with `(from_email, to_email, msg)` 
    """ 
    smtp.login(smtp_user, smtp_password) 
    for from_email, to_email, msg in from_to_msgs: 
     smtp.sendmail(from_email, to_email, msg.as_string()) 
    smtp.quit() 
+0

dzięki. To by zrobiło. Jeszcze jedna rzecz. Czy jest to 'smtp.close()' lub 'smtp.quit()'? – xpanta

+1

Zgodnie z dokumentacją [quit()] (http://docs.python.org/library/smtplib.html#smtplib.SMTP.quit). –

+0

Użyj instrukcji 'with' zamiast jawnego' quit'. –

7

Tak, można sprawdzić, czy połączenie jest otwarte. Aby to zrobić, wydaj polecenie NOOP i sprawdź status == 250. Jeśli nie, otwórz połączenie przed wysłaniem wiadomości e-mail.

def test_conn_open(conn): 
    try: 
     status = conn.noop()[0] 
    except: # smtplib.SMTPServerDisconnected 
     status = -1 
    return True if status == 250 else False 

def send_email(conn, from_email, to_email, msg): 
    if not test_conn_open(conn): 
     conn = create_conn() 
    conn.sendmail(from_email, to_email, msg.as_string()) 
    return conn # as you want are trying to reuse it. 

Pamiętaj, że robisz to, otwierając połączenie, np. Za pomocą Gmaila, zużywa czas, np. 2-3 s. Następnie, aby zoptymalizować wysyłanie wielu e-maili, które możesz mieć pod ręką, powinieneś także postępować zgodnie z odpowiedzią Pedro (ostatnia część).

Powiązane problemy