📌 개념 정리
문의 내역 이메일 발송 시스템은 사용자가 웹 폼을 통해 문의한 내용을 이메일로 보내는 시스템입니다. 이 시스템은 사용자가 웹 폼에 입력한 정보를 서버에서 처리하고, 이메일 서버를 통해 관리자가 이를 받을 수 있도록 구현됩니다. Flask-Mail 라이브러리를 사용하여 이메일을 쉽게 보내며, Flask에서 제공하는 웹 폼을 통해 사용자로부터 정보를 입력받습니다.
이 시스템은 간단한 이메일 보내기 기능뿐만 아니라, 사용자 입력값의 유효성 검증도 포함하고 있어 실제 서비스에서도 유용하게 활용될 수 있습니다.
🚦 동작 원리 및 구조
- 웹 폼에서 사용자 입력: 사용자는 /contact 경로에서 이름, 이메일 주소, 문의 내용을 입력합니다.
- 유효성 검증: 사용자가 입력한 값에 대해 유효성 검사를 진행합니다. 예를 들어, 이메일 형식이 유효한지, 모든 필드가 채워졌는지 확인합니다.
- 이메일 전송: 사용자의 입력값이 유효하면, Flask-Mail을 이용해 이메일을 발송합니다. 이때, contact_mail.html과 contact_mail.txt 템플릿을 사용하여 이메일 내용을 구성합니다.
- 성공적인 처리: 이메일 발송이 완료되면, 사용자는 완료 페이지로 리디렉션되어 "메일 전송 완료" 메시지를 확인합니다.
💻 코드 예시 및 흐름 분석
1. app.py
Flask 애플리케이션과 이메일 전송 기능을 설정합니다.
from flask import Flask, render_template, url_for, redirect, request, flash
from email_validator import validate_email, EmailNotValidError
import logging
import os
from flask_mail import Mail, Message
app = Flask(__name__)
app.config["SECRET_KEY"] = "secret"
app.logger.setLevel(logging.DEBUG)
app.logger.debug("debug")
# 이메일 서버 설정
app.config["MAIL_SERVER"] = os.environ.get("MAIL_SERVER")
app.config["MAIL_PORT"] = os.environ.get("MAIL_PORT")
app.config["MAIL_USE_TLS"] = os.environ.get("MAIL_USE_TLS")
app.config["MAIL_USERNAME"] = os.environ.get("MAIL_USERNAME")
app.config["MAIL_PASSWORD"] = os.environ.get("MAIL_PASSWORD")
app.config["MAIL_DEFAULT_SENDER"] = os.environ.get("MAIL_DEFAULT_SENDER")
mail = Mail(app)
@app.route("/")
def index():
return "메일 보내기 미니 프로젝트"
@app.route("/contact")
def contact():
return render_template("contact.html")
@app.route("/contact/complete", methods=["GET", "POST"])
def contact_complete():
if request.method == "POST":
name = request.form["name"]
email = request.form["email"]
message = request.form["message"]
# 유효성 검증
valid = True
if not name:
flash("이름을 입력해줘.")
valid = False
if not email:
flash("이메일을 입력해줘.")
valid = False
try:
validate_email(email)
except EmailNotValidError:
flash("이메일의 유효성을 확인해줘.")
valid = False
if not message:
flash("문의 내용을 입력해줘.")
valid = False
if not valid:
return redirect(url_for("contact"))
flash("문의해주셔서 감사합니다")
# 이메일 전송
send_email(email, "문의 내용", "contact_mail", user_name=name, description=message)
return redirect(url_for("contact_complete"))
return render_template("contact_complete.html")
# 이메일 전송 함수
def send_email(to, subject, template, **kwargs):
msg = Message(subject, recipients=[to])
msg.body = render_template(template + ".txt", **kwargs)
msg.html = render_template(template + ".html", **kwargs)
mail.charset = 'utf-8'
mail.send(msg)
if __name__ == '__main__':
app.run(debug=True)
2. contact.html
사용자로부터 이름, 이메일, 메시지를 입력받는 폼입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>메일 문의 폼</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="contact-form-container">
<form action="{{ url_for('contact_complete') }}" method="POST" novalidate="novalidate">
<h2>문의하기</h2>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li class="flash">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<label for="name">이름</label>
<input type="text" id="name" name="name" placeholder="이름을 입력하세요">
<label for="email">메일 주소</label>
<input type="email" id="email" name="email" placeholder="이메일을 입력하세요">
<label for="message">문의 내용</label>
<textarea id="message" name="message" rows="5" placeholder="문의 내용을 입력하세요"></textarea>
<button type="submit">메일 보내기</button>
</form>
</div>
</body>
</html>
3. .env 파일구성
FLASK_APP=app.py
FLASK_ENV=development
MAIL_SERVER=smtp.gmail.com
#프로토콜 -> 통신 규악 -> 이메일을 보낼때 사용하는 규칙 = smpt / gmail.com의 서비스를 이용해서 메일을 보내겠다.
MAIL_PORT=587
MAIL_USE_TLS=True
#보안설정 활용
MAIL_USERNAME = gmail@gmail.com # 구글을 사용하기위한 이메일
MAIL_PASSWORD = mnasdfasdfasrg # 생성한 앱 비밀번호 공백없이 설정
MAIL_DEFAULT_SENDER = gmail@gmail.com # 보내는 사람의 이메일 EX)gmail@nate.com
4. contact_complete.html
사용자가 이메일을 성공적으로 보냈을 때 표시되는 완료 페이지입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>메일 전송 완료</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="complete-container">
<h2>메일 전송 완료</h2>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li class="flash">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</div>
</body>
</html>
5. contact_mail.html
이메일 내용의 HTML 형식입니다. 사용자가 보내는 문의 내용을 포함합니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>문의 내용 확인</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
background-color: #f4f4f9;
}
.email-container {
max-width: 600px;
margin: 20px auto;
background: #ffffff;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.email-header {
background: #0078d7;
color: #ffffff;
text-align: center;
padding: 20px;
font-size: 20px;
font-weight: bold;
}
.email-body {
padding: 20px;
color: #333333;
}
.email-footer {
background: #f4f4f9;
text-align: center;
padding: 10px;
font-size: 12px;
color: #888888;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-body">
<p><strong>{{ user_name }}님</strong></p>
<p>문의주셔서 감사합니다.</p>
<p>보내주신 문의 내용은 다음과 같습니다.</p>
<div style="background: #f9f9f9; border-left: 4px solid #0078d7; padding: 10px; margin: 15px 0;">
<p><strong>문의 내용</strong></p>
<p>{{ description }}</p>
</div>
<p>추가적인 문의 사항이 있으시면 언제든지 말씀해 주세요!</p>
</div>
</div>
</body>
</html>
🧪 왜 contact_mail.txt 템플릿이 필요한가?
- 호환성: 모든 이메일 클라이언트가 HTML을 지원하지 않기 때문에, 텍스트 형식의 이메일을 보내는 것이 중요합니다.
- 단순한 텍스트 이메일: 텍스트 형식의 이메일은 디자인 요소 없이 내용을 간단하게 전달하는 데 유용합니다. 이는 일부 사용자가 텍스트 이메일을 선호하는 경우에 적합합니다.
- 대체 형식 제공: Flask-Mail에서 이메일을 보낼 때, HTML 형식과 텍스트 형식 모두 제공하는 것이 일반적입니다. 이를 통해 사용자가 HTML을 지원하지 않는 환경에서도 제대로 내용을 확인할 수 있습니다.
{{ user_name }}님
문의해주셔서 감사합니다.
문의 주신 내용은 다음과 같습니다.
[문의내용]
{{ description }}
🧪 실전 사례
이 예제는 사용자가 contact.html 폼을 통해 문의한 내용을 이메일로 보내는 시스템입니다. 폼 제출 후, 서버에서 입력값의 유효성 검사를 수행하고, 검증된 데이터는 Flask-Mail을 통해 관리자의 이메일로 전송됩니다. 이메일은 HTML 및 텍스트 형식으로 발송되며, 사용자는 이메일을 통해 자신의 문의 내용을 확인할 수 있습니다.
🧠 고급 팁 or 자주 하는 실수
- 보안 및 유효성 검사: 실제 환경에서는 이메일 유효성 검사를 강화하고, 서버 측에서 추가적인 보안을 구현해야 합니다. 예를 들어, 이메일 발송 시 서버에서 발송자의 이메일을 검증하는 절차를 추가할 수 있습니다.
- 비밀번호 및 개인 정보 보호: 이메일 내용에 민감한 개인 정보가 포함될 수 있으므로, 이를 암호화하거나 보안 전송 채널(SSL)을 사용하는 것이 중요합니다.
✅ 마무리 요약 및 복습 포인트
- Flask-Mail을 활용한 이메일 발송 시스템 구현 방법을 학습했습니다.
- Flask 웹 애플리케이션에서 사용자의 문의 내용을 이메일로 전송하는 방법을 배웠습니다.
- 이메일 발송 시 텍스트와 HTML 템플릿을 활용하여 포맷을 꾸미고 사용자에게 정보를 제공합니다.
이 시스템을 통해 간단한 이메일 보내기 기능을 구현하고, 실제 서비스에 맞게 확장할 수 있습니다
📌 구글 2단계 인증 관련 설명
구글 2단계 인증은 계정의 보안을 강화하는 방법 중 하나입니다. 이를 설정하면 비밀번호 외에도 추가적인 인증 절차를 거쳐 계정에 로그인할 수 있습니다. 이 과정에서 앱 비밀번호를 생성하여 외부 애플리케이션에서 구글 계정에 접근할 수 있도록 허용합니다.
🚦 구글 2단계 인증 활성화 방법
- 구글 계정 페이지로 이동:
- 구글 계정 페이지에 접속하여, 2단계 인증을 설정할 수 있습니다.
- 앱 비밀번호 설정:
- 앱 비밀번호 페이지로 이동하여 특정 앱에 대해 별도의 비밀번호를 생성합니다. 예를 들어, 이메일 클라이언트나 다른 앱에서 구글 계정에 로그인하려면 이 앱 비밀번호를 사용해야 합니다.
- 앱 비밀번호 설정 페이지: 앱 비밀번호 페이지
- 앱 비밀번호 사용:
- 생성된 앱 비밀번호는 구글 계정에 연결된 애플리케이션에서 사용됩니다. 이 비밀번호는 일반적으로 로그인 비밀번호와 다르며, 외부 애플리케이션에서 구글 계정에 접근할 때 사용됩니다.
💻 코드 분석: 구글 2단계 인증과 이메일 발송
구글 2단계 인증을 사용하는 경우, 외부 앱에서 이메일을 발송하려면 앱 비밀번호를 사용해야 합니다. 위에서 설명한 코드 예시에서 이메일을 보내는 기능은 Flask-Mail을 이용하여 처리되며, MAIL_USERNAME과 MAIL_PASSWORD는 구글 계정의 앱 비밀번호를 사용하여 설정해야 합니다.
- MAIL_USERNAME: 구글 계정의 이메일 주소
- MAIL_PASSWORD: 구글 계정에서 생성한 앱 비밀번호
이 앱 비밀번호를 사용하여 Flask-Mail에서 이메일을 안전하게 발송할 수 있습니다.
✅ 정리
- contact_mail.txt: 텍스트 형식 이메일을 보내는 템플릿으로, 이메일 클라이언트와의 호환성을 높이고, HTML을 지원하지 않는 환경에서도 이메일 내용을 확인할 수 있게 합니다.
- 구글 2단계 인증: 구글 계정의 보안을 강화하기 위한 추가 인증 절차입니다. 앱 비밀번호를 통해 외부 애플리케이션에서 구글 계정에 안전하게 접근할 수 있습니다.
'기술블로그' 카테고리의 다른 글
🚀 Git Flow 브랜치 전략 초기 셋팅 가이드(1-1) (0) | 2025.04.24 |
---|---|
Flask-Login 을 활용한 간단한 로그인 프로젝트 (0) | 2025.04.23 |
📌 SMTP,프로토콜,통신 규약 이란? (0) | 2025.04.23 |
Flask : 서비스 기획부터 API 개발까지: 시스템 설계의 전체 흐름(with 프론트엔드 소통) (0) | 2025.04.23 |
Flask 템플릿 렌더링 with 파머(1/3) (0) | 2025.04.23 |