通过django框架表CRUD实现发邮件

需求分析

想建立一张电子邮件表, 当往表里面写一行记录的时候, 自动发邮件, 邮件的配置就是表里的内容.

方案

发邮件本身, 可以使用django-email来实现. 然后定义信号函数, 当表被save的时候自动发邮件. 然后通过xadmin做管理

code

settings.py

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.partner.outlook.cn'
EMAIL_PORT = 25
EMAIL_HOST_USER = 'xxx'
EMAIL_HOST_PASSWORD = 'xxx'
DEFAULT_FROM_EMAIL = 'xxx'

utils/django_email.py

# -*- coding: utf-8 -*-
__author__ = '陈章'
__date__ = '2019/9/9 15:22'
import os
import sys

pwd = os.path.dirname(os.path.realpath(__file__))
sys.path.append(pwd + '/../')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xxx_xadmin.settings")

import django

django.setup()
from django.conf import settings
from django.core.mail import EmailMultiAlternatives


def send_email(to_addr, subject, content, attachments=None):
    if attachments is None:
        attachments = []
    if not isinstance(to_addr, list):
        to_addr = [to_addr]
    from_email = settings.DEFAULT_FROM_EMAIL
    msg = EmailMultiAlternatives(subject, content, from_email, to_addr)
    msg.content_subtype = "html"

    # 添加附件(可选)
    for a in attachments:
        msg.attach_file(a)
    # 发送
    msg.send()


if __name__ == '__main__':
    send_email("chenzhang@xxx.cn", "测试", "啪啪啪",
               attachments=["~/xxx_xadmin/utils/django_email.py",
                            '~/xxx_xadmin/utils/exceptions.py'])

models.py

# -*- coding: utf-8 -*-
__author__ = '陈章'
__date__ = '2019/9/9 15:00'
from django.contrib.postgres.fields import ArrayField
from django.db import models

from DjangoUeditor.models import UEditorField
from xxx_xadmin.settings import DEFAULT_FROM_EMAIL

class Email(models.Model):
    STATUS_CHOICES = (('发送中', '发送中'), ('发送完成', '发送完成'), ('发送失败', '发送失败'))
    sender = models.EmailField(help_text='发件人', default=DEFAULT_FROM_EMAIL)
    receivers = ArrayField(models.EmailField(), help_text='收件人(多个用逗号隔开)')
    subject = models.CharField(max_length=200, help_text='邮件主题')
    content = UEditorField(help_text="内容", imagePath="emails/content_img", width=1000, height=300,
                           filePath="emails/content_files", default='')
    status = models.CharField(max_length=100, choices=STATUS_CHOICES, default='发送中', help_text=f'发送状态 {STATUS_CHOICES}')
    fail_reason = models.TextField(help_text='失败原因', default='')
    attachments_path_list = ArrayField(models.FilePathField(), verbose_name='附件路径列表')
    update_time = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = '电子邮件'
        verbose_name_plural = verbose_name

    def attachment_count(self):
        return len(self.attachments_path_list)

signals.py

# -*- coding: utf-8 -*-
__author__ = '陈章'
__date__ = '2019/9/9 19:47'
from django.dispatch import receiver
from django.db.models.signals import post_save
from .models import Email
import traceback


@receiver(post_save, sender=Email)
def send_emails_after_save(sender, instance=None, created=False, **kwargs):
    from utils.django_email import send_email
    if created:
        attachments_path_list = instance.attachments_path_list
        try:
            send_email(instance.receivers, instance.subject, instance.content,
                       attachments_path_list)
        except Exception as e:
            instance.status = '发送失败'
            instance.fail_reason = traceback.format_exc()
        else:
            instance.status = '发送完成'
        instance.save()

apps.py

# -*- coding: utf-8 -*-
__author__ = '陈章'
__date__ = '2019/9/9 19:53'

from django.apps.config import AppConfig


class EmailsConfig(AppConfig):
    name = 'emails'
    verbose_name = '电子邮件'

    def ready(self):
        from emails import signals
        id(signals)

adminx.py

# -*- coding: utf-8 -*-
__author__ = '陈章'
__date__ = '2019/9/9 16:20'
import xadmin
from .models import Email


class EmailAdmin:
    list_display = ["sender", "receivers", "subject", "content", "status", "update_time", 'attachment_count']
    exclude = ["status", "update_time", ]
    remove_permissions = ('change',)
    style_fields = {"content": "ueditor"}


xadmin.site.register(Email, EmailAdmin)