2023-02-15 작성

파이썬 이메일 전송 활용 예제

파이썬으로 간단하게 네이버 이메일을 보내보려고 한다. 이번 포스팅에서는 네이버 메일로 테스트를 진행하지만, 타메일에서도 환경설정만 한다면 이메일 전송할 수 있다.

최종 목표

사전 준비

1. 파이썬과 주피터가 설치되어 있지 않다면 파이썬 3.11 설치와 주피터 노트북 사용법 포스팅을 참고하여 설치한다.

2. 이메일을 전송하기 위해 아래 라이브러리가 필요하다. 파이썬 설치 시 기본 제공되므로 import로 가져다 쓰면 된다. 

  • 이메일 전송하기 위해, smtplib 라이브러리 사용
  • 이메일 메시지를 관리하고 파일 첨부를 할 수 있는 email 라이브러리 사용

자세한 사용법은 라이브러리 문서를 참고하자.

3. 아래 라이브러리가 없다면 라이브러리를 설치한다. '윈도우키+R'을 눌러서 나타난 실행창에 'cmd'를 입력하여 창을 켠다. 그리고 아래 명령어를 입력하여 라이브러리를 설치하자.

# requests 라이브러리 설치
pip install requests

1. 보내는 사람 이메일 SMTP 설정하기

우리가 흔히 보내는 이메일은 이메일 서버간의 약속된 규정으로 주고 받는다. 우리가 이메일을 보내면 SMTP 서버에 저장하고, 받는 사람의 POP3/IMAP 서버로 보내진다.

즉, 보내는 사람의 이메일 계정에서 별도의 설정이 필요하므로, 네이버 메일로 들어가서 [환경설정] > [POP3/IMAP 설정] > [IMAP/SMTP 설정] 클릭한 후 '사용함'을 체크한 후 저장 버튼을 클릭한다. 

 
스크롤을 좀 더 내리면, 메일 송수신 프로토콜 정보가 보인다. 여기서 기억해야 할 정보는 아래와 같다. 

  • 이메일 수신시, IMAP 프로토콜을 사용하며 서버명은 imap.naver.com, 포트는 993이다.
  • 이메일 송신시, SMTP 프로토콜을 사용하며 서버명은 smtp.naver.com, 포트는 587이다. 이메일 송신 시 보안 연결(TLS)가 필요하다.

2. 텍스트 메일 보내기

메일을 보내려고 하는 미디어 종류에 따라 호출하는 클래스가 다르다.

  • MIMEText : 텍스트로 구성된 메일을 보낼 경우
  • MIMEImage : 이미지를 보낼 경우
  • MIMEAudio : 오디오를 보낼 경우
  • MIMEBase : 그 외를 보낼 경우
  • MIMEMultipart : 여러 종류의 메시지를 한 번에 보내고 싶을 경우

먼저 MIMEText를 사용해서 텍스트로만 구성된 메일을 보내볼 것이다.

import smtplib
from email.mime.text import MIMEText

# 메일 전송
def send_email(send_info, message):
    
    # 5. SMTP 세션 생성
    with smtplib.SMTP(send_info["send_server"], send_info["send_port"]) as server:
        
        # 6. TLS 보안 연결
        server.starttls()
        
        # 7. 보내는사람 계정으로 로그인
        server.login(send_info["send_user_id"], send_info["send_user_pw"])

        # 8. 로그인 된 서버에 이메일 전송
        response = server.sendmail(message['from'], message['to'], message.as_string())

        # 9. 이메일 전송 성공시
        if not response:
            print('이메일을 정상적으로 보냈습니다.')
        else:
            print(response)
            
# 1. 메일 전송 파라미터
send_info = dict(
    {"send_server" : "smtp.naver.com", # SMTP서버 주소
     "send_port" : 587, # SMTP서버 포트
     "send_user_id" : "보내는사람_네이버_아이디@naver.com",
     "send_user_pw" : "보내는사람_네이버_비밀번호"
    }
)

