Data Engineering/Python

[Python] 파이썬으로 파일 첨부하여 메일 보내기(Gmail)(SMTP / MIME)

YSY^ 2022. 2. 6. 18:58

이번 포스팅에서는 파이썬으로 구글메일 API를 활용하여 메일을 보내고 파일까지 첨부하는 것을 알아보겠습니다.

권한설정

1. 보안 설정 변경

  • 보안 -> 엑세스 사용 설정 -> 보안 수준이 낮은 앱 허용(사용)으로 바꾸기

2. GMail IMAP값 변경

  • Gmail -> 설정(톱니바퀴) -> 모든 설정보기 클릭

  • 전달 및 POP/IMAP -> IMAP 사용안함을 사용으로 바꾸고 -> 저장

 

개념설명

  • SMTP(Simple Mail Transfer Protocol) : 인터넷에서 메일을 주고 받기 위해 이용하는 프로토콜(메일 서버간 전송 규약)
  • POP3 : 받는 메일, 서버에 메일을 저장해 두지 않음
  • IMAP : 받는 메일, 서버에 메일을 저장해두어서 언제든 원하는 메일 열람 가능
  • MIME : 이메일을 보낼 때 형식을 정해둔 것

 

SMTP 서버와 연결 후 로그인

# smpt 서버와 연결
import smtplib

gmail_smtp = "smtp.gmail.com"  #gmail smtp 주소
gmail_port = 465  #gmail smtp 포트번호
smpt = smtplib.SMTP_SSL(gmail_smtp, gmail_port)
print(smpt)

위와 같은 문구가 뜬다면 성공적으로 연결된 것이다.

# 로그인
my_id = "GMail 계정"
my_password = "GMail 비밀번호"
smpt.login(my_id, my_password)

로그인이 되면 위 문구가 뜬다.

 

기본 설정 및 내용 첨부

from email.mime.multipart import MIMEMultipart # 메일의 Data 영역의 메시지를 만드는 모듈 

# 메일 기본 정보 설정
msg = MIMEMultipart()
msg["Subject"] = f"요청하신 데이터를 전달드립니다"
msg["From"] = "ysyblog"
msg["To"] = "보내는 메일주소"

메일의 기본 정보를 설정합니다.

  • Subject : 메일 제목
  • From : 보내는 사람
  • To : 받는 사람(받는 사람 메일 주소)
# 메일 내용 쓰기

from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈

content = "안녕하세요. \n\n\
데이터를 전달드립니다.\n\n\
감사합니다\n\n\
"

content_part = MIMEText(content, "plain")
msg.attach(content_part)

내용을 쓴 후 MIMEText로 내용을 base64형식으로 변환하여 따로 저장합니다.

 

파일 첨부 (데이터파일, 이미지파일, 음악파일)

# 데이터 파일 첨부하기
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환

file_name = "file.xlsx"

with open(file_name, 'rb') as excel_file : 
    attachment = MIMEApplication( excel_file.read() )
    #첨부파일의 정보를 헤더로 추가
    attachment.add_header('Content-Disposition','attachment', filename=file_name) 
    msg.attach(attachment)
  • Content-Disposition : 컨텐츠가 브라우저에 inline 되어야 하는 웹페이지 자체이거나 웹페이지의 일부인지, 아니면 attachment로써 다운로드 되거나 로컬에 저장될 용도록 쓰이는 것인지를 알려주는 헤더
  • attachment : 반드시 다운로드 받아야 하며 대부분의 브라우저는 'Save as'(새이름으로저장) 창을 보여줌
  • filename :  메일 수신자에서 설정되는 파일 이름

출처 : https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Disposition

# 이미지 파일 추가
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환

image_name = "image.png"
with open(image_name, 'rb') as fp:
    img = MIMEImage(fp.read())
    img.add_header('Content-Disposition','attachment', filename=image_name)
    msg.attach(img)

 

메일 보내고 서버 닫기

# 메일 보내고 서버 끄기
to_mail = "보내고자 하는 메일 주소"

smpt.sendmail(my_id, to_mail, msg.as_string())  
smpt.quit()

서버가 닫혔으면 위 문구가 뜹니다.
메일이 성공적으로 도착하였다.

코드 정리

import smtplib
from email.mime.multipart import MIMEMultipart # 메일의 Data 영역의 메시지를 만드는 모듈 
from email.mime.text import MIMEText # 메일의 본문 내용을 만드는 모듈
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환
from email.mime.image import MIMEImage # 메일의 이미지 파일을 base64 형식으로 변환

# smpt 서버와 연결
gmail_smtp = "smtp.gmail.com"  #gmail smtp 주소
gmail_port = 465  #gmail smtp 포트번호
smpt = smtplib.SMTP_SSL(gmail_smtp, gmail_port)
print(smpt)

# 로그인
my_id = "GMail 계정"
my_password = "GMail 비밀번호"
smpt.login(my_id, my_password)


# 메일 기본 정보 설정
msg = MIMEMultipart()
msg["Subject"] = f"요청하신 데이터를 전달드립니다"
msg["From"] = "ysyblog"
msg["To"] = "보내는 메일주소"

# 메일 내용 쓰기
content = "안녕하세요. \n\n\
데이터를 전달드립니다.\n\n\
감사합니다\n\n\
"
content_part = MIMEText(content, "plain")
msg.attach(content_part)

# 데이터 파일 첨부하기
file_name = "file.xlsx"
with open(file_name, 'rb') as excel_file : 
    attachment = MIMEApplication( excel_file.read() )
    #첨부파일의 정보를 헤더로 추가
    attachment.add_header('Content-Disposition','attachment', filename=file_name) 
    msg.attach(attachment)
    
# 이미지 파일 추가
image_name = "image.png"
with open(image_name, 'rb') as fp:
    img = MIMEImage(fp.read())
    img.add_header('Content-Disposition','attachment', filename=image_name)
    msg.attach(img)
    
# 메일 보내고 서버 끄기
to_mail = "보내고자 하는 메일 주소"
smpt.sendmail(my_id, to_mail, msg.as_string())  
smpt.quit()

 

CF) 만들어놓은 데이터를 로컬에 저장하지 않고 바로 첨부하기

import io

def export_excel(df):
    with io.BytesIO() as buffer:
        writer = pd.ExcelWriter(buffer)
        df.to_excel(writer, index=False)
        writer.save()
        return buffer.getvalue()

def export_csv(df):
    textStream = io.StringIO();
    df.to_csv(textStream, index=False, encoding="utf-8-sig");
    return textStream.getvalue()
 
# 데이터 파일 첨부하기
from email.mime.application import MIMEApplication # 메일의 첨부 파일을 base64 형식으로 변환

file_name = "file.xlsx"

attachment = MIMEApplication(export_excel(df))
attachment.add_header('Content-Disposition','attachment', filename=file_name) 
msg.attach(attachment)
  • 위 코드를 활용하면 로컬에 저장하고 다시 불러올 필요 없이 바로 데이터를 첨부해서 보낼 수 있다.
  • export_excel : xlsx 파일로 만들어서 첨부할 때
  • export_csv : csv 파일로 만들어서 첨부할 때
728x90
반응형