/**
제 벨로그를 방문해주셔서 감사합니다.
Django Admin을 베이스로 작성된 글입니다.
잘못된 정보가 있을 수 있습니다. 댓글이나 caputdraconis@kakao.com으로 오류사항을 전달해주시면 바로 반영하겠습니다.
*/
Django Admin으로 구현된 기존 관리자 대시보드에는, 단체 이메일을 보내는 기능이 존재했습니다. 사용한 라이브러리와 서비스는 아래와 같습니다.
아래 사진과 같이 이메일 템플릿을 사용하여 이메일을 전송하는 기능이였습니다.
하지만, 기존의 메일 시스템의 가장 큰 단점은 직접 이메일 템플릿을 HTML, CSS로 제작하여 이를 붙여넣기 해야한다는 점이였습니다. 이는 관리자 대시보드의 사용자인 에디터 분에게는 아주 곤혹스러운 일이였습니다.
CampaignMonitor란? Drag&Drop으로 이메일 템플릿을 제작할 수 있는 서비스입니다.
메일을 보낼 때마다 위 과정을 반복해야 했으니깐요.
현재의 관리자 대시보드 단체 메일 기능은 기존의 시스템을 모두 버리고 새롭게 처음부터 다시 개발하였습니다. 사용한 라이브러리와 서비스는 아래와 같습니다.
AWS에서 제공하는 클라우드 기반 이메일 발송 서비스/플랫폼 입니다. 사용자의 이메일 주소와 도메인을 사용해 SMTP 방식과 API 방식을 사용하여 이메일을 보내고 받을 수 있습니다.
AWS SES로 갈아타도록 만든 AWS SES의 장점, 그리고 사용하며 느낀 단점은 아래와 같습니다.
기존 관리자 대시보드의 가장 큰 단점이였던 이메일 템플릿을 해결하기 위해서입니다. 위지위그 리치 텍스트 에디터인 CKEditor를 사용하여 에디터가 직접 사진이나, 표를 넣거나 글을 작성하고 배치할 수 있습니다. 그리고 이 결과값은 HTML로 저장되어 그대로 이메일 템플릿으로 사용할 수 있습니다.
우선 메일 전송만 구현한 코드입니다. 도움이 되었으면 합니다.
CKEDITOR_UPLOAD_PATH = 'email/images/' # CKEditor에서 이미지를 넣을 때, 이 이미지를 업로드할 경로입니다. 저는 S3의 상대경로로 주었습니다.
CKEDITOR_IMAGE_BACKEND = "pillow"
EMAIL_HOST = os.environ['AWS_SES_API_ENDPOINT'] # AWS-SES -> SMTP Settings로 들어가면 SMTP endpoint에 적혀있는 주소입니다.
EMAIL_HOST_USER = os.environ['AWS_SES_ACCESS_KEY_ID'] # SES Full Access를 가지고 있는 IAM의 Access Key ID
EMAIL_HOST_PASSWORD = os.environ['AWS_SES_SECRET_ACCESS_KEY'] # 위 ID로 적은 IAM 계정의 Secret Access key
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_PORT = 587 # 25, 587, 2587 중 아무거나
EMAIL_USE_TLS = True # TLS는 필수
from django.db import models
from django.utils import timezone
from core.utils import generateUUID
from ckeditor_uploader.fields import RichTextUploadingField
from django.utils.html import strip_tags
from django.core.mail import EmailMultiAlternatives
class OutgoingMail(models.Model):
class OUTGOING_MAIL_STATUS(models.TextChoices):
SUCCESS = 'SUCCESS'
FAIL = 'FAIL'
TEMPORARY = 'TEMPORARY'
id = models.TextField(primary_key=True, db_column='id', default=generateUUID, editable=False)
recipients = models.TextField(
verbose_name='수신 이메일',
db_column='recipients',
blank=False, null=False
)
sender = models.CharField(
verbose_name='발신 이메일',
db_column='sender',
blank=False, null=False,
max_length=50
)
subject = models.CharField(
verbose_name='제목',
db_column='subject',
max_length=500,
blank=False, null=False
)
content = RichTextUploadingField(
verbose_name='내용',
db_column='content',
blank=False, null=False
)
status = models.TextField(choices=OUTGOING_MAIL_STATUS.choices, verbose_name='상태', default=OUTGOING_MAIL_STATUS.TEMPORARY, editable=False)
createdat = models.DateTimeField(db_column='createdAt', default=timezone.now, verbose_name='메일 작성일', editable=False)
def save(self, *args, **kwargs):
subject, from_email, to = self.subject, self.sender, self.recipients
plain_message = strip_tags(self.content)
# recipients to list
to = to.split(', ')
# Setting Sender
msg = EmailMultiAlternatives(subject=subject, body=plain_message, from_email=from_email, to=to)
msg.attach_alternative(self.content, "text/html")
msg.content_subtype = 'html'
msg.mixed_subtype = 'related'
try:
msg.send(fail_silently=False)
self.status = OutgoingMail.OUTGOING_MAIL_STATUS.SUCCESS
except:
self.status = OutgoingMail.OUTGOING_MAIL_STATUS.FAIL
super(OutgoingMail, self).save(*args, **kwargs)
class Meta:
managed = True
db_table = 'outgoing_mail'
verbose_name='이메일'
verbose_name_plural = '이메일'
save 메소드를 오버라이드 하여 메일 오브젝트를 저장함과 동시에 메일 전송을 하였습니다. 단체 메일의 경우 수신 메일 주소가 여러개일 수 있기에, 메일 주소를 콤마+공백으로 구분하여 입력하여 이를 split으로 잘라서 리스트로 만들었습니다.
content 는 CKEditor의 RichTextUploadingField를 사용하였습니다.
from django.contrib import admin
from mail.models import *
@admin.register(OutgoingMail)
class OutgoinMailAdmin(admin.ModelAdmin):
list_display = ['subject', 'status']
저와 비슷하게 메일 기능을 개발하시면서, 막히는 부분이 있으시다면 본 게시글의 댓글이나 caputdraconis@kakao.com으로 내용 보내주시면 도와드리겠습니다.