OkBublewrap

2025-04-28 TIL (Python 이메일 송/수신) 본문

Today I Learning

2025-04-28 TIL (Python 이메일 송/수신)

옥뽁뽁 2025. 4. 28. 23:00

📅 2025-04-28 | TIL (Today I Learned)

📋 하루 요약

  • PASS BY PASS 제출
  • 파이썬 카카오 이메일 학습

 

⚡️ 회고

이메일 확인하기

카카오 메일 사용

 

[IMAP] Kakao메일 IMAP/ POP3 서버 주소 설정은 어떻게 하나요? | kakao 고객센터

외부 메일 프로그램에 설정하기 전에 가장 먼저 카카오메일에서 POP3 또는 IMAP의 사용여부 설정을 해주셔야 합니다. 카카오메일 > 설정 > IMAP/POP3 에서 사용 여부 설정이 가능합니다. 1. IMAP / SMTP -

cs.kakao.com

 

 

poplib 패키지

  • poplib는 POP3 서버에 연결하여 받은 메일을 확인하는 데 사용하는 모듈
  • 매번 웹 메일을 접속해서 새로운 메일 내용 확인 번거로울 때 이를 자동화할 경우 사용

기본 사용법

import poplib

# 1. SSL로 POP3 서버 접속
server = poplib.POP3_SSL('pop.kakao.com', 995)

# 2. 로그인
# ID 입력
server.user('')

# Password 입력
server.pass_('')

# 3. 메일 리스트 가져오기
resp, mails, octets = server.list()
print(f"총 {len(mails)}개의 메일이 있습니다.")

# 4. 가장 최근 메일 가져오기
if mails:
    resp, lines, octets = server.retr(len(mails))
    msg_content = b'\r\n'.join(lines).decode('utf-8', errors='ignore')
    print(msg_content)

else:
    print("메일이 없습니다.")

 

총 10개의 메일이 있습니다라고 출력이 되고, 카카오 메일에 확인을 해보니 10개가 있는 것을 확인했다.

resp, mails, octets = server.list()

  • resp: 응답결과
    • b'+OK Message follow'
  • mails: 메일 번호와 크기 정보가 들어있는 바이트 문자열 리스트
  • octets: 전체 파일 크기
    • 47227

 

최근 메일 가져오기

# pop3 에 저장된 메일 개수, 크기(bytes)
server.stat()

# 가장 최근 메세지 번호
recent_no = server.stat()[0]

# 메세지 가져오기 (바이트 문자열, 두번째 요소가 메세지 내용)
server.retr(recent_no)

# 줄바꿈으로 메세지 내용 조인
raw_email = b'\n'.join(server(recent_no)[1])

 

email

email는 바이트 문자열 형식의 이메일 메시지를 사람이 알아볼 수 있는 문자열 형태로 파싱 및 디코딩할 때 사용하는 모듈

import email
from email.header import decode_header, make_header

message = email.messasge_from_bytes(raw_email)

# 이메일 정보 확인
# 송신자 확인
message.get('From')
# '=?UTF-8?b?7JuQ7Yuw65Oc?= wanted <news@newsletter.wantedlab.com>'

# email 모듈 디코더 활용
fr = make_header(decode_header(message.get('From')))
print(fr)
# 원티드 추천 포지션 <recommend-noreply@mail.wantedlab.com>

 

 

 

html로 구성되어 있는 추천 포지션

 

이메일 본문 확인

이메일의 메시지는 멀티파트로 구성될 수도 있고 아닐 수도 있음

이메일에 첨부 파일이 있거나 text/plain 또는 text/html 형식의 내용을 동시에 보낸다면 멀티파트 형식

body = None

if message.is_multipart():
    # 멀티파트라면
    for part in message.walk(): # 메일 안 들어있는 파트 하나씩 꺼내기
        ctype = part.get_content_type() # 콘텐츠타입 가져오기
        # text/plain: 텍스트
        # text/html: HTML
        # application/pdf: 첨부 파일
        cdispo = str(part.get('Content-Disposition')) # 첨부파일
        
        # 첨부파일이 아닌 경우
        if 'attachment' not in cdispo:
            if ctype == 'text/plain':
                body = part.get_payload(decode=True) # payload = 실제 본문 내용, decode = True: 이메일이 인코딩된 경우에도 사람이 읽을 수 있는 형태 변환
                break  # text/plain을 최우선으로
            elif ctype == 'text/html' and body is None:
                # text/plain이 없으면 text/html 저장
                body = part.get_payload(decode=True)
