最近一直在糾結一個郵件傳送的問題。
在本地Linux下搭建程式,不填寫EMAIL設定就可以成功傳送郵件,在遠端的雲伺服器下的Linux環境就傳送不了。在windows下搭建的程式也不能傳送註冊郵件,很是奇怪。
初步判斷是程式碼沒有問題,本地Linux伺服器由於以前也鼓搗過其它東西,不一定與雲端伺服器保持一致。於是只能從官方文件的傳送郵件說明入手,慢慢找原因。
from django.core.mail import send_mail send_mail(u'郵件標題', u'郵件內容', '[email protected]',
['[email protected]'], fail_silently=False)
在測試環境使用如上配置,就可以傳送郵件了,看來得翻翻原始碼才能發現問題。
原作者使用如下的方法傳送郵件:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from django.core.mail import EmailMessage
import threading class EmailThread(threading.Thread):
"""
傳送賬號啟用郵件執行緒
"""
def __init__(self,subject='', body='', from_email=None, to=None):
self.subject = subject
self.body = body
self.from_email = from_email
self.to = to
self.fail_silently = True
threading.Thread.__init__(self) def run(self):
msg_email = EmailMessage(self.subject,self.body,self.from_email,self.to)
msg_email.content_subtype = 'html'
try:
msg_email.send(self.fail_silently)
except Exception,e:
# 記錄錯誤日誌
log = open('email_error.log','a')
log.write('%s %s\n' %(time.strftime('%Y-%m-%d %H:%M:%S'),e) )
log.close() def send_email(subject='', body='', from_email=None, to=[]):
"""
傳送郵件方法
"""
email = EmailThread(subject, body, from_email, to)
email.start()
email.join()
基本瞭解程式碼的意思,但是經過幾次摘出來最小化試驗,還是不能傳送成功註冊郵件。本來通過最上面的最簡單的方法可以傳送郵件,但作者使用了執行緒,也許是出於效率和生產環境的考量。於是我上網找了找Django執行緒傳送郵件的例子,還真找到了。就是程式碼無縮排…真是….
from django.core.mail import EmailMultiAlternatives
from django.template import loader
from settings import EMAIL_HOST_USER
from django.http import HttpResponse
import threading class my_EmailThread(threading.Thread):
def __init__(self, subject, body, from_email, recipient_list, fail_silently, html):
self.subject = subject
self.body = body
self.recipient_list = recipient_list
self.from_email = from_email
self.fail_silently = fail_silently
self.html = html
threading.Thread.__init__(self) def run (self):
msg = EmailMultiAlternatives(self.subject, self.body, self.from_email, self.recipient_list)
if self.html:
msg.attach_alternative(self.body,self.html)
msg.send(self.fail_silently) def my_send_mail(subject, body, from_email, to, fail_silently=False, html=None, *args, **kwargs):
my_EmailThread(subject, body, from_email, to, fail_silently, html).start()
def test_mail(subject='', body='', from_email=None, to=[]):
#subject = u'郵件主題'
#to_mail_list = ['[email protected]','[email protected]']
#body = loader.render_to_string('mail_template.html',{'email':email,'date':datetime.today(), })
#send_mail(subject,body,from_email,to_mail_list,html="text/html")
#my_send_mail(u'郵件標題', u'郵件內容', '[email protected]',['[email protected]'],html="text/html")
my_send_mail(subject,body,from_email,to, html="text/html")
因為,有例子做對照,我直接把上面的程式碼加入到工程中。在send_mail與EmailThread前面新增my_為了使得兩段程式碼共存,還沒有搞懂整個工程的執行原理之前,還是保證原先的程式碼原樣更安全些。
經過試驗,直接傳進引數,傳送郵件沒有問題。但是使用變數應用使用者資訊就會發送失敗。
那麼,找到上層的檢視,控制變數進行測試,看看哪個變數沒有正確替換。還真發現了問題。
to = [user.username]
....
#send_email(subject,body,from_email,to)
test_mail(subject,body,from_email,to)
test_mail就是呼叫的新的執行緒傳送郵件,send_mail呼叫的原先的執行緒傳送。如上的兩種情況都不能傳送郵件,就是因為to沒有被賦予正確的郵件地址。
send_email(u'郵件標題', u'郵件內容', '[email protected]',['[email protected]'])
這樣的顯示呼叫,原先的執行緒函處理方法也正確的工作了,看來,上面的兩種執行緒傳送郵件都是可用的。問題出現在變數上。
那麼這個user.username又是什麼,繼續尋找…是使用的User引入的使用者物件
from django.contrib.auth.models import User
看來問題不是出現在郵件傳送方法上,而是使用者物件上。至於為何本地的Linux不經配置,可以直接使用…(請教了作者,作者認為可能是django自帶的郵件服務,暫時也就先這麼放下這個詭異的問題)
明天開始瞭解下Django的使用者方面,感覺不同平臺出現不穩定的情況是因為程式碼還不夠健壯…看能不能有新的發現~