엑셀 매크로(VBA) 보안 경고 끝! 파이썬으로 똑같은 작업 대체하기
"매주 월요일마다 팀원 10명에게 주간 보고서 보내기", "거래처 20곳에 동일한 안내 메일 발송하기"…
받는 사람만 다를 뿐 내용은 거의 같은 이메일을 매번 손으로 작성해서 한 명씩 보내고 있지는 않으신가요? 실수로 수신자를 빠뜨리거나, 이름을 잘못 입력하는 오류도 반드시 생깁니다. 파이썬을 한 번만 세팅해두면 수신자 목록만 준비하면 이메일 발송이 자동으로 처리됩니다.
파이썬이 설치되어 있어야 합니다. 없다면 python.org에서 최신 버전을 받아 설치하세요. 설치 시 반드시 "Add Python to PATH"에 체크해야 합니다.
이번 스크립트는 파이썬 기본 내장 라이브러리(smtplib, email)만 사용합니다. 별도 설치가 필요 없습니다.
단, Gmail을 사용할 경우 앱 비밀번호를 먼저 발급받아야 합니다. 구글은 보안상 일반 비밀번호로 외부 앱의 메일 발송을 차단하기 때문입니다. 아래 순서로 발급하세요:
⚠️ 주의: 앱 비밀번호는 발급 시 한 번만 보여줍니다. 발급 즉시 메모장에 복사해두세요. 분실 시 재발급해야 합니다.
아래 코드를 그대로 복사해서 메모장에 붙여넣고, auto_email.py로 저장하세요. 저장 시 파일 형식은 "모든 파일", 인코딩은 UTF-8로 설정합니다.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# ① 발신자 설정
SENDER_EMAIL = "내이메일@gmail.com" # ← 본인 Gmail 주소
SENDER_PASSWORD = "xxxx xxxx xxxx xxxx" # ← 앱 비밀번호 (16자리)
# ② 수신자 목록 (이름, 이메일 주소)
RECIPIENTS = [
{"name": "홍길동", "email": "hong@example.com"},
{"name": "김철수", "email": "kim@example.com"},
{"name": "이영희", "email": "lee@example.com"},
]
# ③ 이메일 내용 설정
SUBJECT = "5월 업무 공지사항 안내"
BODY_TEMPLATE = """{name}님, 안녕하세요.
이번 달 업무 관련 공지사항을 안내드립니다.
1. 정기 회의: 매주 월요일 오전 10시
2. 보고서 제출 기한: 매월 마지막 날 오후 6시
3. 문의사항은 담당자에게 연락 바랍니다.
감사합니다.
IT꿀팁 연구소장 드림"""
# ④ 발송 실행 (이 아래는 수정하지 않아도 됩니다)
sent = 0
failed = 0
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(SENDER_EMAIL, SENDER_PASSWORD)
for recipient in RECIPIENTS:
try:
msg = MIMEMultipart()
msg["From"] = SENDER_EMAIL
msg["To"] = recipient["email"]
msg["Subject"] = SUBJECT
body = BODY_TEMPLATE.format(name=recipient["name"])
msg.attach(MIMEText(body, "plain", "utf-8"))
server.sendmail(SENDER_EMAIL, recipient["email"], msg.as_string())
print(f" ✔ 발송 완료: {recipient['name']} ({recipient['email']})")
sent += 1
except Exception as e:
print(f" ✘ 발송 실패: {recipient['email']} → {e}")
failed += 1
print(f"\n✅ 완료! 성공: {sent}건 / 실패: {failed}건")
SENDER_EMAIL과 SENDER_PASSWORD에 본인 Gmail 주소와 앱 비밀번호를 입력합니다.RECIPIENTS에 보낼 사람의 이름과 이메일 주소를 추가합니다.SUBJECT(제목)와 BODY_TEMPLATE(본문)을 원하는 내용으로 수정합니다.{name}을 본문에 넣으면 수신자 이름으로 자동 치환됩니다.python auto_email.py
정상 실행 시 터미널에 이렇게 출력됩니다:
✔ 발송 완료: 홍길동 (hong@example.com) ✔ 발송 완료: 김철수 (kim@example.com) ✔ 발송 완료: 이영희 (lee@example.com) ✅ 완료! 성공: 3건 / 실패: 0건
오류 1: SMTPAuthenticationError
Gmail 로그인에 실패한 경우입니다. 일반 비밀번호가 아닌 앱 비밀번호를 사용했는지 확인하세요. 앱 비밀번호는 띄어쓰기 없이 16자리를 그대로 입력합니다.
오류 2: 이름이 치환되지 않고 {name}이 그대로 출력됨
BODY_TEMPLATE에 {name}을 입력했는데 치환이 안 된다면, 코드 ④ 발송 실행 부분에서 .format(name=recipient["name"])이 빠진 경우입니다. 코드를 다시 복사해서 붙여넣으세요.
오류 3: 이메일이 스팸함으로 분류됨
짧은 시간에 많은 수신자에게 동일한 내용을 보내면 스팸으로 분류될 수 있습니다. 수신자가 50명 이상이라면 각 발송 사이에 time.sleep(2)를 추가해 2초 간격을 두는 것을 권장합니다.
PDF, 엑셀 등 파일을 첨부해서 발송하고 싶다면, 코드 ④ 발송 실행의 msg.attach(MIMEText(...)) 아래에 다음 코드를 추가하세요.
from email.mime.base import MIMEBase
from email import encoders
ATTACHMENT_PATH = r"C:\Users\내이름\Desktop\공지사항.pdf" # ← 첨부파일 경로
with open(ATTACHMENT_PATH, "rb") as f:
part = MIMEBase("application", "octet-stream")
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={Path(ATTACHMENT_PATH).name}"
)
msg.attach(part)
💡 매주 반복되는 발송이라면: 수신자 목록을 엑셀 파일로 관리하고, pandas로 읽어오도록 코드를 확장하면 수신자를 추가할 때 코드를 수정하지 않아도 됩니다. 이전 게시글 엑셀 파일 자동 병합 편을 참고하세요.
이 코드를 응용하면 HTML 형식의 이메일 발송, 예약 발송, 엑셀 수신자 목록 자동 연동까지 가능합니다.