상용 이메일 클라이언트는 사용자 친화적인 GUI의 편리함을 제공하지만, 많은 개발자나 콘텐츠 제작자가 이메일 업무에서 원하는 유연성과 커스터마이징 기능은 부족한 경우가 많습니다.
소셜 미디어 채널의 새 구독자에게 감사 이메일을 보내거나, 진행 중인 프로젝트에 이메일 기능을 추가하는 등 파이썬에서 SMTP를 활용해 자동화된 메시지를 보낼 수 있는 능력은 언젠가 반드시 유용하게 쓰이게 됩니다.
오늘 바로 여러분의 컴퓨터에서 파이썬 스크립트로 이메일을 전송할 수 있도록, 그 방법을 하나씩 살펴보겠습니다.
SMTP란 무엇인가?
간단히 말해 SMTP(Simple Mail Transfer Protocol, 단순 메일 전송 프로토콜)는 메일 서버가 인터넷을 통해 이메일을 주고받을 수 있도록 하는 통신 프로토콜입니다.
SMTP는 인터넷 또는 유사한 네트워크에서 통신에 사용되는 프로토콜 집합인 TCP/IP 스위트의 애플리케이션 계층에서 필수적인 역할을 담당합니다. SMTP가 구현된 네트워크에서는 저장 후 전달(store and forward)이라는 방식이 메일을 네트워크 간에 이동시키는 데 사용됩니다.
각 엔드포인트에는 MTA(Mail Transfer Agent)라는 소프트웨어가 있으며, 이 저장 후 전달 방식을 통해 참여 중인 SMTP 서버들 간의 통신이 중개됩니다. 따라서 SMTP의 핵심 역할은 네트워크 안에서 메일이 한 지점에서 다른 지점으로 어디로, 어떻게 이동할지를 규정하는 것입니다.
시작하기
이 프로그램으로 이메일을 보내려면 발송에 사용할 이메일 계정이 필요합니다. 이 튜토리얼에서는 Gmail의 SMTP 서비스를 사용하겠습니다.
로컬 SMTP 디버깅 서버를 통해 테스트 이메일을 보낼 수도 있지만, 여기서는 더 직관적인 실제 이메일 계정을 사용하겠습니다.
기존 Gmail 계정을 그대로 사용할 수도 있지만, 프로그램을 테스트하다 보면 곧 테스트 이메일로 가득 차게 됩니다. 그래서 테스트 전용 일회성('throwaway') 계정을 새로 만드는 것을 권장합니다.
또한 외부 앱의 Gmail 접근을 허용하는 설정을 켜야 하는데, 주 이메일 계정의 보안 설정을 함부로 변경하는 것은 좋지 않으므로 이 역시 일회성 계정을 사용하는 것이 좋은 이유입니다.
참고: 2022년부터 구글은 '덜 안전한 앱 허용' 옵션을 폐지하고 앱 비밀번호(App Password) 방식으로 전환했습니다. 현재는 2단계 인증을 활성화한 뒤 생성한 앱 비밀번호를 사용하는 것이 권장되는 방법입니다.
파이썬으로 이메일 작성하기
파이썬 3에는 smtplib(smtp library의 약자)라는 모듈이 기본으로 포함되어 있어, 별도 설치 없이 SMTP 서버와 연동할 수 있습니다.
다른 파이썬 모듈과 마찬가지로 가장 먼저 할 일은 smtplib를 임포트하는 것입니다.
import smtplibSMTP 객체 초기화
이제 smtplib를 사용해 SMTP 객체를 생성할 수 있습니다. 이 객체는 일반 이메일 클라이언트가 제공하는 대부분의 기능을 담당합니다. 다만 SMTP 객체의 기능은 인스턴스 메서드를 통해서만 사용할 수 있으므로, 당연히 다음 단계는 객체 인스턴스를 선언하는 것입니다.
mySMTP = smtplib.SMTP("smtp.gmail.com")이렇게 하면 SMTP 객체가 구글의 SMTP 서버를 통해 이메일을 발송하도록 설정됩니다.
그다음 발신자와 수신자 이메일을 지정합니다. 앞서 만든 Gmail 계정이 여기서 유용하게 쓰입니다.
emailSender = "senderMail@sender.com"
myThrowaway = "my_email@gmail.com"
emailRecipients = [myThrowaway]여기서 한 가지 주목할 점은 수신자 목록이 배열(array)이라는 것입니다. 즉, 여러 값을 저장할 수 있도록 설계되어 있어 이 필드에 메일링 리스트 전체를 지정할 수도 있습니다!
메시지 작성하기
과정 중 가장 직관적인 부분으로, 새 이메일을 작성할 때 평소 입력하는 값들을 여기에 넣으면 됩니다. 포함되는 항목은 다음과 같습니다.
- 발신자 정보
- 수신자 정보
- 제목
- 메시지 본문
이 필드들은 삼중 따옴표(triple quotation marks) 안에 함께 넣고 아래와 같이 구분합니다.
newEmail = """From: From Person <senderMail@sender.com>
To: To Person <my_email@gmail.com>
Subject: Email Test
This is the body of the email.
"""이메일 보내기
마지막으로 sendmail 명령을 사용해 SMTP 서버에서 수신자의 서버로 메일을 전송합니다.
mySMTP.sendmail(emailSender, emailRecipients, newEmail)이제 마지막 한 단계만 남았습니다. 예상 가능한 프로그램 충돌을 방지하기 위해 코드를 재구성하는 것입니다.
파이썬 이메일 프로그램 문제 해결하기
때때로 SMTP 서버가 수신자의 서버와 연결을 맺지 못하거나, SMTP 포트 간 이메일 전송 과정에서 문제가 생길 수 있습니다. 이런 경우 프로그램이 예기치 않게 충돌할 수 있습니다.
이러한 가능성에 대비하려면 try-except 블록을 사용하고 오류가 발생하기 쉬운 문장들을 try 블록 안에 넣으면 됩니다. try-except 블록을 포함한 전체 프로그램은 다음과 같습니다.
import smtplib
emailSender = "senderMail@sender.com"
myThrowaway = "my_email@gmail.com"
emailRecipients = [myThrowaway]
newEmail = """From: From Person <senderMail@sender.com>
To: To Person <my_email@gmail.com>
Subject: Email Test
This is the body of the email.
"""
try:
smtpObj = smtplib.SMTP("smtp.gmail.com")
mySMTP.sendmail(emailSender, emailRecipients, newEmail)
print("Email sent successfully!")
except SMTPException:
print("Error: There was an error in sending your email.")이메일 보안 강화하기
실제 환경에서 파이썬으로 이메일을 보낼 계획이라면, 양쪽 모두에서 통신이 안전하게 이루어지는지 확인하는 것이 중요합니다.
기본 포트를 사용하는 단순 SMTP 서버는 통신에 어떠한 암호화 계층도 제공하지 않습니다. 즉, 네트워크를 도청하는 제3자가 로그인 자격 증명과 이메일에 담긴 정보에 접근할 수 있습니다.
이 문제를 피하는 한 가지 방법은 TLS(Transport Layer Security) 프로토콜로 통신을 암호화하는 것입니다. Gmail과 Outlook 같은 주요 이메일 클라이언트가 이메일이 잘못된 손에 들어가지 않도록 사용하는 것이 바로 이 프로토콜입니다.
이를 위해 앞서 만든 프로그램에 몇 가지 변경을 해야 합니다.
첫 번째 단계는 당연히 smtplib와 함께 ssl 라이브러리를 임포트하는 것입니다. ssl 라이브러리를 사용하면 보안 SSL 컨텍스트를 생성하고, 양쪽 끝의 특정 포트에 연결해 암호화된 네트워크를 통해 통신할 수 있습니다.
보안 SSL 컨텍스트란 암호화 알고리즘(cipher), 프로토콜 버전, 신뢰할 수 있는 인증서, TLS 옵션 및 TLS 확장 등의 모음입니다.
이후 TLS 포트를 지정하고 몇 가지 ssl 라이브러리 함수를 추가해 보안이 강화된 이메일 발송기를 만들 수 있습니다. 모든 변경 사항이 적용된 코드는 다음과 같습니다.
import smtplib, ssl
smtpServer = "smtp.gmail.com"
port = 587
myEmail = "my_email@gmail.com"
password = "my_password"
# 이메일과 비밀번호는 사용자 입력 필드로 받을 수도 있습니다.
context = ssl.create_default_context()
newEmail = """From: From Person <senderMail@sender.com>
To: To Person <my_email@gmail.com>
Subject: Email Test
This is the body of the email.
"""
try:
server = smtplib.SMTP(smtpServer, port)
server.starttls(context=context)
server.login(myEmail, password)
except Exception as e:
print("The email could not be sent.")
finally:
server.quit()여느 때처럼 SMTP 인스턴스는 try-except 블록 안에서 생성하고 사용해야 갑작스러운 프로그램 충돌을 예방할 수 있습니다.
이 파이썬 스크립트로 할 수 있는 것들
이제 코드로 이메일을 자동화하는 멋지고 의외로 실용적인 기술을 익혔으니, 다양한 메일링 리스트에 이메일을 보내야 하는 어떤 플랫폼에든 적용할 수 있습니다.
개인 웹사이트에서 자동 확인 이메일을 보내는 용도부터, 가족과 친구에게 크리스마스 카드나 초대장을 보내는 용도까지, 이 작은 파이썬 스크립트의 활용 범위는 여러분의 상상력에 의해서만 제한됩니다.
또한 이것은 파이썬으로 할 수 있는 수많은 멋진 일 중 하나일 뿐입니다. 폭넓은 개발자 지원과 배우기 쉬운 문법 덕분에 지금처럼 파이썬 스킬을 익히기 좋은 시기는 없습니다.
코드로 계속 멋진 것을 만들고 싶다면, 파이썬 3로 나만의 텔레그램 봇을 만드는 가이드도 확인해 보세요!