Skip to main content
Glama
Hoodess

naver-mail-mcp-basic

by Hoodess

네이버 메일 MCP 서버 — 기본형 (naver-mail-mcp-basic)

네이버 메일 조회·검색·첨부 정리·발송준비를 하는 MCP 서버입니다. Claude Desktop 에 stdio MCP 로 붙여서 씁니다 (Claude Code / Cowork 도 동일하게 동작).

이 레포는 원본 naver-mail-mcp 에서 메일 수발신 기능만 분리한 기본형(수업용) 입니다. 원본은 이후 사건별 자동 분류 파이프라인·수발신 대장·문서 도구가 추가된 확장판으로 발전했습니다. 두 서버는 이름·Claude Desktop 등록 키·상태 폴더(~/.naver-mail-mcp-basic)가 분리되어 같은 컴퓨터에 함께 설치해도 서로 간섭하지 않습니다.

🤖 AI 에이전트에게: 사용자가 이 레포 주소를 주며 "이 MCP 설치해줘"라고 요청했다면 5절의 방법 C 를 따르세요. 계정 정보(비밀번호)는 채팅으로 묻지도, 대신 입력하지도 마세요.

👉 컴퓨터가 익숙하지 않은 분은 사용설명서.md 를 보세요. 전문용어 없이 설치부터 사용까지 따라 할 수 있게 쓴 문서입니다. 이 README 는 개발/관리자용입니다.

1차 목표는 첨부 다운로드 + 폴더 정리입니다. 메일 발송은 절대 자동으로 하지 않습니다. 발송대기 폴더에 준비만 하고, 사람이 확인 후 직접 보냅니다.


목차

  1. 무엇을 할 수 있나

  2. 네이버 준비 작업 (IMAP 사용 설정 + 앱 비밀번호 발급)

  3. 설치

  4. 설정

  5. Claude 에 등록하기

  6. 수동 테스트 방법

  7. MCP 툴 레퍼런스

  8. 변호사 사무실 시나리오 예시 프롬프트

  9. 보안 설계

  10. 설계 가정 및 알려진 제약

  11. 문제 해결

  12. 프로젝트 구조


1. 무엇을 할 수 있나

기능

읽지 않은 / 새로 온 메일 목록 (첨부 파일명 포함)

list_unread_mails

메일 본문·헤더·첨부 메타데이터 조회

get_mail

첨부파일을 로컬 디스크에 저장 + 확장자별 분류 + 이름 규칙 적용

download_attachments

새 메일 확인 → 첨부 다운로드 → 폴더 정리 → rename 을 한 번에 (증분 처리)

process_new_mails_with_attachments

발신자 / 제목 / 날짜 / 첨부 유무·확장자로 검색

search_mails

발송 준비 (발송대기 폴더 또는 임시보관함 초안) — 발송 안 함

save_draft_or_prepare_send

발송대기 목록 확인

list_prepared_mails

메일함 목록 / 현재 설정 확인

list_mailboxes

기본 분류 폴더:

<DOWNLOAD_BASE_DIR>/
├── pdf/
├── hwp/
├── hwpx/
├── docx/      ← doc, docx
├── xlsx/      ← xls, xlsx, xlsm, csv
├── images/    ← jpg, jpeg, png, gif, bmp, webp, heic, tif …
├── etc/       ← 그 외 전부 (zip, pptx, html …)
└── _발송대기/  ← save_draft_or_prepare_send 결과

2. 네이버 준비 작업

⚠️ 로그인 비밀번호로는 절대 접속되지 않습니다. 반드시 아래 두 가지를 먼저 하세요.

2-1. IMAP/SMTP 사용 설정

  1. PC 웹브라우저로 네이버 메일 접속 후 로그인

  2. 왼쪽 아래 환경설정 (톱니바퀴) 클릭

  3. POP3/IMAP 설정 탭 → IMAP/SMTP 설정 탭 선택

  4. IMAP/SMTP 사용사용함 으로 변경

  5. 맨 아래 확인 버튼 클릭 (이걸 안 누르면 저장되지 않습니다)

"IMAP 동기화 메일 제한" 값도 함께 보입니다. 기본 250통이면 오래된 메일이 IMAP 으로 안 보일 수 있으니 사무실 상황에 맞게 500~1000통으로 올려두는 것을 권장합니다.

