[Python] 메일(smtplib)을 보내는 방법


Development note/Python  2020. 1. 31. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 메일(smtplib)을 보내는 방법에 대한 글입니다.


우리가 프로그램을 작성하면 메일 발송에 관한 프로그램 작성도 꽤 많을 꺼라고 생각됩니다. 웹 서비스 중에서는 회원 가입 인증 여부나 패스워드 재 설정, 찾기 등의 기능이 있고, 여러가지 기능 옵션의 알람 기능으로도 많이 사용됩니다.

웹 서비스 뿐아니라 로컬 프로그램으로는 대량 광고 메일(spam)도 있겠고, 주기적인 알람 기능등도 있을 수 있습니다.


그래서 어떤 프로그램 언어라도 이 메일 전송 라이브러리는 꼭 있는 것 같습니다.

링크 - [PHP] PHPMailer 라이브러리를 이용해서 메일 발송하는 방법

링크 - [C#] System.Net.Mail을 이용하여 메일 보내기

링크 - [Java] Mail 발송


먼저 메일 라이브러리로 메일을 보내기 전에 메일 프로토콜에 대해 알아야 합니다.

메일 프로토콜은 SMTP(Simple Mail Transfer Protocol)를 많이 사용하는데 이게 텔넷 방식으로 되어있고 HELO, MAIL, RCPT, DATA의 명령어로 통신을 합니다. 제가 설명하는 것보다 위키에 매우 잘 설명되어 있으니 참고하시면 됩니다.

링크 - https://ko.wikipedia.org/wiki/


Python으로 메일을 보내기 전에 메일 서버를 먼저 세팅을 해야 합니다.

구글 메일 참조 - https://support.google.com/a/answer/176600?hl=ko

네이버 메일 참조 - https://mail.naver.com/option/imap

다음 메일 참조 - https://cs.daum.net/faq/43/9234.html#35953


저의 경우는 구글을 통해 세팅을 하겠습니다.

먼저 크롬에 접속해서 오른쪽 상단에 회원 정보로 갑니다.(로그인이 되지 않았으면 로그인을 먼저 합니다.)

구글 계정으로 가서 보안 탭의 보안 수준이 낮은 앱의 액세스 탭으로 갑니다.

보안 수준이 낮은 앱의 사용을 체크합니다. 이 체크를 안하면 외부에서 구글 메일을 사용하지 못하게 하는 것이기 때문에 사용하기로 바꿔도 아이디 패스워드 노출이 안 된다면 보안상의 큰 문제는 없습니다.

Python에서 소스를 작성하고 메일을 발송하겠습니다.

# 메일 모듈이다.
import smtplib;
# 메일 메시지를 만드 모듈이다. (MIMEBase는 이하 MIMEMultipart, MIMEText, MIMEApplication, MIMEImage, MIMEAudio)의 상위 모듈이다.
# 굳이 선언할 필요없다.
#from email.mime.base import MIMEBase;
# 메일의 Data 영역의 메시지를 만드는 모듈 (MIMEText, MIMEApplication, MIMEImage, MIMEAudio가 attach되면 바운더리 형식으로 변환)
from email.mime.multipart import MIMEMultipart;
# 메일의 본문 내용을 만드는 모듈
from email.mime.text import MIMEText;
# 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.application import MIMEApplication;
# 메일의 이미지 파일을 base64 형식으로 변환(Content-ID 생성)
from email.mime.image import MIMEImage;
# 메일의 음악 파일을 base64 형식으로 변환(Content-ID 생성)
from email.mime.audio import MIMEAudio;
# 파일 IO
import io;

# 메일 서버와 통신하기 전에 메시지를 만든다.
data = MIMEMultipart();
# 송신자 설정
data['From'] = "nowonbun@gmail.com";
# 수신자 설정 (복수는 콤마 구분이다.)
data['To'] = "nowonbun@gmail.com,nowonbun@gmail.com";
# 참조 수신자 설정
data['Cc'] = "nowonbun@gmail.com";
# 숨은 참조 수신자 설정
data['Bcc'] = "nowonbun@gmail.com"
# 메일 제목
data['Subject'] = "Test Mail"

# 첨부 파일 추가
with open("test.xlsx", "rb") as fp:
  # Name은 메일 수신자에서 설정되는 파일 이름
  part = MIMEApplication(fp.read(), Name = "test.xlsx")
  # Data 영역의 메시지에 바운더리 추가
  data.attach(part)

# 이미지 파일 추가
with open("capture.png", 'rb') as fp:
  # Name은 메일 수신자에서 설정되는 파일 이름
  img = MIMEImage(fp.read(), Name = "capture.png")
  # 해더에 Content-ID 추가(본문 내용에서 cid로 링크를 걸 수 있다.)
  img.add_header('Content-ID', '<capture>')
  # Data 영역의 메시지에 바운더리 추가
  data.attach(img)

# 텍스트 형식의 본문 내용
#msg = MIMEText("Hello world", 'plain');
# Html 형식의 본문 내용 (cid로 이미 첨부 파일을 링크했다.)
msg = MIMEText("Hello Test<br /><img src='cid:capture'>", 'html')
# Data 영역의 메시지에 바운더리 추가
data.attach(msg);
# 메시지를 확인한다.
print(data);

# 메일 서버와 telnet 통신 개시
server = smtplib.SMTP_SSL('smtp.gmail.com',465);
#server = smtplib.SMTP('smtp.gmail.com',587);
# 메일 통신시 디버그
server.set_debuglevel(1);
# 헤로 한번 해주자.(의미 없음)
server.ehlo();
# tls 설정 주문 - tls 587 포트의 경우
#server.starttls();
# 헤로 또 해주자.(의미 없음)
server.ehlo();
# 로그인 한다.
server.login("id", "password");
# 심심하니 또 헤로 해주자.(의미 없음)
server.ehlo();

# MAIL(송신자) 설정
sender = data['From'];
# RCPT(수신자), 리스트로 보낸다.
# 수신자 추가
receiver = data['To'].split(",");
# 참조자 추가
if data['Cc'] is not None:
  receiver += data['Cc'].split(",");  
# 숨은 참조자 추가
if data['Bcc'] is not None:
  receiver += data['Bcc'].split(",");
  
# 메일 프로토콜 상 MAIL, RCPT, DATA 순으로 메시지를 보내야 하는데 이걸 sendmail함수에서 자동으로 해준다.
server.sendmail(sender, receiver, data.as_string());
# QUIT을 보내고 접속을 종료하고 메일을 보낸다.
server.quit();

실행을 하면 위 처럼 메시지 바운더리가 만들어 진 것을 확인할 수 있습니다.

메일이 제대로 전송이 되었습니다. 특히 이미지의 경우는 본문에 잘 보이네요.

링크 - https://docs.python.org/3/library/smtplib.html

링크 - https://docs.python.org/3.4/library/email-examples.html

링크 - https://stackoverflow.com/questions/17759860/


여기까지 Python에서 메일(smtplib)을 보내는 방법에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.