보고서를 자동으로 메일까지 — 파이썬 smtplib 이메일 발송
금요일 보고서 xlsx를 저장한 뒤 Outlook에 첨부하던 루틴 — 김대리 팀은 smtplib로 같은 파일을 팀 메일링에 자동 발송합니다. VBA Outlook과 달리 서버 SMTP만 있으면 되고, Linux·스케줄러와도 잘 맞아요.
오늘은 파이썬 smtplib + email로 첨부 메일을 보내는 실무 패턴입니다. openpyxl 월간보고 · groupby 집계 결과를 붙이면 완전 자동화입니다.
이 글을 따라 하면 얻는 것
– SMTP TLS 로그인
– MIMEMultipart 본문·첨부
– Gmail 앱 비밀번호
– 테스트·로그·보안
1. Gmail 예시 (앱 비밀번호)
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from pathlib import Path
SMTP_HOST = "smtp.gmail.com"
SMTP_PORT = 587
USER = "your@gmail.com"
APP_PASSWORD = "xxxx xxxx xxxx xxxx" # 환경변수 권장
def send_report(to_addr: str, subject: str, body: str, attach_path: str):
msg = MIMEMultipart()
msg["From"] = USER
msg["To"] = to_addr
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain", "utf-8"))
path = Path(attach_path)
if path.is_file():
part = MIMEBase("application", "octet-stream")
part.set_payload(path.read_bytes())
encoders.encode_base64(part)
part.add_header("Content-Disposition", f'attachment; filename="{path.name}"')
msg.attach(part)
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
server.starttls()
server.login(USER, APP_PASSWORD)
server.send_message(msg)
if __name__ == "__main__":
send_report(
"team@example.com",
"[주간] 매출 보고",
"첨부 확인 부탁드립니다.",
"report.xlsx",
)
비밀번호는 코드에 하드코딩하지 마세요 — os.environ["SMTP_APP_PW"].
2. 회사 Exchange / Office 365
호스트·포트는 IT에 확인. 보통 smtp.office365.com:587 + 계정 MFA 시 앱 비밀번호.
3. HTML 본문
msg.attach(MIMEText("<p>보고서 <b>첨부</b>입니다.</p>", "html", "utf-8"))
4. 여러 수신자
msg["To"] = ", ".join(["a@co.kr", "b@co.kr"])
BCC는 msg["Bcc"] — send_message 시 전체 주소 리스트 전달.
5. 실패 처리
try:
send_report(...)
except smtplib.SMTPAuthenticationError:
print("인증 실패 — 앱 비밀번호·2FA 확인")
except FileNotFoundError:
print("첨부 없음")
6. VBA Outlook과 선택
| smtplib | VBA Outlook | |
|---|---|---|
| 환경 | Python·서버 | Windows·Outlook 설치 |
| 초안 검토 | 어려움 | Display 쉬움 |
| 스케줄 | cron·Task Scheduler | OnTime |
무인 발송 전 테스트 수신자로 1회 검증하세요.
7. FAQ
Q. 스팸 처리돼요.
SPF/DKIM은 도메인 관리자 영역. 본문에 링크 과다·첨부 exe 금지.
Q. 대용량 첨부?
25MB 제한 많음 — OneDrive 링크 + 짧은 본문.
8. 연습
1) 자신에게 테스트 메일 2) xlsx 첨부 3) 환경변수로 비밀번호 4) 로그 파일 기록.
참고: smtplib · VBA Outlook.
실무 메모 1
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 2
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 3
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 4
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 5
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 6
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 7
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 8
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 9
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 10
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 11
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 12
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 13
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 14
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 15
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 16
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 17
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 18
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 19
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 20
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 21
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 22
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 23
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 24
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 25
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 26
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 27
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 28
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 29
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 30
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 31
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 32
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 33
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 34
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 35
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 36
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 37
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 38
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 39
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 40
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 41
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 42
첨부 25MB 한도 확인. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 43
앱 비밀번호는 환경변수로. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.
실무 메모 44
테스트 수신자로 1회 검증. 분기말 보고서를 열면 같은 실수가 반복됩니다. 김대리 파일에서도 범위를 명시적으로 잡으니 응답이 빨라졌어요. 팀 README에 기준을 한 줄로 박아 두세요.