# rb8001과 skill-email Gmail 통합 완료 보고서 ## 작업일: 2025-08-19 ## 작업자: 희재 ## 상태: 완료 --- ## 1. 작업 개요 ### 목적 rb8001이 Gmail 기능을 사용할 수 있도록 skill-email 서비스와 통합 ### 배경 - skill-email은 DB 기반 토큰 관리로 전환 완료 - rb8001이 사용자의 Gmail 요청을 감지하고 처리할 수 있도록 통합 필요 - Gmail 아이템 장착 상태 확인 및 권한 관리 필요 --- ## 2. 구현 내용 ### 2.1 환경변수 설정 **파일**: `/home/heejae/rb8001/.env` ```bash # Skill Services SKILL_EMAIL_URL=http://localhost:8501 MONITOR_SERVICE_URL=http://localhost:9024 # PostgreSQL for Gmail tokens (SSH tunnel) POSTGRES_CONNECTION_STRING=postgresql://robeings:robeings@localhost:5433/main_db ``` ### 2.2 Gmail 통합 모듈 구현 **파일**: `/home/heejae/rb8001/app/skills/email_integration.py` #### 주요 클래스: EmailIntegration Gmail 스킬 통합을 담당하는 핵심 모듈 #### 핵심 메서드 1. **check_gmail_equipped(user_id)** ```python async def check_gmail_equipped(self, user_id: str) -> bool: # PostgreSQL에서 직접 장착 상태 확인 # 5분 캐싱으로 성능 최적화 cur.execute(""" SELECT COUNT(*) FROM gmail_token WHERE user_id = %s AND is_equipped = true """, (user_id,)) ``` - gmail_token 테이블의 is_equipped 확인 - 캐시 TTL: 300초 (5분) - DB 연결 실패 시 False 반환 2. **parse_email_intent(message)** ```python def parse_email_intent(self, message: str) -> Optional[Dict[str, Any]]: # 이메일 관련 키워드 감지 # 발송/조회/답장 의도 분류 # 수신자, 제목, 내용 추출 ``` - 키워드: "이메일", "메일", "보내", "전송", "확인", "조회", "답장" - 정규표현식으로 수신자 추출: `([가-힣]+님?)(?:한테|에게|께)` - 이메일 주소 패턴: `[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}` 3. **process_email_request(message, user_id, channel)** ```python async def process_email_request( self, message: str, user_id: str, channel: str = None ) -> Tuple[bool, str]: # 1. Gmail 장착 확인 # 2. 이메일 의도 파싱 # 3. skill-email 서비스 호출 # 4. 응답 처리 ``` **처리 플로우:** - 미장착 시: "Gmail 패스포트를 먼저 장착해주세요! 🎫" - 발송 요청: POST /process 엔드포인트 호출 - 조회 요청: GET /messages 엔드포인트 호출 - 토큰 만료: 재인증 안내 메시지 4. **handle_reauth(user_id)** ```python async def handle_reauth(self, user_id: str) -> Tuple[bool, str]: # robeing-monitor 서비스에 재인증 요청 # OAuth URL 생성 및 반환 ``` ### 2.3 라우터 통합 **파일**: `/home/heejae/rb8001/app/router/router.py` #### 변경 내용 ```python # Import 추가 from app.skills.email_integration import email_integration # route_message 메서드에 Gmail 처리 추가 async def route_message(self, message: str, user_id: str, channel: str, thread_ts: str = None): # 0. 슬래시 명령어 처리 # ... # 0.5. Gmail 요청 확인 및 처리 (새로 추가) email_result = await email_integration.process_email_request(message, user_id, channel) if email_result[0] or email_result[1] is not None: return { "success": email_result[0], "message": email_result[1], "content": email_result[1], "service": "gmail", "execution_plan": {"intent": "email", "skills": ["email"]} } # 1. 기존 Brain 기반 라우팅 # ... ``` **처리 우선순위:** 1. 슬래시 명령어 (/memory, /stats 등) 2. Gmail 요청 (이메일 발송/조회) 3. 일반 Brain 기반 라우팅 --- ## 3. 테스트 구현 ### 3.1 통합 테스트 스크립트 **파일**: `/home/heejae/rb8001/test_gmail_integration.py` #### 테스트 케이스 1. **장착 상태 확인** - U091UNVE41M (전희재): is_equipped=True ✅ - U0925SXQFDK (종태): is_equipped=False ✅ 2. **의도 파싱 테스트** - "종태님한테 회의 일정 메일 보내줘" → action: send, to: 종태님 ✅ - "최근 메일 확인해줘" → action: list, limit: 5 ✅ 3. **프로세스 테스트** - 미장착 사용자 → 장착 안내 메시지 ✅ - 장착된 사용자 → skill-email 호출 ✅ ### 3.2 테스트 결과 ```bash === rb8001 Gmail Integration Test === [Test: 장착 상태 확인] User U091UNVE41M: Gmail equipped = True [Test: 이메일 발송 의도 파싱] Parsed intent: {'action': 'send', 'to': '종태님', 'subject': '회의 일정 안내', 'body': '...'} [Test: 이메일 조회 의도 파싱] Parsed intent: {'action': 'list', 'limit': 5} [Test: 이메일 처리 (미장착)] Success: False Message: Gmail 패스포트를 먼저 장착해주세요! 🎫 [Test: 이메일 처리 (장착됨)] Success: True Message: 이메일을 보내기 위해 다음 정보가 필요합니다... ``` --- ## 4. API 통신 ### 4.1 skill-email 엔드포인트 - **POST /process**: 대화형 이메일 처리 - **GET /messages**: 이메일 목록 조회 - **GET /health**: 서비스 상태 확인 ### 4.2 요청/응답 형식 #### 발송 요청 ```json { "message": "종태님한테 회의 일정 메일 보내줘", "user_id": "U091UNVE41M", "channel": "C123456", "robeing_id": "rb8001" } ``` #### 응답 ```json { "success": true, "content": "이메일 처리 메시지", "data": { "type": "need_more_info|send|error", "draft": {...}, "missing_fields": ["to", "subject"] } } ``` --- ## 5. 보안 및 권한 관리 ### 5.1 장착 확인 - is_equipped=true인 토큰만 사용 가능 - 사용자별 개별 확인 (Slack User ID 기반) ### 5.2 캐싱 - 장착 상태 5분 캐싱 - DB 부하 감소 및 응답 속도 개선 ### 5.3 에러 처리 - DB 연결 실패 → 기본값 False (안전한 실패) - 토큰 만료 → 재인증 안내 - 네트워크 타임아웃 → 30초 제한 --- ## 6. 디렉토리 구조 ``` /home/heejae/rb8001/ ├── .env # 환경변수 (수정됨) ├── app/ │ ├── skills/ # 새로 생성 │ │ └── email_integration.py # Gmail 통합 모듈 │ ├── router/ │ │ └── router.py # 라우터 (수정됨) │ └── ... └── test_gmail_integration.py # 테스트 스크립트 ``` --- ## 7. 데이터 플로우 ``` 사용자 메시지 (Slack) ↓ rb8001 (router.py) ↓ Gmail 의도 감지 ↓ 장착 상태 확인 (PostgreSQL) ↓ skill-email 호출 (HTTP) ↓ Gmail API 실행 ↓ 응답 반환 ↓ Slack 메시지 전송 ``` --- ## 8. 주요 성과 1. **통합 완료** ✅ - rb8001이 Gmail 요청 감지 및 처리 가능 - skill-email 서비스와 완전 연동 2. **권한 관리** ✅ - Gmail 아이템 장착 상태 확인 - 미장착 시 친절한 안내 메시지 3. **성능 최적화** ✅ - 5분 캐싱으로 DB 부하 감소 - 30초 타임아웃으로 무한 대기 방지 4. **유연한 구조** ✅ - 의도 파싱과 서비스 호출 분리 - 확장 가능한 아키텍처 --- ## 9. 문제 해결 ### 9.1 권한 오류 - **문제**: `/home/heejae/rb8001/app/skills/` 디렉토리 생성 실패 - **해결**: `sudo mkdir -p` 및 `chmod 777` 적용 ### 9.2 의도 파싱 - **문제**: "test@example.com에게" 형식 파싱 실패 - **해결**: 이메일 정규표현식 패턴 추가 ### 9.3 모듈 임포트 - **문제**: psycopg2 모듈 위치 - **해결**: 함수 내부에서 동적 임포트 --- ## 10. 사용 시나리오 ### 시나리오 1: 이메일 발송 ``` 사용자: @rb8001 종태님한테 회의 일정 메일 보내줘 rb8001: (장착 확인) → (의도 파싱) → (skill-email 호출) skill-email: 이메일 주소가 필요합니다. 종태님의 이메일은? 사용자: goeun2dc@gmail.com skill-email: (이메일 발송) → 성공 메시지 ``` ### 시나리오 2: 미장착 사용자 ``` 사용자: @rb8001 이메일 보내줘 rb8001: Gmail 패스포트를 먼저 장착해주세요! 🎫 `/inventory` 명령어로 인벤토리를 확인할 수 있습니다. ``` ### 시나리오 3: 메일 조회 ``` 사용자: @rb8001 최근 메일 확인해줘 rb8001: 📧 최근 이메일: 1. *회의 일정 안내* 발신: 김종태 날짜: 2025-08-19 ... ``` --- ## 11. 향후 개선사항 ### 즉시 필요 - [ ] Docker 컨테이너 재빌드 및 배포 - [ ] Slack 실제 환경 테스트 - [ ] 에러 로깅 강화 ### 추후 개선 - [ ] 사용자 이름 → 이메일 주소 자동 매핑 - [ ] 답장 기능 구현 - [ ] 첨부파일 지원 - [ ] 이메일 검색 기능 - [ ] 대화 컨텍스트 유지 (연속 대화) --- ## 12. 의존성 ### Python 패키지 - httpx: 비동기 HTTP 클라이언트 - psycopg2-binary: PostgreSQL 연결 - asyncio: 비동기 처리 ### 외부 서비스 - skill-email (포트 8501) - PostgreSQL (SSH 터널 5433 → 5432) - robeing-monitor (포트 9024, 선택적) --- ## 13. 참고 명령어 ```bash # 통합 테스트 실행 cd /home/heejae/rb8001 && python3 test_gmail_integration.py # skill-email 상태 확인 curl http://localhost:8501/health # 이메일 발송 테스트 curl -X POST http://localhost:8501/process \ -H "Content-Type: application/json" \ -d '{"message": "...", "user_id": "U091UNVE41M", ...}' # PostgreSQL 장착 상태 확인 python3 -c " import psycopg2 conn = psycopg2.connect('postgresql://robeings:robeings@localhost:5433/main_db') cur = conn.cursor() cur.execute('SELECT user_id, is_equipped FROM gmail_token') for row in cur.fetchall(): print(f'{row[0]}: equipped={row[1]}') " ``` --- ## 14. 검증 체크리스트 - [x] 환경변수 설정 완료 - [x] EmailIntegration 클래스 구현 - [x] 장착 상태 확인 동작 - [x] 의도 파싱 정확도 - [x] skill-email API 호출 성공 - [x] 라우터 통합 완료 - [x] 에러 처리 동작 - [x] 캐싱 메커니즘 동작 - [x] 테스트 스크립트 통과 - [ ] 실제 Gmail API 호출 (토큰 유효성) - [ ] Slack 실환경 테스트 --- **작업 완료: 2025-08-19** **다음 단계: Docker 배포 및 실환경 테스트**