유데미에서 Python 부트캠프 : 100개의 프로젝트로 Python 개발 완전 정복 강의를 지원받아 작성한 포스팅입니다.
포스팅 내용은 Day 32일 차에 대한 프로젝트 내용을 담고 있습니다.
강의에 대한 전반적인 느낌
파이썬을 공부하다 보면, 파이썬 기초부터 객체지향 등 공부해야 하는 것들이 무수히 많다는 것을 느낍니다. 이 강의의 가장 좋은 점은 맨 첫 강의에서 오늘 만들어낼 결과물에 대한 소개하고, 해당 기능을 구현하기 위한 최소 단위의 내용을 배웁니다. 강의 중간에는 강사님께서 혼자 고민해 보고 작성해 볼 수 있도록 제안하는 부분이 많이 도움이 되는 것 같습니다. 단순히, 강의만 듣고 끝나는 것이 아니라 직접 고민해 보고 작성해 보고 정답과 비교해 보는 것을 통해 피드백받을 수 있었습니다. 오늘 포스팅에서는 친구의 생일에 자동으로 축하 이메일을 보내는 방법을 배웁니다.
이메일 전송 원리
이메일을 보내는 방법은 누구나 다 알고 있을 것이라고 생각됩니다. 실제 내부적으로는 위와 같은 방식으로 메일이 각 서버를 통과하여 개인에게 전송되는 시스템으로 운영되고 있습니다. 이 과정에서 필요한 부분이 바로 SMTP라는 것입니다. 현실에서는 우체부와 같은 역할을 한다고 보시면 될 것 같습니다. SMTP는 Simple Mail Transfer Protocol로 전자메일을 전송할 때 사용되는 표준 프로토콜입니다. 파이썬에서는 이메일 전송을 위한 smtplib이라는 라이브러리를 제공하고 있습니다.
이메일 파이썬으로 보내기
실제로 잘 동작하는지 확인하기 위해서 새로운 gmail 아이디를 만들어봅시다. 영상을 따라 만들다 보면, 보안 수준을 낮추는 부분이 없는 것을 확인하시게 됩니다. 2022년 5월 30일 이후부터는 해당 문제를 해결하기 위해 2단계 인증과 앱 비밀번호 설정한 뒤에 진행해야 합니다.
보안 탭에서 2단계 인증 절차를 모두 설정하셨으면 검색 창에 "앱 비밀번호" 검색하면 아래와 같이 나옵니다.
첫 번째 리스트인 앱 비밀번호를 클릭하시면 아래와 같은 화면을 볼 수 있는데, 앱 이름을 만들면 자동으로 16자리 비밀번호가 생성됩니다.
위에 나오는 16자리 비밀번호는 잠시 뒤 파이썬 코드에서 활용하게 됩니다. 따로 적어두시고, 다른 분들에게 공유되지 않도록 조심하세요.
# 라이브러리 불러오기
import smtplib
# 개인 정보 입력(email, 앱 비밀번호)
my_email = "myemail@gmail.com"
password = "abcd efgh ijkl mnop"
# 방법 1(with 사용 X)
connection = smtplib.SMTP("smtp.gmail.com") #보내는 메일의 SMTP 주소입력
connection.starttls() # Transport Layer Security : 메시지 암호화 기능
connection.login(user=my_email, password=password)
connection.sendmail(
from_addr=my_email,
to_addr="youremail@naver.com",
msg="Subject:Hello\n\nThis is the body of my email."
) #Subject:제목\n\n내용 구조로 메시지 입력.
connection.close()
# 방법 2(with 사용)
with smtplib.SMTP("smtp.gmail.com") as connection:
connection.starttls() #Transport Layer Security : 메시지 암호화
connection.login(user=my_email, password=password)
connection.sendmail(
from_addr=my_email,
to_addrs="youremail@naver.com",
msg="Subject:Hello\n\nThis is the body of my email."
)
중간에 starttls는 Transport Layer Security로 중간 과정에서 메일을 가로챘을 경우 해당 메시지가 암호화된 메시지로 나올 수 있도록 하는 함수로 보시면 됩니다. 만약, 위의 코드에서 보내는 메일 주소를 Gmail 말고 다른 메일 주소를 사용한다면, 구글에 Naver smtp address 등의 검색어를 활용하여 검색 후 입력해 주면 됩니다. Gmail 말고 다른 서버에서 메일 보내는 테스트는 따로 진행하지 않았습니다. 위와 같이 작성한 코드를 실행하면, 아래처럼 메일 1개가 이상 없이 전송되는 것을 확인할 수 있습니다.
종종 메시지가 스팸메일함 등으로 들어갈 수 있으니, 한번 확인해 보시면 좋을 것 같습니다. 이것으로 축하메시지 보내기 위한 smtplib 사용법은 완료되었습니다.
월요일마다 명언 1개 보내주기
매주 월요일은 월요병이라는 이야기가 있을 정도로 많이들 지치고 힘든 날입니다. 이런 날 명언을 통해 조금이나마 동기부여를 해주면 살짝 힘이 나지 않을까 싶습니다. 이번에는 datetime 모듈의 weekday 함수를 활용해서 월요일인지 확인한 뒤 명언을 임의로 뽑아서 메일로 보내주는 방식으로 구현합니다. quotes.txt에는 총 101개의 영어 명언으로 구성되어 있습니다. 참고로 이메일 내용에 한글을 담기 위해서는 별도의 모듈을 활용해야 합니다.(email 모듈의 MIMEText 해당 내용은 이 블로그 참고하시면 좋을 것 같습니다)
import smtplib
import datetime as dt
import random
# 개인 정보 입력(email, 앱 비밀번호)
my_email = "myemail@gmail.com"
password = "abcd efgh ijkl mnop"
# 날짜 확인
now = dt.datetime.now()
day_of_week = now.weekday() # Mon : 0, Tue : 1, Wed : 2, Thu : 3, Fri : 4, Sat : 5, Sun : 6
# 월요일인지 확인
if day_of_week == 0:
with open("quotes.txt") as file:
all_quotes = file.readlines()
quote = random.choice(all_quotes)
with smtplib.SMTP("smtp.gmail.com") as connection:
connection.starttls() #Transport Layer Security : 메시지 암호화
connection.login(user=my_email, password=password)
connection.sendmail(
from_addr=my_email,
to_addrs=my_email,
msg=f"Subject:Monday Motivation\n\n{quote}"
)
금일 테스트를 위해서 day_of_week를 6으로 설정한 뒤 실행했고, 결과는 위처럼 이상 없이 나왔습니다. 그러면 마지막으로 오늘 배운 내용들을 종합해서 최종 목표 프로그램을 만들어봅시다.
매일 아침마다 친구한테 자동 축하 메일 보내기
축하 메일 전송프로세스는 아래와 같습니다.
- 오늘 날짜의 월일에 대한 정보 추출(datetime.now 활용)
- 저장된 친구 정보 가져오기(pandas read_csv 활용, 정보에는 이름, 메일주소, 생년월일이 포함)
- 오늘 날짜와 생일이 동일한 친구목록 확인
- 메시지 보낼 템플릿 임의 선정(random 활용)
- 선정된 템플릿에 이름 변경(replace 활용)
- 축하메시지 전송(smtplib 활용)
아래는 위의 프로세스를 구현한 내용입니다.
from datetime import datetime
import pandas as pd
import random
import smtplib
MY_EMAIL = "YOUR EMAIL"
MY_PASSWORD = "YOUR PASSWORD"
today = datetime.now()
today_tuple = (today.month, today.day)
data = pd.read_csv("birthdays.csv")
birthdays_dict = {(data_row["month"], data_row["day"]): data_row for (index, data_row) in data.iterrows()}
if today_tuple in birthdays_dict:
birthday_person = birthdays_dict[today_tuple]
file_path = f"letter_templates/letter_{random.randint(1,3)}.txt"
with open(file_path) as letter_file:
contents = letter_file.read()
contents = contents.replace("[NAME]", birthday_person["name"])
with smtplib.SMTP("YOUR EMAIL PROVIDER SMTP SERVER ADDRESS") as connection:
connection.starttls()
connection.login(MY_EMAIL, MY_PASSWORD)
connection.sendmail(
from_addr=MY_EMAIL,
to_addrs=birthday_person["email"],
msg=f"Subject:Happy Birthday!\n\n{contents}"
)
만약, 생일리스트에 생일이 같은 사람이 존재한다면, 위 코드는 이상 없이 돌아갈까요? 메일은 어떻게 올까요? sooho와 gildong은 건너뛰고 sewon에게만 메시지가 가게 됩니다.
df에서 오늘날짜로 필터링을 진행한 뒤, 반복문을 통해서 수정한 코드는 아래와 같습니다.
from datetime import datetime
import pandas as pd
import random
import smtplib
my_email = "myemail@gmail.com"
password = "abcd efgh ijkl mnop"
today = datetime.now()
today_tuple = (today.month, today.day)
df = pd.read_csv("birthdays.csv")
df = df.loc[(df['month'] == today_tuple[0])&(df['day'] == today_tuple[1])]
if len(df) == 0:
exit()
else:
for index, person_info in df.iterrows():
person_name = person_info['name']
person_email = person_info['email']
file_path = f"letter_templates/letter_{random.randint(1,3)}.txt"
with open(file_path) as letter_file:
contents = letter_file.read()
contents = contents.replace("[NAME]", person_name)
with smtplib.SMTP("smtp.gmail.com") as connection:
connection.starttls()
connection.login(my_email, password)
connection.sendmail(
from_addr=my_email,
to_addrs=person_email,
msg=f"Subject:Happy Birthday!\n\n{contents}"
)
그 결과 이상없이 3개 메일이 전송되었습니다. 이것으로 Day 32에 대한 내용 정리를 마치겠습니다. 추가적으로 발전시키실 부분이 있다면, 자유롭게 적용해 보시면 좋을 것 같습니다.
3줄 요약
- 손쉽게 결과물을 만들 수 있다는 점에서 유데미 강의의 장점이 돋보이는 것 같습니다.
- 파이썬으로 이메일 전송하기 위해서 smtp 프로토콜이 필요하며, smtplib을 사용할 수 있습니다.
- 이메일 자동화를 통해, 개인 업무 및 다양한 프로젝트에서 활용할 수 있을 것 같습니다.