2-2. 애플리케이션 비밀번호 발급

2단계 인증을 쓰든 안 쓰든, 외부 메일 프로그램용 비밀번호가 따로 필요합니다.

  1. 네이버 내정보보안 설정

  2. 2단계 인증 메뉴로 이동 (꺼져 있으면 먼저 켭니다)

  3. 애플리케이션 비밀번호 관리 클릭

  4. 애플리케이션 추가 → 이름을 naver-mail-mcp-basic 등으로 입력

  5. 생성된 12자리 비밀번호를 복사 (창을 닫으면 다시 볼 수 없습니다)

이 12자리가 아래 설정의 NAVER_APP_PASSWORD 입니다.

2-3. 접속 정보 (참고)

항목

IMAP 서버

imap.naver.com

IMAP 포트

993 (SSL/TLS 필수)

SMTP 서버

smtp.naver.com

SMTP 포트

587 (STARTTLS) 또는 465 (SSL)

로그인 ID

메일주소의 @ 앞부분 (예: hong@naver.comhong)

이 값들은 코드에 하드코딩되어 있지 않습니다. 전부 환경변수 기본값이며 필요하면 바꿀 수 있습니다.


3. 설치

요구사항: Node.js 20 이상

cd /경로/naver-mail-mcp-basic
npm install
npm run build

빌드 결과는 dist/index.js 에 생성되며, 이 파일이 MCP 서버 진입점입니다.


4. 설정

계정 정보를 주는 방법은 두 가지입니다. 둘 중 하나만 하면 됩니다.

방법 A — .env 파일 (간단)

cp .env.example .env

.env 를 열어 최소 세 줄만 채우면 됩니다.

NAVER_EMAIL=hong@naver.com
NAVER_APP_PASSWORD=여기에_12자리_앱비밀번호
DOWNLOAD_BASE_DIR=/Users/내이름/사건첨부

.env.gitignore 에 들어 있어 커밋되지 않습니다. 파일 권한은 chmod 600 .env 로 조여두세요.

방법 B — 암호화 저장소 (권장, 평문 비밀번호 없음)

npm run setup
  • ID 와 앱 비밀번호를 물어봅니다. 비밀번호는 화면에 표시되지 않습니다.

  • ~/.naver-mail-mcp-basic/credentials.encAES-256-GCM 으로 암호화 저장됩니다.

  • 이 경우 .env 에서 NAVER_APP_PASSWORD 줄은 지워도 됩니다.

암호화 키는 다음 순서로 정해집니다.

  1. 환경변수 NAVER_MCP_MASTER_KEY 가 있으면 그 값에서 scrypt 로 유도 (가장 안전, 키 파일이 디스크에 남지 않음)

  2. 없으면 ~/.naver-mail-mcp-basic/master.key (32바이트 랜덤, 권한 0600)를 자동 생성해 사용

2번 방식은 "노트북을 통째로 가져간 공격자"까지 막지는 못합니다(키가 암호문 옆에 있음). 다만 백업·동기화·실수로 평문 비밀번호가 유출되는 상황은 확실히 막아줍니다. 더 강한 보호가 필요하면 1번 방식을 쓰고 NAVER_MCP_MASTER_KEY 를 macOS 키체인에서 주입하세요.

접속 확인

npm run doctor

설정 요약 → IMAP 접속 → 메일함 목록 → 읽지 않은 메일 수 → SMTP 인증까지 확인합니다. 어떤 출력에도 비밀번호는 나오지 않습니다.


5. Claude 에 등록하기

방법 A — 자동 설치 (macOS, 권장)

프로젝트 폴더의 설치.command 를 더블클릭하면 아래를 한 번에 처리합니다.

  1. Node.js 확인 → 의존성 설치 → 빌드

  2. 네이버 계정 입력 (비밀번호는 화면에 * 표시, AES-256-GCM 암호화 저장)

  3. 첨부 저장 폴더 지정 → .env 갱신 (비밀번호는 .env 에 쓰지 않음)

  4. Claude Desktop 설정 파일에 자동 등록 (기존 설정은 타임스탬프 백업 후 병합)

  5. IMAP/SMTP 실접속 진단

터미널에서 직접 실행하려면:

bash 설치.command

계정/폴더만 다시 잡고 싶으면 (빌드 생략):

