gmail-summary 스킬로 생성된 오늘 날짜의 메일 요약 보고서를 읽어 Slack #slack-integration-test 채널에 전송한다.

Slack Gmail Report

gmail-summary 스킬이 생성한 메일 요약 보고서를 Slack 채널에 전송하는 스킬이다.

Parameters

ParameterRequiredDescriptionDefault
(없음)-오늘 날짜의 보고서를 자동으로 찾는다-

Prerequisites

  • .env 파일에 다음 환경변수가 설정되어 있어야 한다:
    • SLACK_BOT_TOKEN: Slack Bot User OAuth Token (xoxb-로 시작)
    • SLACK_CHANNEL_ID: 전송 대상 채널 ID (현재 #slack-integration-test)
  • Slack App에 chat:write scope가 부여되어 있어야 한다
  • 해당 채널에 봇이 초대되어 있어야 한다
  • general-docs/gmail-summary/ops/ 에 오늘 날짜의 보고서 파일이 존재해야 한다

Process

Step 1: 오늘 날짜 확인 및 보고서 파일 찾기

  1. Bash로 한국 시간(KST) 기준 오늘 날짜를 구한다:
    1TZ=Asia/Seoul date +%Y-%m-%d
  2. general-docs/gmail-summary/ops/YYYY-MM-DD.md 파일이 존재하는지 확인한다
  3. 파일이 없으면 "오늘 날짜의 메일 요약 보고서가 없습니다. /gmail-summary를 먼저 실행해주세요."를 출력하고 종료한다

Step 2: 보고서 파일 읽기

  1. Read 도구로 보고서 파일을 읽는다
  2. 보고서 내용에서 다음 정보를 추출한다:
    • 요약 기간 (시작일 ~ 종료일)
    • 총 메일 건수
    • 중요도별 건수 (🔴 상, 🟡 중, 🟢 하)
    • 각 날짜별 메일 목록

Step 3: 전체 메일에 일련번호 부여

보고서 파일의 모든 메일을 중요도순(🔴→🟡→🟢), 카테고리순, 날짜 오름차순으로 나열하여 **전체 일련번호 [1], [2], ...[N]**을 부여한다. 이 번호는 요약 메시지와 스레드 댓글에서 동일하게 사용되어, 요약 항목에서 원문 제목을 역추적할 수 있게 한다.

Step 4: Slack 요약 메시지 포맷 변환

마크다운 보고서를 Slack Block Kit 형식으로 변환한다. 날짜별이 아닌 중요도별로 그룹핑하여 전송한다.

각 요약 항목 뒤에 Step 3에서 부여한 일련번호를 [N] 형식으로 붙인다. 여러 메일을 하나로 요약한 경우 해당하는 모든 번호를 붙인다 (예: [3][4][5]).

Slack 메시지 구조:

1{
2  "channel": "SLACK_CHANNEL_ID",
3  "blocks": [
4    {
5      "type": "header",
6      "text": {
7        "type": "plain_text",
8        "text": "📬 메일 요약: YYYY-MM-DD ~ YYYY-MM-DD"
9      }
10    },
11    {
12      "type": "section",
13      "text": {
14        "type": "mrkdwn",
15        "text": "요약 기간: *N일* | 총 *N건* 수신\n🔴 상 N건 | 🟡 중 N건 | 🟢 하 N건"
16      }
17    },
18    {
19      "type": "divider"
20    },
21    {
22      "type": "section",
23      "text": {
24        "type": "mrkdwn",
25        "text": "🔴 *즉시 대응 필요*\n\n*💳 결제 오류*\n• Anthropic 결제 실패 4회 [1][2][3][4]\n\n*🔄 App Store 리뷰*\n• 쏘카인드 iOS 앱 1건 승인 완료 [5], 2건 이슈 [6][7]"
26      }
27    },
28    ...
29  ]
30}

변환 규칙:

  • 보고서의 중요도별 > 카테고리별 메일을 추출하여 요약한다
  • 각 요약 항목 뒤에 해당 메일의 일련번호를 [N] 형식으로 붙인다
  • 중요도별 섹션 내에서 카테고리 소제목으로 그룹핑한다
  • 해당 중요도의 메일이 0건이면 해당 중요도 블록 전체를 생략한다
  • Slack Block Kit의 text 필드는 최대 3000자 제한이 있으므로, 초과 시 블록을 분리한다

Step 5: 환경변수 확인

  1. Bash로 .env 파일을 source하여 환경변수를 로드한다:
    1source /Users/miyeon/Workspaces/1-work/sokind-knowledge-vault/.env
  2. SLACK_BOT_TOKENSLACK_CHANNEL_ID가 설정되어 있는지 확인한다
  3. 어느 하나라도 없으면 ".env 파일에 SLACK_BOT_TOKEN 또는 SLACK_CHANNEL_ID가 설정되어 있지 않습니다."를 출력하고 종료한다

Step 6: Slack 요약 메시지 전송

  1. JSON 페이로드를 /tmp/slack-gmail-report.json 임시 파일로 작성한다 (셸 이스케이프 문제 방지)
  2. Bash로 curl을 사용하여 Slack API에 POST 요청을 보낸다:
    1source .env && curl -s -X POST https://slack.com/api/chat.postMessage \
    2  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
    3  -H "Content-Type: application/json" \
    4  -d @/tmp/slack-gmail-report.json
  3. 응답의 ok 필드를 확인한다:
    • true: 응답에서 ts 값을 추출하여 Step 6에서 스레드 댓글에 사용한다
    • false: 에러 메시지 출력 (error 필드 내용 포함) 후 종료한다

Step 7: 스레드 댓글로 이메일 원문 제목 전송

요약 메시지만으로는 나중에 이메일을 검색할 수 없으므로, 스레드 댓글로 이메일 제목 원문 전체 목록을 전송한다. 이 목록은 카테고리/중요도 그룹핑 없이, Step 3에서 부여한 일련번호 순서대로 플랫하게 나열한다.

  1. Step 3의 일련번호 순서대로, 각 메일의 [번호] 제목 원문 발신자이메일 을 나열한다
  2. Step 6에서 받은 ts 값을 thread_ts로 지정하여 스레드 댓글로 전송한다:
    1source .env && curl -s -X POST https://slack.com/api/chat.postMessage \
    2  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
    3  -H "Content-Type: application/json" \
    4  -d @/tmp/slack-gmail-report-thread.json
  3. 응답의 ok 필드를 확인한다

스레드 댓글 메시지 구조:

1{
2  "channel": "SLACK_CHANNEL_ID",
3  "thread_ts": "부모 메시지의 ts 값",
4  "blocks": [
5    {
6      "type": "header",
7      "text": {
8        "type": "plain_text",
9        "text": "📋 이메일 제목 원문 목록"
10      }
11    },
12    {
13      "type": "section",
14      "text": {
15        "type": "mrkdwn",
16        "text": "[1] $200.00 payment to Anthropic, PBC was unsuccessful `failed-payments@mail.anthropic.com`\n[2] $200.00 payment to Anthropic, PBC was unsuccessful again `failed-payments@mail.anthropic.com`\n[3] There's an issue with your 쏘카인드 - AI 화법 직무 교육 서비스 (iOS) submission. `no_reply@email.apple.com`\n..."
17      }
18    },
19    ...
20  ]
21}

변환 규칙:

  • 카테고리/중요도 그룹핑 없이 일련번호 순서대로 플랫하게 나열한다
  • 각 항목 형식: [N] 이메일 제목 원문 \발신자이메일``
  • 제목과 발신자를 원문 그대로 추출한다 (요약/축약 금지)
  • Slack Block Kit text 필드 3000자 제한에 주의하여, 초과 시 블록을 분리한다

Step 8: 임시 파일 정리

전송 완료 후 /tmp/slack-gmail-report.json/tmp/slack-gmail-report-thread.json 파일을 삭제한다.

Important Notes

  • Bot Token은 절대로 코드나 로그에 노출하지 않는다 (.env 파일에서 source로만 참조)
  • Slack Block Kit의 블록 수 제한은 50개이다. 날짜가 많아 50개를 초과할 경우 여러 메시지로 분할 전송한다
  • section 블록의 text 필드는 최대 3000자이다. 초과 시 블록을 분리한다
  • 전송 실패 시 재시도하지 않고, 에러 내용을 사용자에게 출력한다
  • 이 스킬은 보고서를 읽기만 하며, 보고서 파일을 수정하거나 삭제하지 않는다

Example Usage

gmail-summary 실행 후 바로 전송

1/gmail-summary
2/slack-gmail-report

단독 실행 (이미 보고서가 생성된 경우)

1/slack-gmail-report

Quality Checklist

  • 오늘 날짜의 보고서 파일을 정확히 찾았는가
  • .env에서 SLACK_BOT_TOKENSLACK_CHANNEL_ID를 확인했는가
  • 마크다운 → Slack Block Kit 변환이 올바른가
  • Slack 메시지에 모든 날짜와 메일이 빠짐없이 포함되었는가
  • Slack API 응답의 ok 필드를 확인했는가
  • 임시 파일을 정리했는가
  • Bot Token이 로그나 출력에 노출되지 않았는가