장고 프로젝트(맛집 공유 사이트 만들기) - 5 이메일 보내기 Django Project Restaurant share (구글 앱 비밀번호, 구글 인증키 설정 포함)
장고 프로젝트(맛집 공유 사이트 만들기) - CRUD(맛집정보) Django Project Restaurant share - 4
2023.07.31 - [IT & 개발공부/웹개발(HTML, CSS)] - 장고 프로젝트(맛집 공유 사이트 만들기) - CRUD(카테고리) Django Project Restaurant share - 3 장고 프로젝트(맛집 공유 사이트 만들기) - CRUD(카테고리) Django Proje
bmil2011s.tistory.com
지난 글에서 category 와 restaurant 의 CURD 두 가지를 구현해냈다. 이번에는 추가 기능인 이메일 보내기 기능도 구현해보려고 한다. 파이썬에서 제공하는 라이브러리와 구글 SMTP 메일 발송 서버를 이용할 예정이다.
1. 처리 경로 설정
- 먼저 사용자가 이메일 발송을 눌렀을 때 이를 처리하기 위한 경로로 가도록 index.html을 다음과 같이 수정하자.
- 프로젝트 폴더의 urls.py는 다음과 같이 기본 설정되어있는 것을 확인
- sendEmail app의 urls.py도 다음 코드와 같이 설정되어 있을 것이다. 이렇게 되면 app의 views.py의 sendEmail이 처리할 수 있게 경로가 설정된다.
2. 기능구현
- 실제 기능을 구현하기 전에 필요한 기능을 코드로 작성하기 전에 서술식으로 생각해보면 다음과 같을 것이다.
* User가 선택한 맛집 및 입력한 데이터 받아 오기
* User가 선택한 맛집과 인사말을 이용해서 이메일 본문 작성하기
* User가 입력한 수신자에게 입력한 제목과 추가된 본문 등을 이메일로 발송하기
2-1 User가 선택한 맛집 및 입력한 데이터 받아 오기
* 첫번째 기능 구현을 위해 views.py에 이 내용을 코딩하기 전 의문이 드는 것이 있을 것이다. User들이 몇개의 체크박스를 선택하고, 어떤 체크박스를 선택하는지는 매번 다른데 어떻게 해결해야하나? 이전에 잠깐 언급하면서 미리 수정했던 내용이 여기서 등장한다.
- 장고에서는 이름을 동일하게 했을 때 체크된 요소들만 그 value 값을 받아 올 수 있다. 그리고 index.html 227번 줄을 보면 다음과 같은데, input 태그의 name은 checks로 되어있고, value는 각 restaurant의 id로 되어있다. 이는 여러 개의 restaurant를 선택해도 각 체크 박스의 이름은 모두 checks로 동일하게 된다는 것을 의미한다.
<input name="checks" id="check{{restaurant.id}}" type="checkbox" value="{{restaurant.id}}">
- 이 내용을 이해하여 첫번째 기능 구현을 위해 sendEmail 함수 코드를 다음과 같이 작성하자.
* 7번 줄 코드를 이용하여 체크된 요소(인자를 동일하게 checks로 설정)를 모두 가져온다.
* 8~10번 줄 코드는 input의 name 태그를 통해 가져오는 것이다.
* 11번 줄 코드를 이용하여 데이터를 잘 가져오고 있는지 다음과 같이 확인도 할 수 있다.
2-2 User가 선택한 맛집과 인사말을 이용해서 이메일 본문 작성하기
- 앞에서 받아 온 restaurant의 id를 이용해 실제 restaurant 데이터를 꺼내, 맛집의 이름/링크/상세 내용/키워드를 메일 본문으로 작성되도록 하자. 이메일 본문 내용은 html 형태로 만들어야 하므로 다음과 같이 html 태그를 이용해 만들어 준다.
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from shareRes.models import *
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# Create your views here.
def sendEmail(request):
checked_res_list = request.POST.getlist('checks')
inputReceiver =request.POST['inputReceiver']
inputTitle = request.POST['inputTitle']
inputContent = request.POST['inputContent']
mail_html = "<html><body>"
mail_html += "<h1> 맛집 공유 </h1>"
mail_html += "<p>"+inputContent+"<br>"
mail_html += "발신자님께서 공유하신 맛집은 다음과 같습니다.</p>"
for checked_res_id in checked_res_list:
restaurant = Restaurant.objects.get(id = checked_res_id)
mail_html += "<h2>"+restaurant.restaurant_name+"</h3>"
mail_html += "<h4>* 관련 링크</h4>"+"<p>"+restaurant.restaurant_link+"</p><br>"
mail_html += "<h4>* 상세 내용</h4>"+"<p>"+restaurant.restaurant_content+"</p><br>"
mail_html += "<h4>* 관련 키워드</h4>"+"<p>"+restaurant.restaurant_keyword+"</p><br>"
mail_html += "<br>"
mail_html +="</body></html>"
return HttpResponseRedirect(reverse('index'))
* 먼저 4번 줄과 같이 실제 데이터에 접근하기 위해 shareRes app의 models를 import
* 13번 줄부터 이메일 본문을 구성한다. 15번 줄에서 User가 입력한 인사말을 입력하고, 17번 줄부터 각 요소들을 하나씩 꺼내 실제 restaurant 데이터를 찾아 이메일 본문에 추가시킨다.
2-3 User가 입력한 수신자에게 입력한 제목과 추가된 본문 등을 이메일로 발송하기
- 마지막으로 이와 같이 구성된 이메일 본문에 대해서 사용자가 입력한 수신자와 이메일 제목으로 발송 기능을 구현해보자. 이를 위해서 이전에 views.py에 여러 라이브러리들을 import 해주었다.
- 5번 줄부터 차례로 smtplib 라이브러리를, 메일 본문을 html 형태로 나타내기 위해 email.mime.text로 부터 MIMEText를, html 형태의 메시지를 포함하는 메시지 객체를 위해 email.mime.multipart 에서 MIMEMultipart를 import해 주었다.
- 이 방법은 python email send by html 등의 구글링 검색 결과를 통해 알게 되었고, 앞으로도 모르는 기능을 구현하고자 할 때 구글링을 하여 참고하는 것이 좋겠다.
- 한편 앞서 말한 것처럼 python으로 메일을 보낼 것이고 이메일 서버는 google SMTP 사용하려고 할 때는 구글 인증키 발급이 필요하다.
구글 인증키 설정 방법
- 먼저 크롬기준 우측 상단의 프로필을 클릭한 뒤, Google 계정 관리를 클릭
- 화면 왼쪽에서 보안을 클릭
- Google에 로그인하는 방법 탭에서 2단계 인증을 클릭
- 들어간 화면에서 하단으로 내리다보면 앱 비밀번호가 나오는데, 앱 비밀번호 클릭(중간에 재로그인 할 수도 있음)
- 이후 들어간 화면에서 앱 선택에 "기타(맞춤 이름)"을 선택
-원하는 이름을 정한 뒤 생성을 클릭
-16자리 비밀번호를 ※복사하거나 캡쳐하여 기억한다※. (잊어버리면 다시 설정해야 함을 기억한다.)
그러면 다시 VScode로 돌아오자.
- 구글링해서 찾은 결과를 요약하고 종합해서 sendEmail 함수를 다음과 같이 재구성하자.
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from shareRes.models import *
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# Create your views here.
def sendEmail(request):
checked_res_list = request.POST.getlist('checks')
inputReceiver =request.POST['inputReceiver']
inputTitle = request.POST['inputTitle']
inputContent = request.POST['inputContent']
mail_html = "<html><body>"
mail_html += "<h1> 맛집 공유 </h1>"
mail_html += "<p>"+inputContent+"<br>"
mail_html += "발신자님께서 공유하신 맛집은 다음과 같습니다.</p>"
for checked_res_id in checked_res_list:
restaurant = Restaurant.objects.get(id = checked_res_id)
mail_html += "<h2>"+restaurant.restaurant_name+"</h3>"
mail_html += "<h4>* 관련 링크</h4>"+"<p>"+restaurant.restaurant_link+"</p><br>"
mail_html += "<h4>* 상세 내용</h4>"+"<p>"+restaurant.restaurant_content+"</p><br>"
mail_html += "<h4>* 관련 키워드</h4>"+"<p>"+restaurant.restaurant_keyword+"</p><br>"
mail_html += "<br>"
mail_html +="</body></html>"
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login("youremail@gmail.com", "yourpassword")
msg = MIMEMultipart('alternative')
msg['Subject'] = inputTitle
msg['From'] = "youremail@gmail.com"
msg['To'] = inputReceiver
mail_html = MIMEText(mail_html, 'html')
msg.attach(mail_html)
print(msg['To'],type(msg['To']))
server.sendmail(msg['From'],msg['To'].split(','),msg.as_string())
server.quit()
return HttpResponseRedirect(reverse('index'))
* youremail은 본인의 이메일, yourpassword는 아까 받은 16자리 글자를 입력해주면 되겠다.
- 이후 수신자를 본인이 확인 가능한 메일(에러없이 보내졌다고 해도 진짜 왔는지 확인이 필요하므로)로 보내면 잠시 뒤에 작성했던 글들이 사라지고, 다음과 같이 메일이 잘 보내지는 것을 확인할 수 있다.
- 메일까지 확인이 된다면 이메일 전송 기능까지 구현이 된 것이다. 이렇게 장고를 통해 맛집공유하기 웹페이지 프로젝트가 완료되었다.
* 이 글은 Django 한그릇 뚝딱(문범우, 2019)의 챕터 3 "맛집 공유 사이트 만들기" 내용을 참고하였음(틀린 부분 약간 수정됨).