邮件发送工具类
基于from django.core.mail import send_mail 抽取公共的逻辑封装成基本的EmailSender,其他类型的邮件则继承该类,定义好邮件内容模板路径以及模板上下文参数即可。这里利用django的template将邮件内容抽离出来变成模板,也方便了后期页面样式调整。
from django.urls import reverse
from django.utils.crypto import get_random_string
from system.models import EmailRecord, User
from django.core.mail import send_mail
from django.template.loader import render_to_string
from myblog.email_settings import EMAIL_FROM
from myblog.settings import SITE_URL, SITE_NAME
import logging
logger = logging.getLogger(__name__)
class EmailSender(object):
template_name = ""
from_email = EMAIL_FROM
site_url = SITE_URL
site_name = SITE_NAME
def __init__(self, email_type="", username=""):
self.email_type = email_type
self.receiver = self.get_receiver(username)
self.record = EmailRecord(email_type=email_type, code=get_random_string(16), receiver=self.receiver)
self.title = self.record.get_email_type_display()
@staticmethod
def get_receiver(username=""):
try:
user = User.objects.only("username", "id", "email").get(username=username)
return user
except User.DoesNotExist:
raise ValueError("用户名不存在")
def get_template_context(self):
return {"title": self.title, "receiver": self.receiver, "site_name": self.site_name,
"site_url": self.site_url}
def send(self, *args, **kwargs):
context = self.get_template_context(*args, **kwargs)
subject = f"{self.site_name}{self.title}邮件"
html_message = render_to_string(self.template_name, context)
try:
send_mail(from_email=self.from_email,
subject=subject,
message="",
recipient_list=[self.receiver.email],
html_message=html_message)
self.record.succeed = True
logger.info(f"[receiver: {self.receiver.email}]邮件发送成功")
except Exception as e:
self.record.succeed = False
logger.info(f"[receiver: {self.receiver.email}][msg:{e}]邮件发送失败")
self.record.save()
注册激活模板
新建\myblog\templates\user\email-register-active.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ title|default:'个人博客' }}通知邮件</title>
</head>
<body>
<table style="width: 600px; border: 1px solid #ddd; border-radius: 3px; color: #555; font-family: 'Helvetica Neue Regular',Helvetica,Arial,Tahoma,'Microsoft YaHei','San Francisco','微软雅黑',' Hiragino Sans GB',STHeitiSC-Light; font-size: 12px; height: auto; margin: auto; overflow: hidden; text-align: left; word-break: break-all; word-wrap: break-word;"
cellspacing="0" cellpadding="0" border="0">
<tbody style="margin: 0; padding: 0;">
<tr style="background-color: #393D49; height: 60px; margin: 0; padding: 0;">
<td style="margin: 0; padding: 0;">
<div style="color: #5EB576; margin: 0; margin-left: 30px; padding: 0;">
<a style="font-size: 14px; margin: 0; padding: 0; color: #5EB576; text-decoration: none;"
href="{{ site_url|default:'#' }}" target="_blank" rel="noopener">{{ site_name|default:'个人博客' }}——{{ title|default:'这是一封注册激活' }}通知邮件</a>
</div>
</td>
</tr>
<tr style="margin: 0; padding: 0;">
<td style="margin: 0; padding: 30px;">
<p style="line-height: 20px; margin: 0; margin-bottom: 10px; padding: 0;"> Hi,
<em style="padding:0;font-weight:700;color:#6e6e6e;font-size:16px">{{ receiver.username|default:'XXX' }}</em>,你好</p>
<p style="color:#6e6e6e;font-size:13px;line-height:24px">欢迎您注册<em
style="padding:0;font-weight:700;color:#6e6e6e;font-size:16px">[{{ site_name|default:'个人博客' }}博客]</em>,请根据下面的信息完成激活,登陆后如有密码修改需要,可以修改密码!
</p>
<table style="width:100%;border-top:1px solid #eee;border-left:1px solid #eee;color:#6e6e6e;font-weight:normal;"
cellspacing="0" cellpadding="0" border="0">
<thead>
<tr>
<th colspan="2"
style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;background:#f2f2f2;font-weight:700;font-size:16px">
您的注册信息
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;width:100px">
用户名
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
{{ receiver.username|default:'xxxx' }}
</td>
</tr>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;width:100px">
邮箱
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
{{ receiver.email|default:'xxxxxxx@xxx.com' }}
</td>
</tr>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center">
密码
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
{{ password|default:'123456' }}
</td>
</tr>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;width:100px">
激活方式
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
<a href="{{ url|default:'#' }}"
style="background-color: #009E94; color: #fff; display: inline-block; height: 32px; line-height: 32px; margin: 0 15px 0 0; padding: 0 15px; text-decoration: none;"
target="_blank" rel="noopener">立即激活邮箱</a>
</td>
</tr>
</tbody>
</table>
<p style="line-height: 20px; margin-top: 20px; padding: 10px; background-color: #f2f2f2; font-size: 12px;">
如果该邮件不是由你本人操作,请勿进行激活!否则你的邮箱将会被他人绑定。 </p>
</td>
</tr>
<tr style="background-color: #fafafa; color: #999; height: 35px; margin: 0; padding: 0; text-align: center;">
<td style="margin: 0; padding: 0;">系统邮件,请勿直接回复 | {% now "Y/m/d H:m:s" %}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
页面效果:
密码重置邮件模板
新建myblog\templates\user\email-password-reset.html
内容如下
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ title|default:'密码重置' }}通知邮件</title>
</head>
<body>
<table style="width: 600px; border: 1px solid #ddd; border-radius: 3px; color: #555; font-family: 'Helvetica Neue Regular',Helvetica,Arial,Tahoma,'Microsoft YaHei','San Francisco','微软雅黑',' Hiragino Sans GB',STHeitiSC-Light; font-size: 12px; height: auto; margin: auto; overflow: hidden; text-align: left; word-break: break-all; word-wrap: break-word;"
cellspacing="0" cellpadding="0" border="0">
<tbody style="margin: 0; padding: 0;">
<tr style="background-color: #393D49; height: 60px; margin: 0; padding: 0;">
<td style="margin: 0; padding: 0;">
<div style="color: #5EB576; margin: 0; margin-left: 30px; padding: 0;">
<a style="font-size: 14px; margin: 0; padding: 0; color: #5EB576; text-decoration: none;"
href="{{ site_url|default:'#'}}" target="_blank" rel="noopener">{{ site_name|default:'个人博客' }}——{{ title|default:'密码重置' }}通知邮件</a>
</div>
</td>
</tr>
<tr style="margin: 0; padding: 0;">
<td style="margin: 0; padding: 30px;">
<p style="line-height: 20px; margin: 0; margin-bottom: 10px; padding: 0;"> Hi,
<em style="padding:0;font-weight:700;color:#6e6e6e;font-size:16px">{{ receiver.username|default:'XXX' }}</em>,你好</p>
<p style="color:#6e6e6e;font-size:13px;line-height:24px">请使用下面的信息完成密码修改!</p>
<table style="width:100%;border-top:1px solid #eee;border-left:1px solid #eee;color:#6e6e6e;font-size:auto;font-weight:normal"
cellspacing="0" cellpadding="0" border="0">
<thead>
<tr>
<th colspan="2"
style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;background:#f2f2f2;font-weight:700;font-size:16px">
您的个人信息
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;width:100px">
用户名
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
{{ receiver.username|default:'XXX' }}
</td>
</tr>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;width:100px">
登录邮箱
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
{{ receiver.email|default:'xxxxxxx@xxx.com' }}
</td>
</tr>
<tr>
<td style="padding:10px 0;border-right:1px solid #eee;border-bottom:1px solid #eee;text-align:center;width:100px">
修改方式
</td>
<td style="padding:10px 20px 10px 30px;border-right:1px solid #eee;border-bottom:1px solid #eee;line-height:30px">
<a href="{{ url|default:'#'}}"
style="background-color: #009E94; color: #fff; display: inline-block; height: 32px; line-height: 32px; margin: 0 15px 0 0; padding: 0 15px; text-decoration: none;"
target="_blank" rel="noopener">去重置密码</a>
</td>
</tr>
</tbody>
</table>
<p style="line-height: 20px; margin-top: 20px; padding: 10px; background-color: #f2f2f2; font-size: 12px;">
有人要求重设您在[{{ site_name|default:'个人博客' }}]的密码,若不是您本人请求,请忽略本邮件。</p>
</td>
</tr>
<tr style="background-color: #fafafa; color: #999; height: 35px; margin: 0; padding: 0; text-align: center;">
<td style="margin: 0; padding: 0;">系统邮件,请勿直接回复 | {% now "Y/m/d H:m:s" %}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
页面效果如下:
评论审核邮件模板
新建myblog\templates\user\email-comment-check.html
内容如下
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ title|default:'评论审核' }}通知邮件</title>
</head>
<body>
<table style="width: 600px; border: 1px solid #ddd; border-radius: 3px; color: #555; font-family: 'Helvetica Neue Regular',Helvetica,Arial,Tahoma,'Microsoft YaHei','San Francisco','微软雅黑',' Hiragino Sans GB',STHeitiSC-Light; font-size: 12px; height: auto; margin: auto; overflow: hidden; text-align: left; word-break: break-all; word-wrap: break-word;"
cellspacing="0" cellpadding="0" border="0">
<tbody style="margin: 0; padding: 0;">
<tr style="background-color: #393D49; height: 60px; margin: 0; padding: 0;">
<td style="margin: 0; padding: 0;">
<div style="color: #5EB576; margin: 0; margin-left: 30px; padding: 0;">
<a style="font-size: 14px; margin: 0; padding: 0; color: #5EB576; text-decoration: none;"
href="{{ site_url|default:'#' }}" target="_blank" rel="noopener">{{ site_name|default:'个人博客' }}——{{ title|default:'评论审核' }}通知邮件</a>
</div>
</td>
</tr>
<tr style="margin: 0; padding: 0;">
<td style="margin: 0; padding: 30px;">
<p style="line-height: 20px; margin: 0; margin-bottom: 10px; padding: 0;"> Hi,
<em style="padding:0;font-weight:700;color:#6e6e6e;font-size:16px">主人</em>,你好</p>
<p style="color:#6e6e6e;font-size:13px;line-height:24px">您有一条新的留言,摘要信息请见下表。</p>
<table style="font-size:14px;text-align:center;border:1px solid #ccc;table-layout:fixed;width:500px;"
cellspacing="0">
<thead>
<tr>
{#文章评论#}
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;"
width="280px;">文章
</th>
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;"
width="270px;">内容
</th>
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;"
width="110px;">操作
</th>
</tr>
</thead>
<tbody>
<tr>
{#文章评论#}
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
《{{ comment.article.title|default:'xxxxxxxxxxxxx' }}》
</td>
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">{{ comment.content|default:'xxxxxxxxxxxxxx'|safe|truncatechars_html:'15' }}</td>
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<a href="{{ url|default:'#' }}"
style="background-color: #009E94; color: #fff; display: inline-block; height: 32px; line-height: 32px; margin: 0 15px 0 0; padding: 0 15px; text-decoration: none;"
target="_blank" rel="noopener">审核通过</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr style="background-color: #fafafa; color: #999; height: 35px; margin: 0; padding: 0; text-align: center;">
<td style="margin: 0; padding: 0;">系统邮件,请勿直接回复 | {% now "Y/m/d H:m:s" %}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
页面效果如下:
评论审核通过邮件模板
新建myblog\templates\user\email-comment-notice.html
内容如下
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ title|default:'评论审核通过' }}通知邮件</title>
</head>
<body>
<table style="width: 600px; border: 1px solid #ddd; border-radius: 3px; color: #555; font-family: 'Helvetica Neue Regular',Helvetica,Arial,Tahoma,'Microsoft YaHei','San Francisco','微软雅黑',' Hiragino Sans GB',STHeitiSC-Light; font-size: 12px; height: auto; margin: auto; overflow: hidden; text-align: left; word-break: break-all; word-wrap: break-word;"
cellspacing="0" cellpadding="0" border="0">
<tbody style="margin: 0; padding: 0;">
<tr style="background-color: #393D49; height: 60px; margin: 0; padding: 0;">
<td style="margin: 0; padding: 0;">
<div style="color: #5EB576; margin: 0; margin-left: 30px; padding: 0;">
<a style="font-size: 14px; margin: 0; padding: 0; color: #5EB576; text-decoration: none;"
href="{{ site_url|default:'#' }}" target="_blank"
rel="noopener">{{ site_name|default:'个人博客' }}——{{ title|default:'评论审核通过' }}通知邮件</a>
</div>
</td>
</tr>
<tr style="margin: 0; padding: 0;">
<td style="margin: 0; padding: 30px;">
<p style="line-height: 20px; margin: 0; margin-bottom: 10px; padding: 0;"> Hi,
<em style="padding:0;font-weight:700;color:#6e6e6e;font-size:16px">{{ comment.creator.username|default:'xxxxxxxxx' }}</em>,你好
</p>
<p style="color:#6e6e6e;font-size:13px;line-height:24px">您有一条留言通过了管理员的审核并显示在文章页面,摘要信息请见下表。</p>
<table style="font-size:14px;text-align:center;border:1px solid #ccc;table-layout:fixed;width:500px;"
cellspacing="0">
<thead>
<tr>
{
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;"
width="280px;">文章
</th>
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;"
width="270px;">内容
</th>
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;"
width="110px;">操作
</th>
</tr>
</thead>
<tbody>
<tr>
{
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
《{{ comment.article.title|default:'xxxxxxxxxxxxxxxxx' }}》
</td>
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">{{ comment.content|default:'xxxxxxxxxxxxxxxx'|safe|truncatechars_html:'15' }}</td>
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<a href="{{ url|default:'#' }}"
style="background-color: #009E94; color: #fff; display: inline-block; height: 32px; line-height: 32px; margin: 0 15px 0 0; padding: 0 15px; text-decoration: none;"
target="_blank" rel="noopener">查看留言</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr style="background-color: #fafafa; color: #999; height: 35px; margin: 0; padding: 0; text-align: center;">
<td style="margin: 0; padding: 0;">系统邮件,请勿直接回复 | {% now "Y/m/d H:m:s" %}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
页面效果如下:
评论回复邮件模板
新建myblog\templates\user\email-comment-reply.html
内容如下
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ title|default:'个人博客' }}通知邮件</title>
</head>
<body>
<table style="width: 600px; border: 1px solid #ddd; border-radius: 3px; color: #555; font-family: 'Helvetica Neue Regular',Helvetica,Arial,Tahoma,'Microsoft YaHei','San Francisco','微软雅黑',' Hiragino Sans GB',STHeitiSC-Light; font-size: 12px; height: auto; margin: auto; overflow: hidden; text-align: left; word-break: break-all; word-wrap: break-word;"
cellspacing="0" cellpadding="0" border="0">
<tbody style="margin: 0; padding: 0;">
<tr style="background-color: #393D49; height: 60px; margin: 0; padding: 0;">
<td style="margin: 0; padding: 0;">
<div style="color: #5EB576; margin: 0; margin-left: 30px; padding: 0;">
<a style="font-size: 14px; margin: 0; padding: 0; color: #5EB576; text-decoration: none;"
href="{{ site_url|default:'#' }}" target="_blank"
rel="noopener">{{ site_name|default:'个人博客' }}——{{ title|default:'评论回复' }}通知邮件</a>
</div>
</td>
</tr>
<tr style="margin: 0; padding: 0;">
<td style="margin:40px auto;width:90%">
{#文章评论#}
<p>
你好,{{ comment.parent.creator.username|default:'张三' }}。您曾在文章《{{ comment.parent.article.title|default:'xxxxxxx'|truncatechars:'10' }}》上发表评论:</p>
<p style="background-color: #f5f5f5;border: 0px solid #DDD;padding: 10px 15px;margin:18px 0;">{{ comment.parent.content|default:'xxxxxxxxxxxxxxxx'|safe|truncatechars_html:'15' }}</p>
<p>{{ comment.creator.username|default:'李四' }} 给您的回复如下:</p>
<p style="background-color: #f5f5f5;border: 0px solid #DDD;padding: 10px 15px;margin:18px 0;">{{ comment.content|default:'XXXXXXXXX'|safe|truncatechars_html:15 }}</p>
<p>您可以点击 <a style="text-decoration:none; color:#12addb" href="{{ url|default:'#' }}" rel="noopener"
target="_blank">查看回复的完整內容 </a>,欢迎再次光临 <a style="text-decoration:none; color:#12addb"
href="{{ site_url|default:'#' }}" rel="noopener"
target="_blank"> {{ site_name|default:'个人博客' }}网站 </a>。
</p>
</td>
</tr>
<tr style="background-color: #fafafa; color: #999; height: 35px; margin: 0; padding: 0; text-align: center;">
<td style="margin: 0; padding: 0;">系统邮件,请勿直接回复 | {% now "Y/m/d H:m:s" %}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
页面效果如下:
|