S2 · 사내한
회신 미결 메일은 "PC에서 매시 추출해 칸반 API로 푸시"하는 방식이 가장 빠르고, 외부 저장 범위만 먼저 정하면 된다
최근 14일 후보 27건(약 2건/일) · Aside · 2026-10-28 기준 · 범위: Outlook 로컬(읽기 전용) → cands-todo-kanban
총괄 결론 — 칸반 서버(Cloudflare)는 로컬 Outlook에 닿지 못하므로, PC 작업 스케줄러가 매시 PowerShell(COM, 읽기 전용)로 미결 메일을 뽑아 POST /api/ingest로 올리는 안 A를 권장한다. 플래그 사용이 0건이라 "회신 흔적 + 요청 신호 점수"로 판정하고, 칸반의 "회신 불필요" 버튼으로 사용자가 보정한다. 먼저 결정할 1가지: 메일 제목·발신자 메타를 외부 클라우드에 저장해도 되는가.
1. 실측 — 14일간 To 직접수신 63건 중 회신 흔적이 없는 후보는 27건이다
| 항목(최근 14일) | 건수 |
| 수신 전체(받은편지함+하위폴더) | 84 |
| To 직접수신 | 63 |
| 회신 표시(LastVerb 102/103) | 26 |
| 동일 대화 후속 발신 | 29 |
| 플래그 지정 | 0 |
| noreply·알림성(제외) | 7 |
| 미결 후보 | 27 |
| 후보 폴더 | 건수 |
| AI | 10 |
| 받은 편지함 | 4 |
| 노무 / 급여 | 3 / 3 |
| 부서간 요청사항 | 2 |
| 경영지원 / 디자인 용역 | 2 / 2 |
| 정읍공장 | 1 |
후보 수는 "회신 흔적 없음"만 본 상한치다. 실제 회신 필요 여부(제목·본문)는 열람하지 않았다. 받은편지함이 비어 있고 하위 폴더로 분류되므로 전 폴더 스캔이 필수다.
2. 구현 방식은 PC 푸시(안 A)가 즉시 가능하고 본문 반출이 없다
| 안 | 방식 | 장점 | 한계 | 판단 |
| A | PC 스케줄러 → PowerShell(COM) → /api/ingest | 즉시 가능, 본문 반출 없음, 기존 스크립트 재사용 | PC 켜짐 + 클래식 Outlook 실행 필요 | 채택 |
| B | Microsoft Graph API 서버 조회 | PC 무관, 24시간 | Azure 앱 등록·관리자 동의, 메일이 클라우드 경유 | 2단계 |
| C | Power Automate 규칙 | 코드 최소 | 회신 여부 판정 약함, 정책 확인 필요 | 비권장 |
3. "회신 필요"는 6개 규칙으로 판정한다
| # | 규칙 | 내용 |
| 1 | 대상 | 최근 N일(기본 14), 전 폴더, 내가 To인 메일만(CC·숨은참조 제외) |
| 2 | 제외 | noreply·알림성, 내가 보낸 메일, 삭제·정크, 사용자 제외 발신자/도메인 |
| 3 | 회신 완료 | LastVerb 102/103, 또는 보낸편지함 동일 ConversationID에 수신 이후 발신(옵션: 전달 104) |
| 4 | 1대화 1카드 | ConversationID 기준, 최신 수신 메일 대표 |
| 5 | 우선순위 점수 | 요청 표현(물음표·"회신/검토/확인 부탁"·"까지") + 상급자·핵심 거래처 + 경과일 + 본문 기한. 로컬 계산, 본문 미전송 |
| 6 | 재오픈 | Done 대화에 상대 답신이 오면 Doing 복귀. "회신 불필요"는 같은 발신자 새 메일 전까지 유지 |
외부 저장은 메타데이터로 한정하고 민감 폴더는 마스킹해야 약 2일 안에 운영할 수 있다
아키텍처 · 보안 · 단계별 계획 · 미확인 사항 · 결정 요청
4. 매시 :05에 PC가 푸시하고 서버는 기존 병합 로직을 재사용한다
[PC] 작업 스케줄러(매시 :05, cands 동기화 이후)
└ outlook_pending.ps1 (COM, 읽기 전용) → JSON {asOf, items[], resolved[]}
── HTTPS + Bearer INGEST_TOKEN ──▶
[Cloudflare Pages] POST /api/ingest → shared/sync.js 병합 로직 공용화 → KV(board-v1)
[화면] Doing 카드 "Outlook" 태그 · 대기일 뱃지 · "회신 불필요" 버튼
- 카드: id=outlook:<ConversationID>, title="[회신] 제목", meta={발신자, 수신시각, 폴더, 대기일, 점수, 사유}, url=outlook:<EntryID>(이 PC에서만 열림, 동작 미검증)
- 자동 Done: 다음 푸시의 resolved[]에 회신 감지 대화가 오면 Done. 사용자가 직접 옮긴 카드는 기존 locked 규칙 유지
- 인증 분리: ingest 전용 INGEST_TOKEN(쿠키 로그인과 별개), PC에는 사용자 전용 파일/자격 증명에만 보관, 1회 200건 상한
- 누락 대응: PC 꺼짐 시 다음 실행이 14일 전체를 재계산(멱등). "Outlook 마지막 반영 시각" 표시, 2시간 초과 시 경고. KV 쓰기 ≈ 48회/일로 무료 한도(1,000/일) 이내
5. 개인정보 리스크는 전송 필드 최소화와 민감 폴더 마스킹으로 줄인다
| 항목 | 설계 | 비고 |
| 전송 필드 | 제목, 발신자 표시명, 수신시각, 폴더명, 점수·사유만. 본문·첨부·수신자 목록 미전송. 완료 30일 후 KV에서 삭제 | 본문은 로컬 계산에만 사용 |
| 민감 폴더 | 급여·노무·변호사 검토·산재·퇴직 등은 제목을 "[노무] 회신 필요 메일"로 마스킹(발신자 이니셜) 또는 제외 | 기본=마스킹, 확정 필요 |
| 접근 통제 | 현재 단일 비밀번호 → 메일 메타 탑재 전 Cloudflare Access(이메일 OTP) 적용 권장 | 확인 필요 |
| 등급 | cands 데이터는 외부 반출 상한 S1로 승인된 범위. Outlook 메타는 그 범위 밖이라 별도 판단 필요 | 결정 1 |
6. 단계별로 P0 검수 후 진행하며 총 약 2일 공수다
| 단계 | 내용 | 수용 기준 | 공수 |
| P0 | outlook_pending.ps1 로컬 dry-run(전송 없음) | 14일 후보를 눈으로 검수, 오탐 30% 이하 | 0.5일 |
| P1 | /api/ingest + 병합 리팩터링 + UI | 푸시 시 Doing 생성, 회신 후 다음 푸시에 Done | 1일 |
| P2 | 작업 스케줄러 매시 등록 + 경고 표시 | 24시간 무인 운영, 누락 시 경고 | 0.5일 |
| P3 | "회신 불필요" 학습, Graph(안 B) 검토 | 오탐 20% 이하 | 별도 |
7. 확인하지 못한 것과 사용자 결정 3건
확인 못함
후보 27건의 실제 회신 필요 여부(제목·본문 미열람) · 점수식 정확도 · 14일 전 폴더 스캔 소요시간 · outlook: 링크 동작 · Outlook 미실행 시 스케줄러 동작 · Graph 관리자 동의 가능 여부
결정 필요
① 메일 메타의 Cloudflare 저장 허용 및 민감 폴더 마스킹/제외
② 판정 기간 14일 vs 7일, 전달(104)을 완료로 볼지
③ 안 A(상시 켜진 PC) 진행 vs 처음부터 Graph 협의
💡 추천 프롬프트
- "outlook_pending.ps1 P0를 구현해서 최근 14일 회신 미결 후보를 dry-run으로 뽑고, 제목은 마스킹한 표(발신자 이니셜·폴더·대기일·점수·사유)로 보여줘. 전송은 하지 마."
- "cands-todo-kanban에 /api/ingest와 Outlook 카드 UI(대기일 뱃지, 회신 불필요 버튼)를 추가하고, Cloudflare Access 적용 절차도 정리해줘."