Webフォームから送信されたデータを保存後にメールでユーザーやら担当者やらに送信する処理が必要な事が多い。
メール送信処理は結構重いので、リクエスト中に送信するのではなく、後でバッチ処理で送信する処理を作ってみた。
送信するメールを保存するモデルはこんな感じ
# -*- coding: utf-8 -*- from datetime import datetime from django.db import models from django.core.mail import send_mail # Create your models here. class SendMail(models.Model): sender = models.CharField("送信元メールアドレス", max_length=255) recipients = models.TextField("送信先メールアドレス", help_text="1行に1つメールアドレスを入力してください") title = models.CharField("メールタイトル", max_length=255) contents = models.TextField("メール内容") is_sended = models.BooleanField("送信済み") insert_date = models.DateTimeField("登録日", auto_now_add=True) sended_date = models.DateTimeField("送信日", blank=True, null=True) def get_recipient_list(self): recipient_list = self.recipients.split("\n") return recipient_list def set_recipient_list(self, recipient_list): self.recipients = "\n".join(recipient_list) def send(self): send_mail(self.title, self.contents, self.sender, self.get_recipient_list(), fail_silently=True) self.is_sended = True self.sended_date = datetime.now() self.save() class Meta: verbose_name = "送信メール" verbose_name_plural = "送信メール" ordering = ["-insert_date"] def __unicode__(self): return self.title
メールを生成するユーティリティ関数も作っておく。
メールテンプレートからメールを生成するようにしてやる。
utils.pyとかで作る。
from django.conf import settings from django.core.mail import send_mail from django.template.loader import render_to_string from batchmail.models import SendMail def create_mail_from_template(subject, body_template_path="", body_values={}, recipients=[], sender=settings.DEFAULT_FROM_EMAIL): message = render_to_string(body_template_path, body_values) mail = SendMail() mail.sender = sender mail.set_recipient_list(recipients) mail.title = subject mail.contents = message mail.is_sended = False mail.save() return mail
下記のような感じでフォーム内容の保存後にメールを保存する。
... mail = create_mail_from_template(mail_title, "mailform/mail_message.txt", form_data, [form_data["admin_mail"]]) ...
メールの送信は、下記のようなスクリプトを作成して程良い間隔でcronで呼び出す。
# -*- coding: utf-8 -*- # 送信待ちのメールを送信します import sys import socket if socket.gethostname() == "xxxxxxxx.com": HOME_PATH = "/path_to_server_project" else: HOME_PATH = "/path_to_local_project" sys.path.append(HOME_PATH) from django.core.management import setup_environ from batchmail import settings setup_environ(settings) from batchmail.models import SendMail def main(): waiting_mail_list = SendMail.objects.filter(is_sended=False) for mail in waiting_mail_list: mail.send() if __name__ == "__main__": main()
ちょっとしたメール送信処理ならこれでまかなえるかな。
フォームに依存しないので、複数のフォームからのメール送信もできそう。