[Python] IMAP으로 Gmail 메일 가져오기 - 메일 검색, 데이터 추출, 첨부파일 다운로드
by 우와한개발자
1. IMAP이란?
- IMAP(Internet Message Access Protocol)은 서버에서 메일을 가져오는 프로토콜
- 사용자가 모든 장치에서 이메일에 액세스할 수 있게 해준다.
- 서버에서 이메일 클라이언트로 이메일을 다운로드하는 대신 이메일 서버와 이메일 클라이언트 간의 중개자 역할을 한다.
- 즉, 메일을 서버에 보관한 채로 읽기 때문에 여러 기기에서 동기화 가능
- imaplib은 파이썬 기본 내장 라이브러리라 별도 설치가 필요 없다.
2. IMAP으로 Gmail 가져오기
1) 이메일 계정 접속
- Gmail에서 IMAP을 사용하려면 앱 비밀번호가 필요하다.(일반 비밀번호로는 접속이 안 됨)
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com') # Gmail IMAP 서버에 SSL 방식으로 접속
mail.login('your@gmail.com', '앱 비밀번호 16자리') # 일반 비밀번호 아닌 앱 비밀번호 사용
mail.select('inbox') # 받은편지함 선택
print('Connected to mailbox')
- Google 앱 비밀번호 발급 방법
1. Chrome 설정 → Google 계정 관리
2. 보안 및 로그인 → 앱 비밀번호 검색
3. 앱 이름 입력 후 만들기
4. 생성된 16자리 비밀번호 복사해두기 # 생성 후 다시 확인할 수 없으니 반드시 복사
- 폴더 종류
mail.select('inbox') # 받은편지함
mail.select('Sent') # 보낸편지함
mail.select('Drafts') # 임시보관함
mail.select('Trash') # 휴지통
mail.select('Spam') # 스팸함
2) 메일 검색
- mail.search()로 조건에 맞는 메일 ID 목록을 가져온다.
# 전체 메일 검색
result, data = mail.search(None, "ALL")
mail_ids = data[0].split() # 메일 ID 리스트
# 조건 검색
mail.search(None, "UNSEEN") # 읽지 않은 메일
mail.search(None, "FROM 'test@test.com'") # 특정 발신자
mail.search(None, "SUBJECT '업무협조'") # 특정 제목
3) 메일 데이터 가져오기
- 메일 ID로 메일을 가져온 뒤 제목, 발신자, 날짜, 본문을 추출한다.
- 메일 데이터는 전송 과정에서 다양한 인코딩 방식으로 변환되기 때문에 디코딩이 필요하다.
- 제목은 이메일 헤더 규격으로 인코딩 → decode_header()
- 본문은 일반 바이트 데이터 → .decode()
import email
from email.header import decode_header
# 메일 가져오기
result, data = mail.fetch(mail_ids[-1], "(RFC822)") # 가장 최근 메일
raw_email = data[0][1]
msg = email.message_from_bytes(raw_email)
# 제목 디코딩
subject, encoding = decode_header(msg["Subject"])[0]
if isinstance(subject, bytes):
subject = subject.decode(encoding or "utf-8")
# 발신자, 날짜
sender = msg["From"]
date = msg["Date"]
print("제목:", subject)
print("발신자:", sender)
print("날짜:", date)
# 본문 텍스트 추출
for part in msg.walk():
if part.get_content_type() == "text/plain":
body = part.get_payload(decode=True).decode("utf-8", errors="ignore")
print("본문:", body[:200])
4) 첨부파일 다운로드
- 메일은 텍스트, 이미지, 첨부파일 등 여러 파트로 구성되어있다.
메일 (msg)
├── 텍스트 본문 (Content-Type: text/plain)
├── HTML 본문 (Content-Type: text/html)
├── 첨부파일1.pdf (Content-Disposition: attachment)
└── 첨부파일2.xlsx (Content-Disposition: attachment)
- 각 파트의 Content-Disposition 헤더값이 attachment이면 첨부파일로 판단한다.
- 파일명도 제목과 마찬가지로 인코딩되어 있어서 decode_header()로 디코딩이 필요하다.
import os
SAVE_DIR = "./downloads"
os.makedirs(SAVE_DIR, exist_ok=True) # 저장 폴더 없으면 자동 생성
all_files = []
for part in msg.walk(): # 메일의 각 파트 순회
content_disposition = part.get("Content-Disposition")
# 첨부파일 여부 확인
if content_disposition and "attachment" in content_disposition:
filename = part.get_filename()
if filename:
filename, enc = decode_header(filename)[0] # 파일명 디코딩
if isinstance(filename, bytes):
filename = filename.decode(enc or "utf-8")
filepath = os.path.join(SAVE_DIR, filename)
with open(filepath, "wb") as f:
f.write(part.get_payload(decode=True)) # 파일 저장
print(f"다운로드 완료: {filepath}")
all_files.append(filepath)
'언어 > Python' 카테고리의 다른 글
| [Python] Streamlit이란? — 설치, UI 컴포넌트, 세션 상태 (0) | 2026.06.10 |
|---|---|
| [Python] pdfplumber로 PDF 텍스트 추출하기 (0) | 2026.04.29 |
| [Python] 데코레이터(Decorator) - @문법, functools.wraps (0) | 2026.04.21 |
| [Python] pandas로 Oracle 데이터 읽기 - read_sql, DataFrame (0) | 2026.04.19 |
| [Python] 오라클 DB 연결 - pip install oracledb / Connect, Cursor, Row 객체 (0) | 2026.04.19 |
블로그의 정보
우와한개발자 님의 블로그
우와한개발자