naritoブログ

【お知らせ】
新ブログができました。今後そちらで更新し、このサイトは更新されません(ウェブサイト自体は残しておきます)
このブログの内容に関してコメントしたい場合は、新ブログのフリースペースに書き込んでください

このブログの内容を新ブログに移行中です。このブログで見つからない記事は、新ブログにありま

Djangoで、メール通知アプリを作る

約317日前 2017年12月31日16:22
プログラミング関連
Django Python
今回はちょっとしたメール通知アプリを作ります。

まず、管理画面でこのようにスケジュールを登録し...


以下のようなコマンドを入力すると、メールの送信が開始されます。

python manage.py mail



メールの送信が終わると、送信済みと表示されるようにしました。



今回は管理画面からのデータ追加と、Djangoのカスタムコマンドを作成するだけなので、ビューやテンプレートは作りません。
まず、models.py

from django.conf import settings
from django.db import models
from django.utils import timezone


class To(models.Model):
"""連絡先"""

email = models.EmailField('メールアドレス')
name = models.CharField('名前', max_length=255)
created_at = models.DateTimeField('作成日', default=timezone.now)

def __str__(self):
return '{0}({1})'.format(self.name, self.email)


class Schedule(models.Model):
"""通知スケジュール"""

datetime = models.DateTimeField('連絡日・時間')
subject = models.CharField('題名', max_length=255)
text = models.TextField('本文')
mail_from = models.EmailField('From', default=settings.EMAIL_HOST_USER)
mail_to = models.ManyToManyField(To, verbose_name='To')
is_sended = models.BooleanField('送信済みフラグ', default=False)
created_at = models.DateTimeField('作成日', default=timezone.now)

def __str__(self):
message = '{0} {1}'
sended = '送信済み' if self.is_sended else '未送信'
return message.format(self.subject, sended)





連絡先は、一度登録したら使いまわせるようにモデルにしました。Toモデルです。それをManyToManyで紐付けます。
Scheduleモデルは、連絡する日・時間と、メールの題名、本文、送信元、送信先、送信フラグ、といったフィールドをもたせます。

今回はappというアプリケーション名です。appフォルダ内に、「management」フォルダを作ります。その中に「commands」フォルダを作り...
そして、mail.pyを以下のように作ります。

import time
from django.core.management.base import BaseCommand
from django.core.mail import send_mail
from django.utils import timezone
from app.models import Schedule


def _send_mail(schedule):
"""メールの送信処理"""
# 送信者達
recipient_list = [to.email for to in schedule.mail_to.all()]

# メールの送信
send_mail(schedule.subject, schedule.text, schedule.mail_from, recipient_list)


class Command(BaseCommand):
def handle(self, *args, **options):
while True:
now = timezone.now()
schedule_list = Schedule.objects.filter(datetime__lte=now, is_sended=False)
for schedule in schedule_list:
_send_mail(schedule)
schedule.is_sended = True
schedule.save()
time.sleep(10)




コマンドの実行で、handleメソッドが呼ばれます。
handleメソッド内では、未送信で今現在を過ぎているScheduleを取得します。
それをfor文で順番に取り出し、メールを送信し、送信済みフラグをTrueにし、time.sleep(10)で10秒ほど待機します。
whileでの無限ループなので、10秒毎にこの処理を繰り返します。

cron等を使うのもよさそうですが、今回は無限ループの中で10秒毎に送信メールがあるかを確認する、という方法を使いました。
Gmailを使いましたが、この場合はsettings.pyに設定を記述します。

EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'toritoritorina@gmail.com'
EMAIL_HOST_PASSWORD = パスワードを入れる。2段階認証をしておかないと、弾かれることがあります
EMAIL_USE_TLS = True



メールの題名、本文はテンプレートを使って組み立てることもできます。
関連記事の「Djangoで、メール送信」に書いています。