• 初探Django线程发送邮件


    最近一直在纠结一个邮件发送的问题。

    在本地Linux下搭建程序,不填写EMAIL设置就可以成功发送邮件,在远端的云服务器下的Linux环境就发送不了。在windows下搭建的程序也不能发送注册邮件,很是奇怪。

    初步判断是代码没有问题,本地Linux服务器由于以前也鼓捣过其它东西,不一定与云端服务器保持一致。于是只能从官方文档的发送邮件说明入手,慢慢找原因。

    from django.core.mail import send_mail
     
    send_mail(u'邮件标题', u'邮件内容', 'from@example.com',
        ['to@example.com'], 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
    ' %(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 = ['abc@gmail.com','test@qq.com']
        #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'邮件内容', 'xxxx@163.com',['qqqq@163.com'],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'邮件内容', 'xxxx@163.com',['qqqq@163.com'])

    这样的显示调用,原先的线程函处理方法也正确的工作了,看来,上面的两种线程发送邮件都是可用的。问题出现在变量上。

    那么这个user.username又是什么,继续寻找…是使用的User引入的用户对象

    from django.contrib.auth.models import User

    看来问题不是出现在邮件发送方法上,而是用户对象上。至于为何本地的Linux不经配置,可以直接使用…(请教了作者,作者认为可能是django自带的邮件服务,暂时也就先这么放下这个诡异的问题)

    明天开始了解下Django的用户方面,感觉不同平台出现不稳定的情况是因为代码还不够健壮…看能不能有新的发现~

  • 相关阅读:
    linux内核中听过就能记住的概念
    专治不会看源码的毛病--spring源码解析AOP篇
    接口性能优化方案及其理论依据
    Redis各种数据结构性能数据对比和性能优化实践
    iOS 防止UIButton重复点击
    iOS开发之OC与swift开发混编教程,代理的相互调用,block的实现。OC调用Swift中的代理, OC调用Swift中的Block 闭包
    Git简单使用
    软考和软件设计师
    libstdc++适配Xcode10与iOS12
    Objective-C Block与函数指针比较
  • 原文地址:https://www.cnblogs.com/ishell/p/4217319.html
Copyright © 2020-2023  润新知