npm run install-desktop

방법 B — Claude Desktop 수동 등록

설정 파일에 아래를 추가합니다.

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "naver-mail-mcp-basic": {
      "command": "/절대경로/node",
      "args": ["/절대경로/naver-mail-mcp-basic/dist/index.js"],
      "env": {
        "NAVER_MAIL_MCP_ENV": "/절대경로/naver-mail-mcp-basic/.env"
      }
    }
  }
}

⚠️ command 에는 node 의 절대경로를 쓰세요 (which node 로 확인). Claude Desktop 은 셸 PATH 없이 실행되기 때문에 그냥 "node" 라고 쓰면 nvm/Homebrew 로 설치한 node 를 찾지 못하는 경우가 많습니다. 자동 설치(방법 A)는 이를 알아서 처리합니다.

저장 후 Claude Desktop 을 완전히 종료(메뉴 → Quit)했다가 다시 실행하세요.

MCP 서버는 임의의 작업 디렉터리에서 실행되므로 NAVER_MAIL_MCP_ENV.env 절대경로를 지정하는 것이 가장 확실합니다. (지정하지 않으면 실행 디렉터리 → 패키지 루트 순으로 .env 를 찾습니다.)

방법 C — AI 에이전트(코워크 등)에게 맡기기

사용자가 이 레포 주소와 함께 설치를 요청했다면, 에이전트는 아래 순서대로 진행하세요. 터미널 대화형 절차(설치.command, npm run setup)는 쓰지 않습니다 — 계정 입력은 사람이 파일을 직접 열어서 합니다.

  1. 받기 — 사용자가 폴더를 지정하지 않았으면 홈 폴더 아래에 클론합니다: git clone https://github.com/Hoodess/naver-mail-mcp-basic.git (git 이 없으면 GitHub 에서 zip 을 내려받아 풉니다.)

  2. 빌드 — 레포 폴더에서 npm installnpm run build. Node.js 가 없거나 20 미만이면 여기서 중단하고 https://nodejs.org 의 LTS 설치를 안내하세요.

  3. .env 만들기.env.example 을 복사해 .env 를 만듭니다.

    • NAVER_EMAILNAVER_APP_PASSWORD자리표시자 그대로 둡니다. ⚠️ 이 두 값을 채팅으로 묻거나 대신 채우지 마세요 — 비밀번호는 사람이 직접 넣습니다.

    • DOWNLOAD_BASE_DIR 은 비밀이 아니므로, 사용자에게 원하는 저장 폴더를 물어 채우거나 홈 폴더 아래 NaverMailMCP/attachments 로 정해 채우세요 (폴더도 만들어 두세요).

  4. Claude Desktop 등록 — 방법 B 의 JSON 형식대로 claude_desktop_config.json 에 추가합니다. command 는 node 절대경로, NAVER_MAIL_MCP_ENV 는 방금 만든 .env 절대경로. 기존 설정 파일이 있으면 백업해 두고 병합하세요.

  5. 사용자 안내 — 마지막에 두 가지를 안내하고 마칩니다:

    • "{.env 절대경로} 파일을 텍스트 편집기(메모장 등)로 열어 NAVER_EMAILNAVER_APP_PASSWORD 를 본인 것으로 바꿔 저장하세요. 앱 비밀번호 발급 방법은 README 2절을 보세요."

    • "저장했으면 Claude Desktop 을 완전히 종료(메뉴 → Quit)했다가 다시 실행하세요."

  6. (선택) 확인 — 사용자가 입력을 마쳤다고 하면 npm run doctor 로 접속을 확인하세요. 어떤 출력에도 비밀번호는 나오지 않습니다.

(참고) Claude Code CLI

claude mcp add naver-mail-mcp-basic -- node /절대경로/naver-mail-mcp-basic/dist/index.js

6. 수동 테스트 방법

6-1. 명령줄에서 (Claude 없이)

npm run doctor
npm run smoke

scripts/smoke-test.mjs 는 실제 MCP 서버를 stdio 로 띄우고 JSON-RPC 로 전체 흐름을 검증합니다. (툴 목록 → 읽지 않은 메일 → 검색 → 본문 조회 → 첨부 다운로드 → 중복 방지 → 경로 이탈 차단 → 증분 워크플로우 → 발송 준비). 저장 폴더/상태를 임시 디렉터리에 격리해 실행하므로 여러 번 돌려도 실제 환경을 건드리지 않습니다.

