EML과 MBOX는 무엇인가
EML은 메일 한 통을 일반 텍스트로 저장한 파일입니다. 형식은 RFC 5322의 인터넷 메시지 형식으로, From:·Subject: 같은 헤더 줄이 먼저 나오고 빈 줄 하나 뒤에 본문이 옵니다. 본문의 구조는 MIME(RFC 2045~2049)이 정합니다. 한글 같은 비ASCII 텍스트, 같은 내용의 여러 버전, 바이너리 첨부를 텍스트 파일 안에 담는 규칙입니다.
MBOX는 여러 통을 한 파일에 이어 붙인 형식입니다. 각 메일은 From 뒤에 발신자와 날짜가 오는 구분선으로 시작합니다. 예를 들면 From billing@example.com Mon Nov 22 07:00:00 2021 같은 줄이고, 형식은 RFC 4155에 설명되어 있습니다. 이 줄은 헤더가 아니라 형식이 덧붙인 표시이며 메일 본체의 일부가 아닙니다. Gmail Takeout, Thunderbird, 오래된 유닉스 메일 도구가 MBOX를 쓰는 이유는 뒤에 이어 붙이기 쉽기 때문입니다. Outlook, Apple Mail, Windows 메일은 메일 한 통을 바탕화면으로 끌어다 놓으면 EML로 저장합니다.
둘 다 바이트 수준에서는 일반 텍스트입니다. 아무 텍스트 편집기로 열어 헤더를 읽을 수 있고, 이 점은 뒤에서 중요해집니다.
메일 프로그램 설치 없이 여는 방법
EML·MBOX 메일 뷰어는 백그라운드 워커가 .eml과 .mbox를 읽고 제목·발신자·날짜를 목록으로 보여 줍니다. 검색, 필터, 미리보기와 선택 내보내기를 지원합니다. 파일은 1 GiB, 메일함은 120,000통, 메시지 하나는 128 MiB까지 받으며 서버로 올리지 않습니다.
MBOX 뷰어는 같은 워커와 한도를 쓰되 메일함 탐색, 검색, 디코딩된 미리보기와 CSV 목록에 집중합니다. 목록 미리보기는 약 240자, CSV는 4,000자까지 담습니다. 메일함 텍스트가 약 1억 2,800만 자를 넘으면 메시지마다 처음 6,000자를 검색합니다.
뷰어가 보여 주는 것은 해석된 결과입니다. 제목, 보낸 사람(From), 받는 사람(To), 참조(Cc), 날짜(Date), 본문, 첨부입니다. 원본 헤더 블록은 보여 주지 않으므로, 아래에서 설명할 Received 체인이나 인증 결과를 보려면 같은 .eml 파일을 텍스트 편집기로 여세요.
| 하려는 일 | 쓸 도구 | 참고 |
|---|---|---|
| 저장해 둔 메일 한 통 읽기 | EML·MBOX 메일 뷰어 | EML 여러 개를 한꺼번에 선택 가능 |
| 큰 메일함 탐색 | EML·MBOX 메일 뷰어 | 1 GiB, 120,000통, 메시지당 128 MiB |
| 빠른 확인과 CSV 목록 | MBOX 뷰어 | 같은 한도, 간결한 미리보기 |
| 메일 한 통당 파일 하나 | MBOX를 EML로 변환 | message-00001.eml, message-00002.eml, ... |
| 원본 헤더 읽기 | 텍스트 편집기 | 뷰어는 Received·Authentication-Results를 표시하지 않음 |
읽어 둘 가치가 있는 헤더
배달 이력은 헤더에 남습니다. 아래는 이 글을 위해 쓴 현실적인 헤더 블록이고 뷰어로 파싱해 확인했으며, 발신 도메인은 shop.example입니다. 메일을 거친 서버가 자기 Received 줄을 맨 위에 추가하므로 아래에서 위로 읽어야 합니다.
From은 받는 사람 눈에 보이는 발신자입니다. 발신 소프트웨어가 적는 값이라, 이후 검사로 도메인과 묶이지 않으면 무엇이든 될 수 있습니다.Reply-To는 답장이 갈 주소를 정합니다. 한 주소에서 왔는데 다른 주소로 답하라는 메일은 한 번 더 살펴볼 만합니다.Return-Path는 배달 시점에 기록된 봉투 발신자로 반송 메일이 가는 곳입니다. 뉴스레터나 쇼핑몰 메일에서는From과 다른 경우가 흔합니다.Received줄은 구간별 기록이고 가장 오래된 것이 맨 아래입니다. 보낸 쪽이 가짜 옛 줄을 끼워 넣을 수 있으므로 믿을 수 있는 것은 신뢰하는 서버가 추가한 줄, 보통 위쪽 줄뿐입니다.Message-ID는 고유해야 합니다. 서로 다른 두 메일에 같은 ID가 있다면 중복이나 재전송의 단서입니다.Date에는 시간대 오프셋이 있습니다. 12:14:08 +0900은 UTC 03:14:08이며, 뷰어는 이 값으로 정렬과 필터를 합니다.
Return-Path: <bounce+abc@mail.shop.example>
Received: from mail-out.shop.example (mail-out.shop.example [203.0.113.25])
by mx.example.com with ESMTPS id k12si345; Tue, 01 Sep 2026 03:14:09 +0000 (UTC)
Received: from app01.internal (app01.internal [10.0.4.7])
by mail-out.shop.example with SMTP id x9; Tue, 01 Sep 2026 03:14:08 +0000
Authentication-Results: mx.example.com;
spf=pass smtp.mailfrom=bounce+abc@mail.shop.example;
dkim=pass header.d=shop.example header.s=s1;
dmarc=pass header.from=shop.example
From: =?UTF-8?B?66+865Ok66CIIOyDgeygkA==?= <orders@shop.example>
Reply-To: support@shop.example
Message-ID: <20260901031408.1234@shop.example>
Date: Tue, 01 Sep 2026 12:14:08 +0900SPF·DKIM·DMARC가 증명하는 것과 그렇지 않은 것
Authentication-Results(RFC 8601)는 받는 서버가 적는 요약으로 세 가지 검사를 담습니다. SPF(RFC 7208)는 접속한 서버가 봉투 도메인 대신 메일을 보내도 되는지 봅니다. DKIM(RFC 6376)은 일부 헤더와 본문에 대한 서명이 서명 도메인 기준으로 맞는지 검증합니다. DMARC(RFC 7489)는 SPF나 DKIM이 통과하고, 검증된 도메인이 화면에 보이는 From의 도메인과 일치할 때만 통과합니다.
통과는 어떤 도메인이 그 메일을 허가했거나 서명했다는 뜻입니다. 내용이 사실이라는 뜻도, 보낸 사람이 당신이 생각하는 사람이라는 뜻도, 첨부가 안전하다는 뜻도 아닙니다. 피싱 사이트가 직접 등록한 비슷한 도메인에서 세 검사를 모두 통과하는 메일을 보낼 수 있습니다. 실패하거나 없는 결과는 경고 신호이지만, 전달된 메일은 정상인데도 SPF에 실패할 수 있습니다.
이 헤더는 적은 서버만큼만 믿을 수 있습니다. 본인 메일 서비스가 추가한 Authentication-Results를 신뢰하고, 메일과 함께 들어온 다른 복사본은 무시하세요. 직접 내보낸 파일에는 본인의 서비스가 적은 줄이 있습니다. 남이 보내 준 파일은 EML이 일반 텍스트이므로 누구든 헤더를 고쳤을 수 있습니다.
인코딩된 제목(encoded-word) 풀어 보기
헤더 줄은 원래 ASCII로 정의되어 있어서 비ASCII 제목이나 표시 이름은 encoded-word(RFC 2047) 형태인 =?문자셋?인코딩?텍스트?=로 감쌉니다. 인코딩은 Base64를 뜻하는 B, 또는 quoted-printable 변형인 Q입니다. 푸는 방법은 Base64를 읽고, 나온 바이트를 지정된 문자셋으로 해석하는 것입니다. 아래는 뷰어 샘플 메일함의 한글 제목을 Node.js로 직접 계산한 결과입니다.
- encoded-word 하나는 75자까지라서 긴 제목은 여러 개로 나뉘고, 디코딩할 때 단어 사이의 공백은 무시됩니다.
From·To의 표시 이름도 같은 방식으로 인코딩되므로, 원본 헤더는 알 수 없는 문자열처럼 보이는데 뷰어에는 이름이 나옵니다.- 선언한 문자셋이 틀리면 오류가 아니라 글자가 깨진 결과가 나옵니다. 다음 절들에서 그 모습을 다룹니다.
=?UTF-8?B?7JWI64WV7ZWY7IS47JqUIOyDiOuhnOyatCDtlITroZzsoJ3tirg=?=
base64 디코딩 -> 바이트 -> UTF-8 -> 안녕하세요 새로운 프로젝트
=?UTF-8?B?7JWI64WV7ZWY7IS47JqU?= -> 안녕하세요
UTF-8 15바이트: ec9588 eb8595 ed9598 ec84b8 ec9a94
=?UTF-8?Q?Caf=C3=A9_menu?= -> Café menu
Q 인코딩에서 _ 는 공백, =C3=A9 는 é의 UTF-8 바이트 두 개multipart/alternative, multipart/mixed, 본문 이미지(cid)
MIME은 메일을 부분(part)의 트리로 감쌉니다. multipart/alternative는 같은 내용의 여러 버전을 담습니다. 보통 텍스트와 HTML 한 쌍이고 읽는 쪽이 하나를 고릅니다. multipart/mixed는 서로 독립적인 것들, 곧 본문과 첨부를 담습니다. multipart/related는 HTML과 그 안에서 쓰는 이미지를 묶습니다. 실제 메일은 이것들을 겹쳐 씁니다. 바깥이 mixed, 그 안이 alternative, 다시 안쪽이 related입니다.
related 이미지에는 Content-ID: <logo@shop> 헤더가 있고 HTML은 src="cid:logo@shop"로 가리킵니다. 본문 안에 표시되지만 구조로는 여전히 첨부 부분입니다. 제가 파싱한 샘플 메일의 첨부 목록에는 본문 로고인 logo.png와 receipt.pdf가 함께 들어 있었습니다.
- EML·MBOX 메일 뷰어는 텍스트 본문을, 또는 스크립트·폼·스타일·링크를 제거한 HTML을 샌드박스 프레임에 보여 줍니다. 본문의
cid:이미지는 메일 자체에서 꺼내 채웁니다. - 원격 이미지는 열면 발신자에게 읽었다는 사실이 전달되므로, 메일마다 허용하기 전에는 차단됩니다.
- 미리보기는 원본이 아닙니다. HTML만 있는 메일이면 텍스트 보기는 그 HTML에서 만든 것입니다.
multipart/mixed
multipart/alternative
text/plain "주문이 접수되었습니다."
multipart/related
text/html <p>주문 접수</p><img src="cid:logo@shop">
image/png Content-ID: <logo@shop> logo.png
application/pdf receipt.pdf한글 메일과 문자셋 문제
오래된 한국 메일 프로그램은 KS X 1001 텍스트에 charset=euc-kr, 또는 마이크로소프트식 이름인 ks_c_5601-1987을 선언하곤 했고, 본문은 Base64나 quoted-printable로 인코딩되었거나 8비트 원문 그대로일 수 있습니다. 같은 글자도 바이트가 다릅니다. 안녕하세요는 UTF-8로 15바이트, EUC-KR로 10바이트입니다. EUC-KR 바이트를 UTF-8로 읽으면 �ȳ��ϼ���, Latin-1로 읽으면 ¾È³çÇϼ¼¿ä가 됩니다. 둘 다 문자셋이 틀렸을 때의 전형적인 모습입니다.
아래는 그 바이트를 브라우저가 쓰는 WHATWG Encoding 이름으로 Node.js에서 디코딩한 결과입니다.
바이트(16진) be c8 b3 e7 c7 cf bc bc bf e4 (EUC-KR, 10바이트)
TextDecoder("euc-kr") -> 안녕하세요
TextDecoder("ks_c_5601-1987") -> 안녕하세요 (같은 디코더의 다른 이름)
TextDecoder("utf-8") -> �ȳ��ϼ���
TextDecoder("latin1") -> ¾È³çÇϼ¼¿ä
Subject: =?ks_c_5601-1987?B?vsiz58fPvLy/5A==?= -> 안녕하세요Gmail Takeout MBOX를 EML 파일로 나누기
Gmail Takeout은 라벨마다 .mbox 하나를 만들고, 구분선은 보통 From 1830000000000000000@xxx Thu Jan 01 00:00:00 +0000 2026 같은 모습입니다. 메일에는 대개 X-Gmail-Labels 헤더가 붙습니다. 구분선 판정은 엄격해서 From , 발신자, 요일, 월, 일, 시각, 연도가 모두 맞아야 합니다. 본문의 From the archive: kept 같은 줄은 이 형식에 맞지 않으므로 메일을 둘로 자르지 못합니다.
이 형식에는 길이 필드가 없어서, 본문에서 정말로 From 으로 시작하는 줄은 새 메일로 오인됩니다. 쓰는 쪽은 그런 줄 앞에 >를 붙여 막습니다. mboxo는 >를 하나 붙입니다. mboxrd는 이미 >From 이나 >>From 인 줄에도 >를 하나 더 붙여서 되돌릴 수 있게 합니다. 읽는 쪽은 >를 하나씩 뗍니다. 아래는 두 형태가 모두 들어 있는 뷰어 샘플 메일함에서 실제로 나온 결과입니다.
- MBOX를 EML로 변환 도구는 실제 구분선에서 자르고
>From인용을 되돌려message-00001.eml,message-00002.eml, ... 를 ZIP 하나에 담습니다. 줄바꿈, 헤더, MIME 구조, 첨부를 포함한 메시지 바이트는 원래 그대로 옮깁니다. - 1 GiB나 120,000통을 넘는 Takeout 파일은 받지 않으며 메시지 하나는 128 MiB까지 가능합니다. Takeout에서 라벨을 줄이거나 기간으로 나눠 따로 변환하세요.
- 이렇게 만든 EML은
X-Gmail-Labels를 평범한 헤더로 유지하므로 나중에 분류할 때 유용합니다.
MBOX에 저장된 모양 메일에서 읽은 모양
>From my notes: ... From my notes: ...
>>From the label: ... >From the label: ...
From the desk of Dad ... From the desk of Dad ... (구분선이 아님)
감지된 변형: mboxrd, 2줄 복원, 메일 5통개인정보: 이 파일은 메일함 전체입니다
MBOX는 문서가 아닙니다. 수년 치 주고받은 메일, 영수증, 비밀번호 재설정 링크, URL 속 토큰, 다른 사람들의 주소가 들어 있습니다. 데이터베이스 내보내기처럼 다루고, 가능하면 내 컴퓨터 안에서 처리하는 도구를 쓰세요. 여기서 소개한 뷰어와 변환 도구는 파일을 브라우저 안에서 읽고 업로드하지 않습니다.
복사본으로 작업하고, 끝나면 복사본을 지우며, 결과물을 저장하는 위치에 신경 쓰세요. 첨부 ZIP이나 HTML 내보내기도 원본만큼 민감합니다. 메일이 내 보관함에 있다는 사실이 안전하다는 뜻은 아니므로 첨부는 열기 전에 검사하세요. 법적 효력이 걸린 용도라면 변환본 옆에 원본 EML 또는 MBOX를 손대지 않은 채로 보관하세요.