# 2. 전송할 메일 정보 작성
sender = send_info["send_user_id"]
receiver = "받는사람_네이버_아이디@naver.com"
title = "개발새발 보낸 메일 제목입니다"
content = "개발새발 보낸 메일 내용입니다"

# 3. 메일 객체 생성
message = MIMEText(_text = content, _charset = "utf-8") # 메일 내용
message['subject'] = title # 메일 제목
message['from'] = sender # 보낸사람
message['to'] = receiver # 받는사람

# 4. 메일 전송 함수를 호출
send_email(send_info, message)

위 소스를 실행 결과한 결과이다. 제목과 내용이 정상적으로 보내진다.

3. 이미지 파일도 추가하여 메일 보내기

이번에는 단순 텍스트 말고도 이미지 파일도 추가해 볼 것이다. MIMEText 말고도 MIMEImage, MIMEMultipart도 사용했다.

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

# 메일 전송
def send_email(send_info, message):
    
    # SMTP 세션 생성
    with smtplib.SMTP(send_info["send_server"], send_info["send_port"]) as server:
        
        # TLS 보안 연결
        server.starttls()
        
        # 보내는사람 계정으로 로그인
        server.login(send_info["send_user_id"], send_info["send_user_pw"])

        # 로그인 된 서버에 이메일 전송
        response = server.sendmail(message['from'], message['to'], message.as_string())

        # 이메일 전송 성공시
        if not response:
            print('이메일을 정상적으로 보냈습니다.')
        else:
            print(response)

# 첨부파일 추가
def attach_multi(multi_info):

    # 3. 이메일 메시지에 다양한 형식을 담아내기 위한 객체 설정
    multi = MIMEMultipart(_subtype='mixed')
    
    # 4. 이미지 갯수만큼 반복
    for key, value in multi_info.items():
    
        # 이미지 타입 MIMEImage 함수 호출하여 msg 객체 생성   
        with open(value['filename'], 'rb') as fp:
            msg = MIMEImage(fp.read(), _subtype=value['subtype'])
        
        # 파일명을 첨부파일 제목으로 추가
        msg.add_header('Content-Disposition', 'attachment', filename=value['filename'])

        # 첨부파일 추가
        multi.attach(msg)
    
    return multi

# 메일 전송 파라미터
send_info = dict(
    {"send_server" : "smtp.naver.com", # SMTP서버 주소
     "send_port" : 587, # SMTP서버 포트
     "send_user_id" : "보내는사람_네이버_아이디@naver.com",
     "send_user_pw" : "보내는사람_네이버_비밀번호"
    }
)

# 1. 보낼 이미지 파라미터
multi_info = {
  'image1' : {'maintype' : 'image', 'subtype' :'jpg', 'filename' : 'lonelyPark_1.jpg' },
  'image2' : {'maintype' : 'image', 'subtype' :'jpg', 'filename' : 'lonelyPark_2.jpg' },
  'image3' : {'maintype' : 'image', 'subtype' :'jpg', 'filename' : 'lonelyPark_3.jpg' }
}

# 전송할 메일 정보 작성
sender = send_info["send_user_id"]
receiver = "받는사람_네이버_아이디@naver.com"
title = "개발새발 보낸 메일 제목입니다"
content = "개발새발 보낸 메일 내용입니다"

# 메일 객체 생성
message = MIMEText(_text = content, _charset = "utf-8") # 메일 내용

# 2. 첨부파일 추가
multi = attach_multi(multi_info)

# 5. 첨부파일 추가한 객체에 정보 세팅
multi['subject'] = title # 메일 제목
multi['from'] = sender # 보낸사람
multi['to'] = receiver # 받는사람
multi.attach(message)

# 메일 전송 함수를 호출
send_email(send_info, multi)

위 소스를 실행 결과한 결과이다. 제목과 내용 말고도, 샘플 이미지 3개가 첨부파일에 보이고 있다.

4. 다양한 미디어 메일 보내기(최종 소스)

텍스트, 이미지 말고도 txt, mp3, mp4, pdf, xlsx 등 다양한 미디어 파일을 보내기 위해서 예제를 더 응용해 봤다. 