첨부 유무 필터가 걸린 조회는 메일함 전체의 구조를 훑어야 해서 계정에 따라 수 분이 걸릴 수 있습니다. 자세한 이유는 10. 설계 가정 및 알려진 제약 참고.

6-2. Claude 대화창에서 (권장 순서)

① 읽지 않은 메일 확인

네이버 메일에서 읽지 않은 메일 중 첨부 있는 것만 10통 보여줘

list_unread_mails 가 호출되고 각 메일의 uid, 제목, 발신자, 첨부 파일명이 나옵니다.

② 그중 하나의 첨부 내려받기

그중 uid 12345 메일 첨부를 받아서 종류별로 정리해줘

download_attachments 가 호출되고 저장된 파일의 절대경로 목록이 반환됩니다. Finder/탐색기에서 DOWNLOAD_BASE_DIR 아래에 pdf/, hwp/ 같은 폴더가 생겼는지 확인하세요.

③ 같은 명령을 한 번 더 실행

동일 파일은 내용 해시가 같으므로 중복 건너뜀 으로 표시되고 _1, _2 사본이 생기지 않아야 정상입니다.


7. MCP 툴 레퍼런스

list_unread_mails

읽지 않은 메일 목록. 읽음 처리하지 않습니다.

파라미터

타입

기본값

설명

limit

number

30

최대 개수

since_date

string

today / yesterday / 7d / 2026-08-01

mailbox

string

INBOX

한글 별칭(보낸메일함, 임시보관함 등) 인식

only_with_attachments

boolean

false

첨부 있는 메일만

include_inline_images

boolean

false

서명 로고 등 인라인 이미지도 첨부로 셀지

scan_limit

number

200

첨부 필터 시 훑어볼 최대 메일 수

반환: 제목, 발신자, 수신일, uid, messageId, 첨부 여부, 첨부 파일명 목록, 크기


get_mail

파라미터

타입

기본값

설명

uid

number

uid 또는 message_id 중 하나 필수

message_id

string

RFC822 Message-ID

mailbox

string

INBOX

max_body_chars

number

20000

본문 최대 길이

include_html

boolean

false

원본 HTML 도 반환

반환: 본문(텍스트, HTML 은 자동으로 평문 변환), 헤더, 첨부 메타데이터(파일명/크기/MIME 타입/파트번호)


download_attachments

파라미터

타입

기본값

설명

uids

number[]

uids 또는 message_ids 중 하나 필수

message_ids

string[]

느리므로 uids 권장

mailbox

string

INBOX

target_dir

string

DOWNLOAD_BASE_DIR

기준 폴더 기준 상대경로 권장. 밖으로 나가면 거부

organize_by_type

boolean

true

확장자별 하위 폴더 생성

rename_template

string

아래 토큰 표 참고

extensions

string[]

예: ["pdf","hwp"]

include_inline_images

boolean

false

on_duplicate

rename|skip|overwrite

rename

group_by_mail

boolean

false

메일별 하위 폴더 한 단계 더

rename_template 토큰

토큰

예시 값

{date}

2026-08-03

{date_compact}

20260803

{time}

1430

{datetime}

2026-08-03_1430

{from}

김변호사 (표시명, 없으면 메일 ID)

{from_email}

lawyer@example.com

{subject}

제목 (60자로 자름)

{original}

원본 파일명 (소장.pdf)

{basename}

확장자 뺀 원본 이름 (소장)

{ext}

pdf

{uid} / {index} / {mailbox}

UID / 메일 내 첨부 순번 / 메일함

예: "{date}_{from}_{original}"2026-08-03_김변호사_소장.pdf 템플릿에 확장자가 없으면 원본 확장자를 자동으로 붙입니다.

반환: savedPaths (저장된 절대경로 배열), 메일별 상세 결과, 분류별 개수, 합계


process_new_mails_with_attachments (핵심 워크플로우)

"새 메일 확인 → 첨부 다운로드 → 종류별 정리 → rename" 을 한 번에 수행합니다.

파라미터

타입

기본값

설명

since

string

last_run

last_run / today / yesterday / 7d / 2026-08-01

base_dir

string

DOWNLOAD_BASE_DIR

