2012-09-23 59 views
6

Tôi đang sử dụng smtplib và tôi đang gửi email thông báo từ ứng dụng của mình. Tuy nhiên tôi nhận thấy rằng đôi khi (đặc biệt là khi có rất nhiều thời gian nhàn rỗi giữa gửi thư) tôi nhận được một lỗi SMTPServerDisconnected.python. Tôi có thể kiểm tra xem máy chủ SMTP có bị ngắt kết nối không (vì vậy tôi có thể kết nối lại?)

Tôi đoán có 2 giải pháp cho việc này (biết ai trong số họ, mặc dù)

  1. Tăng thời gian nhàn rỗi giữa gửi mail
  2. kết nối lại khi kết nối được xuống.

Tôi nghĩ giải pháp thứ 2 có vẻ thanh lịch hơn. Nhưng làm thế nào tôi có thể làm điều đó?

chỉnh sửa: Tôi thêm mã

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

Bạn đang sử dụng 'SMTP.sendmail' để gửi email? Điều đó sẽ đóng gói tất cả các lệnh cấp thấp hơn bắt đầu từ 'connect'. Hoặc bạn đang cố gắng giữ một phiên SMTP mở và tái sử dụng cho một số email? –

+0

Tôi đã thêm mã bạn yêu cầu. Hy vọng rằng làm rõ câu hỏi nhiều hơn một chút. :-) – xpanta

Trả lời

4

Nếu trường hợp sử dụng của bạn đang gửi một thông điệp duy nhất tại một thời điểm, các giải pháp mà có vẻ chính xác nhất đối với tôi, sẽ là để tạo ra một phiên SMTP mới cho mỗi thông điệp:

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

Nếu máy chủ SMTP của bạn không yêu cầu bạn xác nhận bản thân (một trường hợp phổ biến), điều này có thể được đơn giản hóa hơn nữa để:

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

Nếu thông thường có nhiều tin nhắn để gửi cùng một lúc và bạn muốn tối ưu hóa trường hợp này bằng cách sử dụng lại cùng một phiên SMTP cho nhóm thư (có thể được đơn giản hóa như trên nếu bạn không cần đăng nhập tới máy chủ 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

cảm ơn. Điều đó sẽ làm. Một điều nữa. Có phải là 'smtp.close()' hay 'smtp.quit()'? – xpanta

+1

Theo tài liệu [quit()] (http://docs.python.org/library/smtplib.html#smtplib.SMTP.quit). –

+0

Sử dụng câu lệnh 'with' thay vì' thoát' rõ ràng. –

7

Có, bạn có thể kiểm tra xem kết nối có đang mở hay không. Để thực hiện việc này, hãy ra lệnh NOOP và kiểm tra trạng thái == 250. Nếu không, hãy mở kết nối trước khi gửi thư của bạn.

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. 

Lưu ý rằng bạn đang thực hiện thao tác này khi mở kết nối, nói với gmail, tốn thời gian, như 2-3 giây. Sau đó, để tối ưu hóa việc gửi nhiều email mà bạn có thể có trong tay, sau đó bạn cũng nên làm theo phản ứng của Pedro (phần cuối).

Các vấn đề liên quan