import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.audio import MIMEAudio
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase

# 메일 전송
def send_email(send_info, message):
    
    # SMTP 세션 생성
    with smtplib.SMTP(send_info["send_server"], send_info["send_port"]) as server:
        
        # TLS 보안 연결
        server.starttls()
        
        # 보내는사람 계정으로 로그인
        server.login(send_info["send_user_id"], send_info["send_user_pw"])

        # 로그인 된 서버에 이메일 전송
        response = server.sendmail(message['from'], message['to'], message.as_string())

        # 이메일 전송 성공시
        if not response:
            print('이메일을 정상적으로 보냈습니다.')
        else:
            print(response)

# 첨부파일 추가
def attach_multi(multi_info):

    # 이메일 메시지에 다양한 형식을 담아내기 위한 객체 설정
    multi = MIMEMultipart(_subtype='mixed')
    
    # 미디어 파라미터 갯수만큼 반복
    for key, value in multi_info.items():
        
        if key == 'text': # 텍스트 타입
            with open(value['filename'], encoding='utf-8') as fp:
                msg = MIMEText(fp.read(), _subtype=value['subtype'])
                
        elif key == 'image': # 이미지 타입
            with open(value['filename'], 'rb') as fp:
                msg = MIMEImage(fp.read(), _subtype=value['subtype'])

        elif key == 'audio': # 오디오 타입
            with open(value['filename'], 'rb') as fp:
                msg = MIMEAudio(fp.read(), _subtype=value['subtype'])
        
        else: # 그외
            with open(value['filename'], 'rb') as fp:
                msg = MIMEBase(value['maintype'],  _subtype=value['subtype'])
                msg.set_payload(fp.read())
                encoders.encode_base64(msg)
        
        # 파일 이름을 첨부파일 제목으로 추가
        msg.add_header('Content-Disposition', 'attachment', filename=value['filename'])

        # 첨부파일 추가
        multi.attach(msg)
    
    return multi

# 메일 전송 파라미터
send_info = dict(
    {"send_server" : "smtp.naver.com", # SMTP서버 주소
     "send_port" : 587, # SMTP서버 포트
     "send_user_id" : "보내는사람_네이버_메일@naver.com",
     "send_user_pw" : "보내는사람_네이버_비밀번호"
    }
)

# 보낼 미디어 파라미터
multi_info = {
  'text' : {'maintype' : 'text', 'subtype' :'plain', 'filename' : 'sample.txt'}, # 텍스트 첨부파일
  'image' : {'maintype' : 'image', 'subtype' :'jpg', 'filename' : 'lonelyPark_1.jpg' }, # 이미지 첨부파일
  'audio' : {'maintype' : 'audio', 'subtype' :'mp3', 'filename' : 'ditto.mp3' }, # 오디오 첨부파일
  'video' : {'maintype' : 'video', 'subtype' :'mp4', 'filename' : '개발새발.mp4' }, # 비디오 첨부파일
  'application' : {'maintype' : 'application', 'subtype' : 'octect-stream', 'filename' : 'daily_price.xlsx'} # 그외 첨부파일
}

# 전송할 메일 정보 작성
sender = send_info["send_user_id"]
receiver = "받는사람_네이버_메일@naver.com"
title = "개발새발 보낸 메일 제목입니다"
content = "개발새발 보낸 메일 내용입니다"

# 메일 객체 생성
message = MIMEText(_text = content, _charset = "utf-8") # 메일 내용

# 첨부파일 추가
multi = attach_multi(multi_info)

# 첨부파일 추가한 객체에 정보 세팅
multi['subject'] = title # 메일 제목
multi['from'] = sender # 보낸사람
multi['to'] = receiver # 받는사람
multi.attach(message)

# 메일 전송 함수를 호출
send_email(send_info, multi)

실행 결과는 아래와 같다. 다양한 미디어 샘플 파일들이 정상적으로 첨부되어 보인다. 단, 보내는데 용량 제한이 있으니 대용량의 파일은 메일 전송이 실패할 수 있다.