저장 폴더

only_with_attachments

boolean

true

mark_as_seen

boolean

false

로펌 기본값: 읽음 처리 안 함

mailbox

string

INBOX

organize_by_type

boolean

true

rename_template

string

extensions

string[]

group_by_mail

boolean

false

unread_only

boolean

false

limit

number

50

한 번에 처리할 최대 메일 수

dry_run

boolean

false

저장하지 않고 대상만 보고

update_state

boolean

true

last_run 커서 갱신 여부

증분 처리 방식

  • 메일함별 마지막 처리 UID 를 ~/.naver-mail-mcp-basic/state.json 에 저장합니다.

  • 날짜가 아니라 UID 기준이라, 같은 날 여러 번 실행해도 중복 처리되지 않습니다.

  • 오래된 메일부터 처리하고 처리한 것까지만 커서를 전진시키므로 limit 에 걸려도 누락이 없습니다. (남은 메일은 같은 툴을 한 번 더 실행하면 이어서 처리됩니다)

  • 서버의 UIDVALIDITY 가 바뀌면 자동으로 상태를 초기화하고 경고를 반환합니다.

  • 첫 실행에는 기록이 없으므로 안전을 위해 "오늘"부터 시작합니다. 과거 메일까지 훑으려면 since: "30d" 처럼 명시하세요.


search_mails

파라미터

설명

from / to / subject

부분 일치 (한글 가능)

body

본문 키워드 (한글은 네이버 서버가 지원하지 않을 수 있음)

since / before

날짜 범위

has_attachment

true = 첨부 있는 것만

attachment_extensions

예: ["pdf","hwp"]

unread_only / mailbox / limit / scan_limit

한글 키워드는 서버 SEARCH 가 실패해도 날짜·상태 조건으로 좁힌 뒤 클라이언트에서 필터링해 결과를 냅니다.


save_draft_or_prepare_send (발송 준비 — 발송 안 함)

파라미터

타입

설명

to / cc / bcc

string[]

받는사람 필수

subject

string

제목

body_text / body_html

string

본문

attachment_paths

string[]

첨부할 로컬 파일 경로

mode

prepare|imap_draft

기본 prepare

note

string

담당자 확인용 메모

mode: "prepare" (기본) 이면 OUTBOX_DIR 아래에 이런 폴더를 만듭니다.

_발송대기/2026-08-03_143012_자료송부의건/
├── meta.json        ← 수신자·제목·첨부 목록·상태(대기중)
├── body.txt
├── message.eml      ← 메일 클라이언트로 바로 열 수 있는 완성된 메일
└── attachments/     ← 첨부 사본

mode: "imap_draft" 이고 ALLOW_IMAP_DRAFT=true 이면 네이버 임시보관함에도 초안으로 올립니다.

어떤 경우에도 이 툴은 메일을 발송하지 않습니다. 실제 발송은 사람이 직접:

npm run send-prepared -- "/경로/_발송대기/2026-08-03_143012_자료송부의건" --confirm

--confirm 없이 실행하면 내용만 보여주고 종료합니다.

첨부로 붙일 수 있는 파일은 기본적으로 DOWNLOAD_BASE_DIROUTBOX_DIR 안쪽으로 제한됩니다. 사건기록 폴더 등을 추가하려면 .envATTACH_ALLOWED_ROOTS 를 설정하세요.


8. 변호사 사무실 시나리오 예시 프롬프트

시나리오 1 — "오늘 온 네이버 메일 첨부파일 전부 받아서 종류별로 정리해줘"

오늘 온 네이버 메일 첨부파일 전부 받아서 종류별로 정리해줘. 저장은 2026-08 폴더에 하고, 파일명은 날짜_보낸사람_원본파일명 형식으로 해줘. 읽음 처리는 하지 마.

Claude 가 호출하는 것:

{
  "tool": "process_new_mails_with_attachments",
  "arguments": {
    "since": "today",
    "base_dir": "2026-08",
    "organize_by_type": true,
    "rename_template": "{date}_{from}_{original}",
    "mark_as_seen": false
  }
}

결과: <DOWNLOAD_BASE_DIR>/2026-08/pdf/2026-08-03_서울중앙지방법원_소장부본.pdf 같은 경로들.