else:
    # 싱글파트라면
    body = message.get_payload(decode=True)

# 본문 디코딩
if body:
    body = body.decode('utf-8')
    print(f"보낸사람: {fr}")
    print(f"제목: {subject}")
    print(f"내용: {body}")
else:
    print("본문이 없습니다.")

 

일부분 추출

 

html 저장

# html 저장
filename = f"{subject}.html"  # 제목으로 파일 이름 만들기 

with open(filename, 'w', encoding='utf-8') as f:
    f.write(body)

 

이메일 보내기

예제 실습

  • SMTP 메일서버 주소: smtp.kakao.com (465 / SSL)
  • smtplib 라이브러리 사용(메시지 발송 모듈)
더보기
# 발송할 메세지는 email 모듈을 사용해서 작성
import smtplib

# 파일 첨부용 멀티파트 객체
from email.mime.multipart import MIMEmultipart
msg = MIMEMultipart()

# 이메일 송수신자 설정
msg['From'] = 'user1@kakao.com'
msg['To'] = 'user2@gmail.com'

# 날짜 설정
from email.utils import formatdate
msg['Date'] = formatdate(localtime=True)

# 이메일 제목/본문 작성
from email.header import Header
from email.mime.text import MIMEText

msg['Subject'] = Header(s='[원티드] 이 회사에서 원하고 있어요', charset='utf-8')
body = MIMEText('html를 확인해주세요', _charset='utf-8')

# 메일 본문 추가
msg.attach(body)

files = list()
files.append('test1.pdf')
files.append('test2.jpg')

import os
from email.mime.base import MIMEBase
from email.encoders import encode_base64

for f in files:
    part = MIMEBase('application', "octet-stream")
    part.set_payload(open(f, "rb").read())
    encode_base64(part)                           # 바이너리 파일 base64 인코딩
    part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
    msg.attach(part)     # 파일 첨부

# 메일 발송하기
mailServer = smtplib.SMTP_SSL('smtp.kakao.com')          
mailServer.login('user_id', 'user_password')
mailServer.send_message(msg)
mailServer.quit()

gmail 수신된 이메일

 

html 보내기

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

# 저장해둔 HTML 파일 읽기
with open(r"이 회사에서 원하고 있어요!🤗.html", "r", encoding="utf-8") as f:
    html_content = f.read()

# 메일 준비
msg = MIMEMultipart('alternative')
msg['Subject'] = "이 회사에서 원하고 있어요!🤗"
msg['From'] = 'user1@kakao.com'
msg['To'] = 'user2@gmail.com'

# 읽어온 HTML을 본문으로 추가
mime_html = MIMEText(html_content, 'html')
msg.attach(mime_html)

# 4. 메일 서버 연결 후 전송
server = smtplib.SMTP_SSL('smtp.kakao.com', 465)
server.login('user_id', 'user_password')
server.sendmail(msg['From'], msg['To'], msg.as_string())
server.quit()

 

요약

  • 이메일 본문이 HTML인 경우 파일로 저장해 재사용 가능
  • MIMEText의 html 타입을 사용하면 HTML 레이아웃 안깨짐
  • POP3/STMP 서버 주소/포트를 정확히 입력하고 SSL 연결 사용
  • 파일 읽기/쓰기 시 인코딩 utf-8(이메일 기본적으로 바이트로 디코딩되서 전달)
  • kakao, gmail 같은 경우 2차 비밀번호를 사용한다. 앱 비밀번호를 사용

 

✔️ To-Do

2025.04.29 할 일

  • 뉴스기사 요약 이메일 보내기
  • 북스터디
  • 면접스터디

'Today I Learning' 카테고리의 다른 글

2025-04-30 TIL (면접코칭)  (0) 2025.04.30
2025-04-29 TIL (일기)  (0) 2025.04.30
2025-04-27 TIL (socket, 북스터디)  (0) 2025.04.28
2025-04-23 TIL (gensim)  (0) 2025.04.23
2025-04-15 TIL (일기)  (0) 2025.04.16