- Gmail to SQLite는 Gmail 메시지를 로컬 SQLite 데이터베이스로 동기화해 분석과 보관에 활용하는 Python 애플리케이션임
- 기본 동작은 새 메시지만 내려받는 증분 동기화이며, 전체 동기화 옵션으로 모든 메시지를 내려받고 삭제 여부도 감지할 수 있음
- 메시지 가져오기는 멀티스레드 병렬 처리를 사용하며, 지수 백오프 기반 자동 재시도와 CTRL+C 처리 같은 오류·종료 대응을 포함함
- 실행에는 Python 3.8 이상, Gmail API가 활성화된 Google Cloud Project, OAuth 2.0
credentials.json 파일이 필요함
- 저장된 데이터는 발신자, 수신자, 라벨, 본문, 크기, 읽음 여부, 발신 여부, 삭제 여부 등을 포함해 SQL로 Gmail 사용 패턴을 직접 분석할 수 있음
Gmail 메시지 로컬 동기화 도구
- Gmail to SQLite는 Gmail 메시지를 로컬 SQLite 데이터베이스에 저장하는 Python 애플리케이션임
- 목적은 Gmail 데이터를 분석하고 보관할 수 있게 만드는 것임
- 코드베이스 전반에 타입 힌트를 적용해 타입 안전성을 갖추고 있음
동기화 방식과 안정성
- 기본 동기화는 증분 동기화로 동작해 새 메시지만 다운로드함
--full-sync 옵션을 사용하면 전체 메시지를 동기화하고 Gmail에서 삭제된 메시지를 감지함
- 메시지 가져오기는 멀티스레드 병렬 처리로 수행해 성능을 높임
- 오류 처리에는 자동 재시도와 지수 백오프가 포함됨
- CTRL+C를 누르면 우아한 종료 절차가 실행됨
- 새 작업 수락을 중단함
- 실행 중인 작업이 끝나기를 기다림
- 완료된 작업의 진행 상태를 저장함
- 정상 종료함
- CTRL+C를 한 번 더 누르면 즉시 종료함
설치와 준비 조건
- 실행 환경에는 Python 3.8 이상이 필요함
- Gmail API가 활성화된 Google Cloud Project가 필요함
- OAuth 2.0 인증 파일
credentials.json이 프로젝트 루트에 있어야 함
- 설치 흐름은 저장소를 클론한 뒤
uv sync로 의존성을 설치하는 방식임
- Gmail API 인증 설정은 Google Cloud Console에서 프로젝트를 만들거나 선택하고, Gmail API를 활성화한 뒤 Desktop application용 OAuth 2.0 자격 증명을 생성해
credentials.json으로 저장함
명령어 사용법
python main.py sync --data-dir ./data
# or: uv run main.py sync --data-dir ./data
- 전체 동기화와 삭제 감지는
--full-sync를 사용함
python main.py sync --data-dir ./data --full-sync
- 특정 메시지만 동기화하려면
sync-message와 --message-id를 사용함
python main.py sync-message --data-dir ./data --message-id MESSAGE_ID
- 삭제된 메시지만 감지하고 표시하려면
sync-deleted-messages를 사용함
python main.py sync-deleted-messages --data-dir ./data
- 워커 스레드 수는
--workers로 지정할 수 있으며, 기본값은 CPU 코어 수임
python main.py sync --data-dir ./data --workers 8
- 명령줄 인자는 다음과 같음
command: 필수이며 sync, sync-message, sync-deleted-messages 중 하나
--data-dir: 필수이며 SQLite 데이터베이스가 저장될 디렉터리
--full-sync: 선택 사항이며 전체 동기화를 강제함
--message-id: sync-message에서 필수이며 동기화할 특정 메시지 ID
--workers: 선택 사항이며 워커 스레드 수
--help: 명령과 옵션 도움말 표시
SQLite 스키마와 분석 예시
- 생성되는 SQLite 데이터베이스의
messages 테이블은 Gmail 메시지 분석에 필요한 필드를 포함함
message_id: 고유 Gmail 메시지 ID
thread_id: Gmail 스레드 ID
sender: 이름과 이메일을 담은 JSON 발신자 정보
recipients: to, cc, bcc 유형별 수신자 JSON
labels: Gmail 라벨 배열
subject: 메시지 제목
body: 일반 텍스트 메시지 본문
size: 바이트 단위 메시지 크기
timestamp: 메시지 시각
is_read: 읽음 상태
is_outgoing: 사용자가 보낸 메시지 여부
is_deleted: Gmail에서 삭제된 메시지 여부
last_indexed: 마지막 동기화 시각
- 발신자별 이메일 수를 집계할 수 있음
SELECT sender->>'$.email', COUNT(*) AS count
FROM messages
GROUP BY sender->>'$.email'
ORDER BY count DESC
- 읽지 않은 이메일을 발신자별로 집계해 흥미 없는 이메일을 많이 보내는 발신자를 확인할 수 있음
SELECT sender->>'$.email', COUNT(*) AS count
FROM messages
WHERE is_read = 0
GROUP BY sender->>'$.email'
ORDER BY count DESC
strftime을 사용해 연도, 월, 일, 요일, 시간 단위로 이메일 수를 집계할 수 있음
SELECT strftime('%Y', timestamp) AS period, COUNT(*) AS count
FROM messages
GROUP BY period
ORDER BY count DESC
- 본문에
newsletter 또는 unsubscribe가 포함된 메일을 찾아 뉴스레터를 발신자별로 묶을 수 있음
SELECT sender->>'$.email', COUNT(*) AS count
FROM messages
WHERE body LIKE '%newsletter%' OR body LIKE '%unsubscribe%'
GROUP BY sender->>'$.email'
ORDER BY count DESC
- 발신자별 총 메일 크기와 큰 이메일 발신자를 MB 단위로 확인할 수 있음
SELECT sender->>'$.email', sum(size)/1024/1024 AS size
FROM messages
GROUP BY sender->>'$.email'
ORDER BY size DESC
- 자신에게 보낸 메일 수를
recipients JSON과 sender 이메일 조건으로 계산할 수 있음
SELECT count(*)
FROM messages
WHERE EXISTS (
SELECT 1
FROM json_each(messages.recipients->'$.to')
WHERE json_extract(value, '$.email') = 'foo@example.com'
)
AND sender->>'$.email' = 'foo@example.com'
- 수신한 메일 중 발신자별 총 용량이 큰 순서를 확인할 수 있음
SELECT sender->>'$.email', sum(size)/1024/1024 as total_size
FROM messages
WHERE is_outgoing=false
GROUP BY sender->>'$.email'
ORDER BY total_size DESC
- 삭제된 메시지는
is_deleted=1 조건으로 조회함
SELECT message_id, subject, timestamp
FROM messages
WHERE is_deleted=1
ORDER BY timestamp DESC