시나리오 2 — "○○ 사건 관련 메일 첨부만 pdf 폴더로 모아줘"

"김철수" 관련 메일을 찾아서, 그 메일들의 PDF 첨부만 사건/김철수 폴더에 모아줘.

Claude 가 호출하는 것 (2단계):

{ "tool": "search_mails",
  "arguments": { "subject": "김철수", "has_attachment": true, "limit": 30, "scan_limit": 1000 } }
{ "tool": "download_attachments",
  "arguments": {
    "uids": [23011, 23044, 23090],
    "target_dir": "사건/김철수",
    "extensions": ["pdf"],
    "organize_by_type": true,
    "rename_template": "{date}_{subject}_{original}"
  } }

발신자로 찾는 편이 더 정확하면 from: "kimcs@lawfirm.co.kr" 을 쓰라고 알려주세요. 오래된 사건이면 scan_limit 을 올리라고 함께 지시하는 것이 좋습니다.


시나리오 3 — "고객 발송용 파일 모아서 발송대기 폴더에 준비해줘"

사건/김철수/pdf 에 있는 파일들을 첨부해서, 의뢰인(kim@example.com)에게 보낼 메일을 발송대기 폴더에 준비해줘. 제목은 "[○○법률사무소] 김철수님 사건 자료 송부", 본문은 자료 확인 요청 내용으로. 절대 발송하지는 마.

Claude 가 호출하는 것:

{
  "tool": "save_draft_or_prepare_send",
  "arguments": {
    "to": ["kim@example.com"],
    "subject": "[○○법률사무소] 김철수님 사건 자료 송부",
    "body_text": "안녕하세요, ○○법률사무소입니다.\n요청하신 사건 관련 자료를 첨부하여 송부드립니다.\n확인 후 회신 부탁드립니다.",
    "attachment_paths": [
      "/Users/내이름/사건첨부/사건/김철수/pdf/2026-08-03_소장부본.pdf"
    ],
    "mode": "prepare",
    "note": "담당 변호사 검토 후 발송"
  }
}

결과: _발송대기/... 폴더에 meta.json + message.eml + 첨부 사본이 생성되고, 발송은 되지 않습니다. 담당자가 내용을 확인한 뒤 터미널에서 npm run send-prepared -- "<폴더>" --confirm 로 보냅니다.


9. 보안 설계

위협

대응

평문 비밀번호가 디스크에 남음

환경변수 또는 AES-256-GCM 암호화 저장소(credentials.enc, 0600)

로그·에러 메시지에 비밀번호 노출

전역 마스킹 (util/redact.ts) — 원문/base64/URL 인코딩 형태까지 치환. 모든 로그와 툴 응답이 이 필터를 거침

첨부 파일명을 이용한 경로 조작 (../../etc/passwd)

파일명에서 경로 구분자·제어문자 제거, 마지막 경로 요소만 사용

target_dir 로 샌드박스 탈출

모든 저장 경로를 DOWNLOAD_BASE_DIR 기준으로 resolve 후 하위 여부 검증

심볼릭 링크로 우회

저장 직전 realpath 로 다시 검증 (base 와 target 을 동일 방식으로 해석)

통신 도청

IMAP TLS 필수 (NAVER_IMAP_SECURE=false 는 설정 단계에서 거부), SMTP 는 STARTTLS/SSL, minVersion: TLSv1.2

의도치 않은 메일 발송

MCP 툴에는 발송 코드 자체가 없음. 발송은 별도 CLI + --confirm 필요

의도치 않은 읽음 처리

조회는 전부 EXAMINE(읽기 전용)으로 메일함을 염. mark_as_seen 기본 false

임의 파일 첨부를 통한 유출

첨부 소스 경로를 허용 루트(DOWNLOAD_BASE_DIR, OUTBOX_DIR, ATTACH_ALLOWED_ROOTS)로 제한

대용량 첨부로 인한 메모리 고갈

첨부는 메모리에 올리지 않고 스트리밍으로 디스크에 기록. MAX_ATTACHMENT_MB 초과 시 건너뜀

stdout 오염으로 MCP 프로토콜 깨짐

모든 로그는 stderr 로만 출력

생성되는 파일 권한: 설정/상태 폴더 0700, 자격증명·상태·첨부 파일 0600.


10. 설계 가정 및 알려진 제약

