크즈망의 코딩 팩토리

썸네일

파이썬으로 업무 자동화를 하다 보면 항상 이메일 발송 자동화가 있는 것 같다.

파이썬이 이메일 보내기도 쉽고 이메일 대량 발송도 편해서 자주 애용하고 있다.


이메일 발송의 기본적인 개념

1. SMTP

대한민국에서 거래할 때 화폐가 원화로 지정되어있는 것처럼 이메일에도 표준적인 약속 체계나 규약이 있다.

SMTP(Simple Mail Transter Protocol) 영어를 그대로 해석하면 간단한 메일 전송 프로토콜이다.

 

여기서 프로토콜은 각 메일 회사마다 다르게 설정되어있다.

정확히 말하면 SMTP서버가 다르고 Well Known 포트인 465번을 공통적으로 사용한다.

 

쉽게 말하면 어떤 프로그래밍 언어든 간에 자신이 발신할 메일 주소의 SMTP 서버 주소포트만 알면 보낼 수 있다.

이번 설명글에서는 제가 회사에서 업무 메일로 쓰는 Daum 메일 기준으로 설명할 예정입니다.

 

파이썬 이메일은 파이썬에서 기본적으로 제공하는 smtplib를 이용할 생각이다.

 

2. MIME

SMTP서버에 메일을 전송하기 위해서는 MIME 포맷으로 보내주어야 한다.

MIME는 전자 우편을 위한 인터넷 표준 포맷인데 깊숙이는 잘 모르겠다.

smtplib를 이용하여 우리는 코드를 작성해 보내지만 실제로 SMTP 서버에 전송되는 데이터를 보면

MIME에 맞게 데이터가 변환되어 보내진다.

 

MIMIE로 변환된 데이터

대충 이런 형식이다. 이 형식은 SMTP는 7비트의 ASCII 문자를 사용하는데 8비트 이상의 데이터는 자동으로 MIME 포맷에 맞게 변환된다.

 

이건 머리 아프니 알아서 변환되는 구나하고 넘어가면 될 것 같다 (?)

 


이메일을 발송해보자

이제 메일을 보내보자.

아래는 다음 SMTP 서버를 이용해서 보내는 예제이다.

앞서 설명하였듯 메일 발송에 필요한 데이터 포맷은 MIME이다.

데이터의 종류가 텍스트, 이미지 파일, 엑셀 파일 등등 다양한 종류가 있는데

이걸 따로 MIME 포맷에 맞게 설정하여 변환해주어야 한다.

일반 텍스트의 경우 그냥 Text 형식으로 변환하면 되지만 첨부파일이 있을 경우

Javascript의 경우 MultiPart로 변경하듯 데이터 포맷을 MultiPart로 변경 후

MIME의 mixed라는 형식으로 보내야 한다.

 

아래 예제는 대량 전송과 첨부파일이 있을 때 어떤 식으로 전송해야 할지 작성되어있다.

send_email로 메일을 전송하며, 인자로 메일 주소 목록(딕셔너리), 제목, 내용, 첨부파일 경로이다.

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib

# 환경 설정
SETTING = {
    'SERVER': 'smtp.daum.net', # SMTP 서버 주소
    'PORT': 465,               # SMTP 포트
    'USER': '이메일 계정',      # SMTP 서버 로그인 계정
    'PASSWORD': '비밀번호'     # SMTP 서버 로그인 비밀번호
}

# 이메일 주소 등록
emails = ['kzkzmang@naver.com', 'kzkz']

# 이메일 주소 체크
def email_check(email):
    import re;
    # 이메일 체크 정규식
    regex = '^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'

    if re.match(regex, email):
        return True
    else:
        return False

def send_email(emails, subject, content, attach=None):
    for email in emails:
        if not email_check(email):
            print('메일주소를 확인해주세요 => ' + email)
            return

        # MIME 형식 설정
        if attach:
            #첨부파일이 존재할 경우
            mime = MIMEMultipart('mixed')
        else:
            mime = MIMEMultipart('alternative')

        mime['From'] = SETTING.get('USER')
        mime['To'] = email
        mime['Subject'] = subject

        contents = content
        text = MIMEText(_text = contents, _charset = 'utf-8')
        mime.attach(text)

        if attach:
            from email.mime.base import MIMEBase
            from email import encoders
            import os

            data = MIMEBase('application', 'octect-stream')
            data.set_payload(open(attach, 'rb').read())
            encoders.encode_base64(data)

            filename = os.path.basename(attach)
            data.add_header('Content-Disposition', 'attachment', filename=('UTF-8', '', filename))
            mime.attach(data)

        smtp = smtplib.SMTP_SSL(SETTING.get('SERVER'), SETTING.get('PORT'))

        smtp.login(SETTING.get('USER'), SETTING.get('PASSWORD'))

        smtp.sendmail(SETTING.get('USER'), email, mime.as_string())

        smtp.close()

        print('메일 발송 완료 ==> ' + email)


send_email(emails, '제목', '내용')

실제로 테스트해 본 이미지이다.

테스트 완료
파일을 첨부하여 보냈을 때

대량으로 이메일 전송하기가 끝이 났다.
생각보다 이메일 전송은 쉽게 할 수 있고, 여기서 더 나아가 성공, 실패를 카운트하여 그래프를 그려도 되고,
Restful 하게 만들어 메일 전송의 반환 값을 받아오면 메일 전송 실패 상세 원인까지 가져올 수 있으니 활용도는
다양하다.

하지만, 이건 엄연히 다른 회사의 SMTP 서버를 빌려서 전송하는거라 쉽고, 실제로 SMTP서버를 구성하여
메일 보내기를 하면 생각보다(?) 어렵다.

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading