Django发送邮件的方法
小编给大家分享一下Django发送邮件的方法,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨方法吧!
当我们创建一个网站时,经常会有发送邮件的需要。无论是用户注册,还是用户忘记密码,又或者是用户下单后进行付款确认,都需要发
送不同的邮件。所以发送邮件的需求实际上是非常重要的,而且如果如果不在一开始就建造结构清晰的邮件服务,到后面可能会是一团糟。
基本的邮件发送假设我们希望在用户注册到我们的网站。我们可以参照Django文档,向验证通过并创建成功的用户发送邮件。具体实现如下:
importloggingfromrest_framework.viewsimportAPIViewfromdjango.httpimportJsonResponsefromdjango.core.mailimportsend_mailfromusers.modelsimportUserlogger=logging.getLogger('django')classRegisterView(APIView):defpost(self,request):#Runvalidationsifnotrequest.data:returnJsonResponse({'errors':'Userdatamustbeprovided'},status=400)ifUser.objects.filter(email=request.data['email']).exists():returnJsonResponse({'errors':'Emailalreadyinuse'},status=400)try:#Createnewuseruser=User.objects.create_user(email=request.data['email'].lower())user.set_password(request.data['password'])user.save()#Sendwelcomeemailsend_mail(subject='Welcome!',message='Heythere!Welcometoourplatform.',html_message='<p><strong>Hetthere!</strong>Welcometoourplatform.</p>'from_email='from@example.com',recipient_list=[user.email],fail_silently=False,)returnJsonResponse({'status':'ok'})exceptExceptionase:logger.error('Errorat%s','registerview',exc_info=e)returnJsonResponse({'errors':'Wrongdataprovided'},status=400)
当然肯定文档中所说的那样,你也必须提前设定好一些重要的配置项,例如EMAIL_HOST和EMAIL_PORT。
很好!现在我们已经发送了欢迎邮件!
创建一个mailer类正如我之前所说,在我们的应用中不同的模块可能都需要发送邮件,所以最好有一个电子邮件服务或者mailer类来处理所有的邮件请求。更简单,因为我们不再需要每次都去翻遍全部代码。
iimportloggingfromdjango.confimportsettingsfromdjango.core.mailimportsend_mailfromusers.modelsimportUserlogger=logging.getLogger('django')classBaseMailer():def__init__(self,to_email,subject,message,html_message):self.to_email=to_emailself.subject=subjectself.message=messageself.html_message=html_messagedefsend_email(self):send_mail(subject=self.subject,message=self.message,html_message=self.html_message,from_email='from@example.com',recipient_list=[self.to_email],fail_silently=False,)
让我们来看看经过这次改变后,注册服务的视图层是某种子:
importloggingfromrest_framework.viewsimportAPIViewfromdjango.httpimportJsonResponsefromdjango.core.mailimportsend_mailfromusers.modelsimportUserfromusers.mailersimportBasicMailerlogger=logging.getLogger('django')classRegisterView(APIView):defpost(self,request):#Runvalidationsifnotrequest.data:returnJsonResponse({'errors':'Userdatamustbeprovided'},status=400)ifUser.objects.filter(email=request.data['email']).exists():returnJsonResponse({'errors':'Emailalreadyinuse'},status=400)try:#Createnewuseruser=User.objects.create_user(email=request.data['email'].lower())user.set_password(request.data['password'])user.save()#SendwelcomeemailBasicMailer(to_email=user.email,subject='Welcome!',message='Heythere!Welcometoourplatform.',html_message='<p><strong>Hetthere!</strong>Welcometoourplatform.</p>').send_email()returnJsonResponse({'status':'ok'})exceptExceptionase:logger.error('Errorat%s','registerview',exc_info=e)returnJsonResponse({'errors':'Wrongdataprovided'},status=400)作者:cyril_lee链接:https://juejin.im/post/5eb6171c5188256d7a3cac97来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
mailer子类
现在我们已经把所有的“邮件代码”移动到一个单独的地方,可以把它利用起来啦!这时候可以继续创建特定的mailer类,并让它们知道每次被调用时该发送什么内容。让我们创建一个mailer类用来在每次用户注册时进行调用,另一个mailer类用来发送订单的确认信息。
importloggingfromdjango.confimportsettingsfromdjango.core.mailimportsend_mailfromusers.modelsimportUserlogger=logging.getLogger('django')classBaseMailer():def__init__(self,to_email,subject,message,html_message):self.to_email=to_emailself.subject=subjectself.message=messageself.html_message=html_messagedefsend_email(self):send_mail(subject=self.subject,message=self.message,html_message=self.html_message,from_email='from@example.com',recipient_list=[self.to_email],fail_silently=False,)classRegisterMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='Welcome!',message='Heythere!Welcometoourplatform.',html_message='<p><strong>Hetthere!</strong>Welcometoourplatform.</p>')classNewOrderMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='NewOrder',message='Youhavejustcreatedaneworder',html_message='<p>Youhavejustcreatedaneworder.</p>')
这表明在不同的场景下集成邮件服务是非常简单的。你只需要构造一个基础的邮件类来进行实现,然后在子类中设置具体内容。
因为不用实现所有邮件相关的代码,所以现在我们注册服务的视图层看起来更加简明:
importloggingfromrest_framework.viewsimportAPIViewfromdjango.httpimportJsonResponsefromdjango.core.mailimportsend_mailfromusers.modelsimportUserfromusers.mailersimportRegisterMailerlogger=logging.getLogger('django')classRegisterView(APIView):defpost(self,request):#Runvalidationsifnotrequest.data:returnJsonResponse({'errors':'Userdatamustbeprovided'},status=400)ifUser.objects.filter(email=request.data['email']).exists():returnJsonResponse({'errors':'Emailalreadyinuse'},status=400)try:#Createnewuseruser=User.objects.create_user(email=request.data['email'].lower())user.set_password(request.data['password'])user.save()#SendwelcomeemailRegisterMailer(to_email=user.email).send_email()returnJsonResponse({'status':'ok'})exceptExceptionase:logger.error('Errorat%s','registerview',exc_info=e)returnJsonResponse({'errors':'Wrongdataprovided'},status=400)使用Sendgrid
假设我们必须使用正式的蟒库将我们的邮件服务后端迁移Sendgrid(一个用于交易和营销邮件的客户通信平台)。我们将不能再使用的Django的SEND_EMAIL方法,而且我们还不得不使用新库的语法。
嗯,但我们还是很幸运的地方!因为我们已经将所有与邮件管理相关的代码都放到了一个单独的地方,所以我们可以很轻松的进行这场比赛
importloggingfromdjango.confimportsettingsfromsendgridimportSendGridAPIClient,Email,Personalizationfromsendgrid.helpers.mailimportMailfromusers.modelsimportUserlogger=logging.getLogger('django')classBaseMailer():def__init__(self,email,subject,template_id):self.mail=Mail()self.subject=subjectself.template_id=template_iddefcreate_email(self):self.mail.from_email=Email(settings.FROM_EMAIL)self.mail.subject=self.subjectself.mail.template_id=self.template_idpersonalization=Personalization()personalization.add_to(Email(self.user.email))self.mail.add_personalization(personalization)defsend_email(self):self.create_email()try:sg=SendGridAPIClient(settings.SENDGRID_API_KEY)sg.send(self.mail)exceptExceptionase:logger.error('Errorat%s','mailer',exc_info=e)classRegisterMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='Welcome!',template_id=1234)classNewOrderMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='NewOrder',template_id=5678)
请注意,您必须在配置文件中设置Sendgrid的api密钥,以及指定需要被使用的模板的ID,Sendrid会直接从自己的页面中根据这个ID来加载指定的html邮件模版。
太好了!这并不困难,而且我们不用去修改发送邮件的每一行代码。
现在让我们的步子再迈大一点。
根据域信息定制邮件内容
当然我们发送邮件的时候,有时候可能也会使用一些域信息来填充模板。比如说,如果在欢迎邮件里面能有新用户的名字,那肯定会显得更友好。Sendgrid 允许你在邮件模板中定义变量,这些变量将替换为从我们这里接收的实际信息。所以现在让我们来添加这部分数据吧!
importloggingfromdjango.confimportsettingsfromsendgridimportSendGridAPIClient,Email,Personalizationfromsendgrid.helpers.mailimportMailfromusers.modelsimportUserlogger=logging.getLogger('django')classBaseMailer():def__init__(self,email,subject,template_id):self.mail=Mail()self.user=User.objects.get(email=email)self.subject=subjectself.template_id=template_idself.substitutions={'user_name':self.user.first_name,'user_surname':self.user.last_name}defcreate_email(self):self.mail.from_email=Email(settings.FROM_EMAIL)self.mail.subject=self.subjectself.mail.template_id=self.template_idpersonalization=Personalization()personalization.add_to(Email(self.user.email))personalization.dynamic_template_data=self.substitutionsself.mail.add_personalization(personalization)defsend_email(self):self.create_email()try:sg=SendGridAPIClient(settings.SENDGRID_API_KEY)sg.send(self.mail)exceptExceptionase:logger.error('Errorat%s','mailer',exc_info=e)classRegisterMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='Welcome!',template_id=1234)classNewOrderMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='NewOrder',template_id=5678)
这里我看到的唯一一个问题是替换方案不那么灵活。很可能会发生的情况是,我们传递的数据可能是用户根据请求的上下文访问不到的。比如说,新的订单编号、重置密码的链接等等。这些变量参数可能很多,把它们作为命名参数传递可能会让代码变得比较脏乱。我们希望的是一个基于关键字,并且长度可变的参数列表,一般来说会被定义为 **kwargs,但在此我们命名它为 **substitutions,让这个表达会更形象:
importloggingfromdjango.confimportsettingsfromsendgridimportSendGridAPIClient,Email,Personalizationfromsendgrid.helpers.mailimportMailfromusers.modelsimportUserlogger=logging.getLogger('django')classBaseMailer():def__init__(self,email,subject,template_id,**substitutions):self.mail=Mail()self.user=User.objects.get(email=email)self.subject=subjectself.template_id=template_idself.substitutions={'user_name':self.user.first_name,'user_surname':self.user.last_name}forkeyinsubstitutions:self.substitutions.update({key:substitutions[key]})defcreate_email(self):self.mail.from_email=Email(settings.FROM_EMAIL)self.mail.subject=self.subjectself.mail.template_id=self.template_idpersonalization=Personalization()personalization.add_to(Email(self.user.email))personalization.dynamic_template_data=self.substitutionsself.mail.add_personalization(personalization)defsend_email(self):self.create_email()try:sg=SendGridAPIClient(settings.SENDGRID_API_KEY)sg.send(self.mail)exceptExceptionase:logger.error('Errorat%s','mailer',exc_info=e)classRegisterMailer(BaseMailer):def__init__(self,to_email,**substitutions):super().__init__(to_email,subject='Welcome!',template_id=1234,**substitutions)classNewOrderMailer(BaseMailer):def__init__(self,to_email):super().__init__(to_email,subject='NewOrder',template_id=5678,**substitutions)
如果希望将额外信息传递给 mailer 类,就需要按如下编码:
NewOrderMailer(user.email,order_id=instance.id).send_email()PasswordResetMailer(user.email,key=password_token.key).send_email()
看完了这篇文章,相信你对Django发送邮件的方法有了一定的了解,想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。