요구사항에 명시되지 않아 합리적으로 가정한 것들입니다.

가정

  1. 런타임은 Node.js 20+ / TypeScript 를 선택했습니다. imapflow 가 MIME 파트 단위 스트리밍 다운로드를 지원해 대용량 첨부에 안전하고, MCP TypeScript SDK 가 가장 성숙하며, 요청하신 등록 명령(claude mcp add ... -- node dist/index.js)과 그대로 맞기 때문입니다.

  2. docx/ 폴더에는 .doc 도 함께 넣습니다. xlsx/ 에는 .xls, .xlsm, .csv 를 함께 넣습니다. 실무에서 구버전 포맷을 따로 찾아다니는 것이 더 불편하다고 판단했습니다. .pptx, .zip, .html 등은 명세대로 etc/ 로 갑니다. 분류표는 .envATTACHMENT_CATEGORY_MAP 으로 바꿀 수 있습니다.

  3. 본문에 삽입된 인라인 이미지(cid 를 가진 서명 로고·배너)는 기본적으로 첨부로 보지 않습니다. 그렇게 하지 않으면 로고 파일이 images/ 에 수백 개 쌓입니다. include_inline_images: true 로 켤 수 있습니다.

  4. 내용이 완전히 같은 파일(sha256 일치)은 _1, _2 사본을 만들지 않고 건너뜁니다. 명세는 "중복 시 _1, _2" 였지만, 그대로 두면 워크플로우를 재실행할 때마다 사본이 무한 증식합니다. 이름만 같고 내용이 다르면 명세대로 _1, _2 가 붙습니다.

  5. process_new_mails_with_attachments 의 첫 실행은 "오늘"부터 시작합니다. 기록이 없다고 메일함 전체(수천 통)를 내려받으면 사고이기 때문입니다. 경고 메시지로 안내하고, since 로 넓힐 수 있습니다.

  6. save_draft_or_prepare_send 는 SMTP 로 초안을 저장하지 않습니다. SMTP 프로토콜에는 초안 저장 기능이 없습니다. 대신 (a) 발송대기 폴더 + .eml 생성, (b) IMAP APPEND 로 네이버 임시보관함에 초안 저장 — 두 가지를 제공합니다.

  7. 실제 발송 기능은 MCP 툴로 제공하지 않습니다. 별도 CLI(npm run send-prepared -- <폴더> --confirm)로만 가능합니다.

  8. list_mailboxes 툴을 추가했습니다. 명세에는 없지만, 네이버 메일함 이름이 한글이거나 modified-UTF7 로 인코딩되어 있어 다른 툴의 mailbox 값을 채우려면 사실상 필요합니다.

알려진 제약

  • 첨부 유무/확장자 필터는 느립니다. IMAP 에는 "첨부 있는 메일" 검색 조건이 없어서 후보 메일들의 BODYSTRUCTURE 를 하나씩 받아 판별해야 합니다. 네이버 서버 응답이 느린 편이라 200통 훑는 데 1~2분이 걸릴 수 있습니다. → 날짜 조건(since)을 함께 주면 훨씬 빠릅니다. 기본 스캔 범위는 최근 200통(CLIENT_SCAN_LIMIT)이며, 더 넓게 보려면 툴 인자 scan_limit 을 올리세요. 범위에 걸리면 응답에 경고가 함께 나옵니다.

  • 한글 본문 검색(body)은 네이버 IMAP 이 제대로 처리하지 못할 수 있습니다. 제목·발신자 검색은 서버가 실패해도 클라이언트에서 필터링하지만, 본문은 전체 메일을 받아야 해서 폴백하지 않습니다.

  • 깨진 첨부 파일명 복구. 국내 금융기관 메일은 파일명을 RFC 2047 인코딩 없이 EUC-KR 원시 바이트로 보내는 경우가 많고, 이때 IMAP 라이브러리가 UTF-8 로 잘못 디코딩합니다. 이 서버는 이름이 깨진 첨부에 한해 원본 MIME 헤더(BODY[n.MIME])를 다시 받아 CP949 로 복구합니다. (실제 계정 테스트에서 보안암호첨부.html 정상 복구 확인)

  • IMAP 동기화 제한. 네이버 환경설정의 "IMAP 동기화 메일 제한"보다 오래된 메일은 서버가 아예 보여주지 않습니다.

  • 네이버 첨부 용량. 대용량 첨부(네이버 클라우드 링크)는 실제 파일이 아니라 본문 링크이므로 다운로드되지 않습니다.


