GitHub push 이메일 알림 안 옴: 종료된 기능과 Actions 대체 설정

Quick Answer
GitHub push 메일이 안 오는 이유와 Actions 대체 알림의 확인 순서는 무엇인가요?
GitHub push 이메일 알림이 안 온다면 기존 저장소 push 알림을 쓰던 것인지 먼저 확인하세요. GitHub는 2026년 10월 15일 이 기능을 종료해 더 이상 발송하지 않습니다. 대안은 push로 실행되는 Actions와 자체 SMTP·메일 제공업체를 연결하는 방식입니다. 워크플로 성공, SMTP 접수, 최종 메일 수신은 따로 확인해야 합니다.
Reading Guide
이 글에서 해결할 문제
- 이런 분께
- 기존 push 이메일 중단 원인을 확인하고 대체 발송 경로를 준비하는 개발자·관리자
- 읽고 나면
- 종료 범위를 판단하고 push 감지·SMTP 접수·실제 수신의 증거를 구분합니다.
- 다루는 범위
- 공식 자료 분석·SMTP 모의 시험 10개·로컬 CLI 입력 거부 2건입니다. GitHub 원격 실행·실제 발송·수신은 미검증입니다.
- 직접 확인
- 받던 메일의 종류와 10월 15일 종료 범위를 확인합니다.
- branches·Actions 권한·SMTP 인증 방식과 secrets 범위를 맞춥니다.
- SHA·run ID·Message-ID·제공업체 기록·수신 헤더를 대조합니다.
상황별 바로가기: 종료된 알림 확인 · main 브랜치 설정 예제 · Actions 실행이 없을 때 · 성공했는데 메일이 없을 때
10월 15일 종료된 것은 저장소 push 이메일 알림입니다
GitHub의 공식 공지는 “종료 예정” 안내가 아닙니다. 2026년 10월 15일부터 저장소 push 이벤트 이메일 알림을 보내지 않는다는 시행 내용입니다. 수신자의 사전 동의 없이 원치 않는 메일을 보낼 수 있었던 문제를 종료 이유로 설명했습니다. GitHub 공식 종료 공지
예전에 저장소 push 이메일 설정으로 받던 메일만 끊겼다면 옛 안내의 메뉴를 반복해서 설정하기보다 알림 경로를 바꿔야 합니다. 이미 자체 Actions·SMTP로 보내던 메일이 끊겼다면 그 경로의 실행·발송 기록을 조사합니다. 이번 종료가 자체 SMTP 장애의 원인이라고 단정할 수는 없습니다.
| 받던 알림 | 이번 공지로 판단할 범위 | 다음 확인 |
|---|---|---|
| 기존 저장소 push 이메일 | 종료 대상. GitHub에서 더 이상 발송하지 않음 | Actions와 별도 메일 발송 경로 검토 |
| 직접 만든 Actions·SMTP 메일 | 기존 기능과 다른 경로 | 실행 ID·발송 제공업체·수신 기록 대조 |
| PR·이슈·보안 등 다른 GitHub 메일 | 모든 이메일이 종료됐다는 공지가 아님 | 해당 알림 종류의 설정·현재 공지 확인 |
설정 전 확인할 저장소 권한과 메일 계정 조건
알림 경로는 허용 브랜치의 push → Actions → SMTP 접수 → 수신 서버 → 받은편지함입니다. GitHub가 기존 push 메일을 다시 보내는 설정이 아니라, 운영자가 별도의 발송 계정을 준비하는 구성입니다.
- 저장소: 워크플로·스크립트를 변경할 수 있어야 하며 보호 브랜치의 검토 절차를 따릅니다. 조직의 Actions 허용 정책도 확인합니다.
- 비밀값: 저장소 Actions secrets를 만들 권한과 접근 범위를 확인합니다. 조직 secrets를 쓴다면 해당 저장소에 공개돼 있어야 합니다.
- 메일 계정: 예제는 STARTTLS 방식의 SMTP와 사용자 이름·비밀번호 인증을 사용합니다. 기본 포트는 587이며 발신 주소 사용 권한도 필요합니다.
- 시험 주소: 수신 동의를 받은 주소 한 개로 먼저 확인합니다. 여러 수신자·대량 발송은 이 예제의 범위에 넣지 않았습니다.
조직 저장소의 repository secrets 생성에는 write 접근, 개인 저장소에는 collaborator 조건이 안내돼 있습니다. 환경·조직 secrets의 관리 권한과 허용 범위는 별도이므로 설정 메뉴가 보이지 않으면 권한 담당자에게 확인하세요. Actions secrets 생성·사용 조건
SMTP 인증 방식·발송 한도·요금은 선택한 제공업체에서 확인해야 합니다. 제공업체가 발급한 SMTP 전용 자격증명 등을 사용하고, GitHub 토큰을 SMTP 비밀번호로 대신 넣지 마세요. 암시적 TLS인 465 포트, OAuth 전용 인증, 메일 제공업체 HTTP API는 아래 STARTTLS 예제와 구현이 다릅니다. Python의 SMTP·STARTTLS·SMTP_SSL 구분
1. main 브랜치 push만 감지하는 Actions 예제
워크플로·Python 스크립트·로컬 테스트 ZIP을 별도 폴더에 풉니다. 대상 저장소에 다음 두 파일을 같은 경로로 복사하고 기존 파일과 충돌하지 않는지 검토하세요.
.github/workflows/push-email.yml
scripts/send_push_email.py
워크플로는 저장소의 실제 .github/workflows 아래에 있어야 합니다. 다운로드 폴더 안에만 두면 실행되지 않습니다. 아래 내용은 ZIP에 포함한 워크플로 전체입니다.
name: Push email (SMTP)
on:
push:
branches: [main]
permissions:
contents: read
jobs:
notify:
if: ${{ github.event.deleted == false }}
runs-on: ubuntu-24.04
timeout-minutes: 3
steps:
- name: Check out notification script
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Submit push notice to SMTP
env:
SMTP_HOST: ${{ secrets.SMTP_HOST }}
SMTP_PORT: "587"
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
MAIL_FROM: ${{ secrets.MAIL_FROM }}
MAIL_TO: ${{ secrets.MAIL_TO }}
run: python3 scripts/send_push_email.py
main은 예제의 감지 대상입니다. 저장소가 master 등 다른 브랜치를 쓴다면 실제 이름으로 바꿉니다. releases/** 같은 패턴을 추가할 수도 있습니다. branches만 지정한 이 구성은 태그 push를 알리지 않습니다. 브랜치·태그 필터 규칙
github.event.deleted == false는 브랜치 삭제를 이번 메일 발송에서 제외합니다. push는 기본 브랜치에 병합하지 않은 워크플로도 실행할 수 있으므로, 시험하는 브랜치에 워크플로와 스크립트가 함께 있는지 확인하세요. workflow_dispatch의 기본 브랜치 조건과 혼동하지 않습니다. push 실행·삭제 시 SHA 동작
checkout은 공식 v7.0.1의 커밋으로 고정했고 토큰 권한은 저장소 읽기로 제한했습니다. GitHub 호스팅 ubuntu-24.04 기준 설정이며 자가 호스팅 runner의 실행 조건은 별도입니다. 사용한 공식 checkout 커밋
2. 다섯 비밀값과 SMTP 발신 조건 연결하기
저장소의 Settings → Secrets and variables → Actions → New repository secret에서 다음 이름을 만듭니다. 이름은 YAML의 secrets. 뒤와 일치해야 합니다. 이 예제는 repository secrets를 사용하며 environment secrets를 가져오는 job 구성은 포함하지 않았습니다.
| 항목 | 넣을 값 | 확인할 점 |
|---|---|---|
| SMTP_HOST | 제공업체 SMTP 호스트 | HTTP API URL과 구분 |
| SMTP_USERNAME | SMTP 인증용 사용자 이름 | 제공업체가 지정한 계정 형식 |
| SMTP_PASSWORD | SMTP 인증용 비밀값 | 현재 인증 방식·발급·만료 조건 확인 |
| MAIL_FROM | 발신 허용된 주소 하나 | 인증 계정에 해당 발신 주소 사용 권한이 있는지 |
| MAIL_TO | 수신 동의를 받은 시험 주소 하나 | 이 예제는 표시 이름 없는 ASCII 주소 한 개만 허용 |
| SMTP_PORT | YAML env의 587 | 비밀값이 아님. 제공업체의 STARTTLS 포트와 대조 |
설정하지 않은 secret 참조는 빈 문자열이 될 수 있습니다. “이름을 YAML에 적었다”와 “값이 전달됐다”를 구분하세요. 예제 스크립트는 필수값이 없으면 SMTP 연결 전에 종료 코드 2로 중단합니다. 값을 출력해 확인하기보다 이름·저장 범위·저장소 접근 정책을 대조합니다. 빈 secret과 환경변수 전달 안내
실제로 재현한 입력 오류: 다운로드 스크립트에 합성 입력을 넣어 SMTP_PASSWORD 누락과 수신 주소 두 개 입력을 각각 실행했습니다. 두 경우 모두 SMTP 전송 전에 종료 코드 2와 아래 출력을 반환했습니다.
{"stage": "configuration_error"}
이 단계라면 네트워크·스팸함 조사보다 다섯 필수 secret, 단일 수신 주소와 실행 메타데이터를 먼저 대조합니다. 같은 오류 이름이 여러 입력 문제를 포함하므로 로그만으로 누락된 항목 하나를 특정할 수는 없습니다. 값을 출력하지 않고 설정 이름·범위를 확인하세요. 실제 로컬 CLI 오류 2건과 종료 코드는 합성 이벤트를 사용한 입력 검사 기록이며 GitHub 실행·SMTP 인증·메일 수신 시험은 아닙니다.
3. 메일 본문은 push 식별 정보로 제한합니다
전체 발송 스크립트는 Python 표준 라이브러리만 사용합니다. 제목·본문에는 저장소, ref, 전체 커밋 SHA, actor, 실행 ID·attempt가 포함된 URL을 넣습니다. 커밋 메시지·코드 전문·비밀번호를 메일로 복사하지 않으며 push를 배포 성공이라고 표시하지 않습니다.
SMTP 연결의 핵심 부분은 다음과 같습니다. 인증서 검증을 적용한 STARTTLS 후 인증·제출을 수행하며, 전체 파일에는 입력 검사와 실패 처리도 들어 있습니다.
with smtplib.SMTP(host, port, timeout=30) as smtp:
smtp.ehlo()
smtp.starttls(context=ssl.create_default_context())
smtp.ehlo()
smtp.login(username, password)
refused = smtp.send_message(
message, from_addr=sender, to_addrs=[recipient]
)
예제의 smtp_accepted는 SMTP 제출 처리가 완료됐다는 자체 로그입니다. 받은편지함 도착을 확인한 값은 아닙니다. 인증 실패·수신자 거부·SMTP 오류는 성공으로 덮지 않고 0이 아닌 종료 코드로 반환합니다. 원본 예외 문구에는 주소 등이 들어갈 수 있어 로그에는 정해진 단계 이름만 남깁니다.
GitHub의 기본 변수로 SHA·실행 ID·재실행 attempt를 묶습니다. 같은 실행을 다시 시도해도 attempt가 달라질 수 있으므로 실행 ID 하나만 보고 같은 발송으로 합치지 마세요. GITHUB_SHA·GITHUB_RUN_ID·GITHUB_RUN_ATTEMPT
4. 테스트 push에서 수신까지 같은 기록으로 연결하기
별도 시험 저장소와 시험용 메일 계정으로 시작합니다. 보호 브랜치라면 승인·병합 절차를 따르고 테스트를 위해 보호 규칙을 우회하지 않습니다. 아래는 독자가 원격 환경에서 진행할 절차이며 편집부가 수신까지 완료한 기록은 아닙니다.
- 워크플로·스크립트·비밀값을 준비한 뒤 작은 변경을 허용 브랜치에 push합니다. push에 포함된 끝 커밋의 전체 SHA를 기록합니다.
- Actions에서
Push email (SMTP)실행을 찾고 SHA, run ID, attempt와 알림 step의 결과를 대조합니다. smtp_accepted가 있다면 로그의 Message-ID와 해당 시각을 메일 제공업체의 접수·전달·반송 기록에서 찾습니다. 제공업체 자체 ID는 Message-ID와 다를 수 있어 함께 기록합니다.- 수신 메일의 헤더·본문에서 Message-ID와 같은 SHA·실행 URL이 맞는지 확인합니다. 공개 캡처에서는 수신·발신 주소와 내부 저장소 정보를 가립니다.
push·발송·수신 대조 기록표는 빈 양식입니다. 알림 테스트에서는 최소한 전체 SHA → run ID·attempt → Message-ID·제공업체 ID → 수신 시각을 연결해 둡니다. 여러 커밋이 포함된 push와 한 커밋씩 보내는 알림도 구분하세요. 이번 예제는 각 워크플로 실행에서 메일 한 건을 제출합니다.
실행 기록이 없다면 스팸함보다 이벤트 조건부터 봅니다
| 관측한 상황 | 먼저 볼 항목 | 구분할 점 |
|---|---|---|
| 다른 브랜치에만 push | branches와 실제 ref | main 전용 예제라면 필터 제외는 설정대로의 동작 |
| 태그 push만 수행 | tags 조건 유무 | 이 예제는 태그 알림 미포함 |
| 경로 필터를 추가한 뒤 실행 안 됨 | branches와 paths의 동시 충족 여부 | 두 조건은 둘 다 만족해야 실행. 원본 예제에는 paths 없음 |
| 커밋에 skip 지시문을 사용 | 커밋 메시지의 [skip ci] 등 | 지원되는 지시문은 push 워크플로를 건너뛰게 할 수 있음 |
| 다른 Actions가 코드 변경을 push | 그 push의 인증이 GITHUB_TOKEN인지 | 해당 토큰이 만든 push는 재귀 실행 방지로 새 워크플로가 실행되지 않을 수 있음 |
| Actions 자체가 실행 불가 | 저장소·조직 정책과 워크플로 비활성화·구문 오류 | SMTP 접속 문제를 조사하기 전 단계 |
브랜치·경로 조건은 공식 필터 문법, 커밋 지시문은 실행 건너뛰기 안내, 자동화가 만든 push는 GITHUB_TOKEN의 재귀 실행 방지 규칙과 대조하세요.
일반적인 Actions 권한과 PR 검사 구조는 GitHub Actions 테스트 자동화 글에서 확인할 수 있습니다. 이 글의 발송 성공 기준을 PR 테스트 통과나 배포 성공 기준으로 대신 쓰지는 않습니다.
Actions는 성공했는데 메일이 없다면 어디를 볼까요?
먼저 전체 실행의 초록색 표시만 보지 말고 이 알림 job·step이 실제 실행됐는지 확인합니다. skipped·오류 무시·다른 job의 성공과 SMTP 제출 성공은 다릅니다. 이 예제에는 continue-on-error나 오류를 숨기는 셸 처리를 넣지 않았습니다.
| 확인한 마지막 단계 | 다음 조사 | 아직 입증되지 않은 것 |
|---|---|---|
| configuration_error | secret 이름·저장 범위·접근 정책, 필수 메타데이터 | SMTP 연결·발송 |
| smtp_authentication_failed | SMTP 전용 인증값·만료·현재 인증 방식 | 메시지 접수 |
| smtp_recipient_refused 또는 smtp_error | 연결·STARTTLS·발신 허용·수신 주소·제공업체 제한과 기록 | 정상 접수·수신 |
| smtp_accepted | 같은 Message-ID의 제공업체 접수·전달·반송 상태 | 수신 서버 전달·받은편지함 도착 |
| 제공업체가 전달 처리로 표시 | 수신함·스팸함·조직 격리함·메일 규칙과 수신 헤더 | 사용자가 실제 받은편지함에서 확인했는지 |
시간 초과나 연결 종료 오류는 서버가 메시지를 접수한 뒤에도 생길 수 있습니다. 무조건 재실행하면 같은 push 메일이 중복될 수 있으므로 제공업체 기록부터 확인합니다. 이 예제는 자동 재시도나 정확히 한 번 전달을 보장하는 중복 방지 저장소를 구현하지 않았습니다.
편집부가 실제 확인한 것은 로컬 모의 시험 10개입니다
2026년 10월 18일 macOS arm64·Python 3.9.6에서 다운로드 예제의 테스트를 실행했습니다. SMTP 객체를 메모리 기반 대역으로 바꾸고 socket.create_connection 호출을 막아 외부 서버로 연결하지 않았습니다. YAML도 로컬 문법 검사를 통과했습니다.
python3 -m unittest discover -s tests -v
| 확인 과제 | 이번 검증 | 남은 원격 확인 |
|---|---|---|
| 정상 접수 경로 | SMTP 대역이 접수를 반환할 때 종료 코드 0·SHA·run ID 기록 확인 | 실제 제공업체 접수와 수신 메일 |
| 인증 실패·거부·시간 초과 | 모의 예외·거부 응답에서 실패 코드 반환·비밀값 비출력 확인 | 선택한 제공업체의 실제 실패 상태 |
| TLS·메일 내용 | 인증서 검증 옵션·평문 대체 없음·코드 전문 미포함 확인 | 실제 TLS 협상과 인증 정책 |
| 필터로 미실행 | YAML의 main 조건과 공식 규칙 대조 | 실제 허용·제외 브랜치의 Actions 실행 유무 |
실제 로컬 테스트 출력과 테스트 원문을 제공합니다. 모의 시험 10개와 입력 거부 CLI 2건을 확인했습니다. 실제 GitHub runner·SMTP·받은편지함 결과는 미확인입니다.
자주 묻는 질문
모든 GitHub 이메일이 종료됐나요?
아닙니다. 이번 공지는 저장소 push 이벤트의 기존 이메일 기능 종료입니다. PR·이슈·보안 등 다른 알림까지 모두 종료됐다고 해석하면 안 됩니다. 기존 push 이메일인지 자체 발송 메일인지부터 구분하세요.
Actions는 성공했는데 메일이 없으면 어디를 보나요?
알림 step의 실제 실행과 smtp_accepted 로그를 먼저 확인합니다. 이후 Message-ID와 제공업체 기록, 반송·격리·스팸함·수신 규칙을 대조하세요. 워크플로 성공만으로 받은편지함 도착을 확인한 것은 아닙니다.
특정 브랜치의 push만 알릴 수 있나요?
push의 branches로 제한할 수 있습니다. 예제는 main만 감지합니다. 경로 조건도 추가하면 두 필터가 모두 맞아야 하며, 태그 push를 포함하려면 태그 조건도 따로 검토해야 합니다.
확인일과 다음 갱신 기준
공식 종료 시행일은 2026년 10월 15일, 이 글의 자료·로컬 예제 확인일은 10월 18일입니다. 실제 수신까지 시험한 뒤에는 동일 SHA·run ID·제공업체 접수 기록·개인정보를 가린 수신 자료를 추가합니다. Actions 이벤트·runner·checkout과 선택한 메일 제공업체의 인증 방식이 바뀌면 설정과 검증 범위도 함께 갱신합니다.
Evidence & Limitations
근거·검증 범위·업데이트 기록
확인한 근거
GitHub 저장소 push 이메일 알림 종료 공지를 기준으로 핵심 사실을 확인하고, 사실과 편집부 해석을 구분했습니다.
경험 정보와 한계
직접 사용 후기나 자체 성능 시험이 아닌 공개 원문·공식 문서 기반 분석입니다. 실제 화면과 기능은 계정·기기·배포 시점에 따라 다를 수 있습니다.
게시·수정 기록
최초 게시 2026-10-18T12:16:54+09:00 · 최종 수정 2026. 10. 18.
필수값 누락·다중 수신 주소의 실제 CLI 오류와 대조할 설정을 추가하고 중복된 검증 범위 설명을 줄였습니다.
전문 검토 영역
IT 매거진 편집부가 AI·소프트웨어·개발·모바일·보안·테크 비즈니스 관점에서 구성하고 팩트체크 데스크가 출처와 표현을 검토했습니다.
Related Articles
이 주제를 더 깊게 읽어보세요
현재 기사와 연결되는 배경·기술·시장 분석을 골라 바로 이동할 수 있습니다.