11. 문제 해결

증상

원인/해결

네이버 IMAP 로그인에 실패했습니다

① 메일 환경설정에서 IMAP/SMTP 사용함 + 확인 버튼 눌렀는지 ② 로그인 비밀번호가 아니라 앱 비밀번호인지 ③ 앱 비밀번호를 재발급했는지

설정 오류: 네이버 계정 정보를 찾을 수 없습니다

.env 위치를 못 찾은 경우가 대부분. NAVER_MAIL_MCP_ENV.env 절대경로를 지정하세요

Claude 에서 툴이 안 보임

npm run build 를 했는지, dist/index.js 경로가 절대경로인지 확인. Claude Desktop 은 완전 종료 후 재시작 필요

오래된 메일이 안 보임

네이버 환경설정의 "IMAP 동기화 메일 제한"을 올리세요

첨부 검색이 너무 오래 걸림

날짜 조건을 주거나 scan_limit 을 낮추세요

허용되지 않은 경로입니다

target_dirDOWNLOAD_BASE_DIR 밖입니다. 상대경로를 쓰거나 DOWNLOAD_BASE_DIR 을 바꾸세요

자격증명 복호화에 실패했습니다

master.key 가 사라졌거나 NAVER_MCP_MASTER_KEY 가 바뀐 경우. npm run setup 으로 다시 저장

로그를 더 보고 싶다

.envLOG_LEVEL=debug (로그는 stderr 로만 나갑니다)


12. 프로젝트 구조

naver_mail_mcp/
├── src/
│   ├── index.ts                 # MCP 서버 진입점 (stdio, 툴 등록)
│   ├── config.ts                # 환경변수/설정 로딩, 확장자 분류표
│   ├── secrets.ts               # AES-256-GCM 자격증명 저장소
│   ├── imap.ts                  # IMAP 연결 관리 (재사용/재연결/직렬화/메일함 별칭)
│   ├── attachments.ts           # ★ 첨부 다운로드 + 분류 + rename 엔진
│   ├── outbox.ts                # 발송 준비 (.eml 생성, 임시보관함 초안) — 발송 없음
│   ├── state.ts                 # 증분 처리 상태(last_run)
│   ├── mail/
│   │   ├── service.ts           # 검색/목록/본문 조회 (서버검색 + 클라이언트 폴백)
│   │   ├── message.ts           # bodyStructure 해석, 본문/첨부 파트 판별
│   │   ├── mime.ts              # RFC2047/RFC2231 파일명 디코딩, charset 처리
│   │   ├── repair.ts            # EUC-KR 원시 바이트 파일명 복구
│   │   ├── rename.ts            # rename_template 처리, 확장자→폴더 매핑
│   │   └── html-text.ts         # HTML → 평문 변환
│   ├── tools/                   # MCP 툴 정의 (스키마 + 핸들러)
│   ├── cli/
│   │   ├── setup.ts             # npm run setup   — 자격증명 암호화 저장
│   │   ├── doctor.ts            # npm run doctor  — 연결 진단
│   │   └── send-prepared.ts     # npm run send-prepared — 사람이 직접 발송
│   └── util/                    # 경로 보안, 로깅, 비밀정보 마스킹, 날짜
├── scripts/
│   ├── smoke-test.mjs           # MCP stdio 종단 테스트 (임시 폴더에 격리 실행)
│   └── install-desktop.mjs      # Claude Desktop 자동 등록 마법사
├── 설치.command                  # macOS 더블클릭 설치 (빌드→계정→등록→진단)
├── 사용설명서.md                 # 비전문가용 사용설명서
├── .env.example
└── dist/                        # 빌드 결과 (npm run build)

참고

아키텍처·IMAP 연결·증분 처리·자격증명 암호화 패턴은 youngsooco/k-mail-mcp 을 참고했습니다. 다만 이 프로젝트의 핵심인 첨부 로컬 저장 / 확장자별 분류 / 파일명 규칙 / 경로 샌드박스는 새로 설계·구현했습니다.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Hoodess/naver-mail-mcp-basic'

If you have feedback or need assistance with the MCP directory API, please join our Discord server