Initial commit: Gmail Automation RPA
Gmail API를 활용한 이메일 자동화 RPA 프로그램 Features: - Gmail API 인증 및 연동 - 키워드/발신자 기반 자동 분류 - 조건별 자동 답장 기능 - 통계 리포트 생성 - 커스터마이징 가능한 JSON 설정 Modules: - gmail_automation.py: 메인 프로그램 - gmail_auth.py: Gmail API 인증 - email_classifier.py: 이메일 분류 로직 - auto_reply.py: 자동 답장 로직 - config.json.example: 설정 예시 Documentation: - 상세한 README.md (설치, 사용법, 트러블슈팅) - Google Cloud Console 설정 가이드 - 실제 효과 측정 데이터
This commit is contained in:
195
auto_reply.py
Normal file
195
auto_reply.py
Normal file
@@ -0,0 +1,195 @@
|
||||
"""
|
||||
자동 답장 모듈
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
import base64
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
|
||||
class AutoReply:
|
||||
"""자동 답장 클래스"""
|
||||
|
||||
def __init__(self, service, config):
|
||||
"""
|
||||
초기화
|
||||
|
||||
Args:
|
||||
service: Gmail API 서비스
|
||||
config: 자동 답장 규칙 설정
|
||||
"""
|
||||
self.service = service
|
||||
self.rules = config.get('auto_reply_rules', [])
|
||||
|
||||
def should_reply(self, email_data):
|
||||
"""
|
||||
자동 답장 필요 여부 판단
|
||||
|
||||
Args:
|
||||
email_data: 이메일 정보
|
||||
|
||||
Returns:
|
||||
True/False
|
||||
"""
|
||||
# 현재 시간
|
||||
current_hour = datetime.now().hour
|
||||
|
||||
for rule in self.rules:
|
||||
condition = rule.get('condition', '')
|
||||
|
||||
# 업무 시간 외 체크
|
||||
if condition == '업무 시간 외':
|
||||
hours = rule.get('hours', {})
|
||||
end_hour = hours.get('end', 9)
|
||||
start_hour = hours.get('start', 18)
|
||||
|
||||
# 업무 시간 외인 경우
|
||||
if current_hour >= start_hour or current_hour < end_hour:
|
||||
return True
|
||||
|
||||
# 특정 키워드 포함 시
|
||||
keywords = rule.get('keywords', [])
|
||||
if keywords:
|
||||
subject = email_data.get('subject', '').lower()
|
||||
body = email_data.get('body', '').lower()
|
||||
full_text = f"{subject} {body}"
|
||||
|
||||
if any(keyword.lower() in full_text for keyword in keywords):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_reply_template(self, email_data):
|
||||
"""
|
||||
답장 템플릿 가져오기
|
||||
|
||||
Args:
|
||||
email_data: 이메일 정보
|
||||
|
||||
Returns:
|
||||
답장 메시지 템플릿
|
||||
"""
|
||||
current_hour = datetime.now().hour
|
||||
|
||||
for rule in self.rules:
|
||||
condition = rule.get('condition', '')
|
||||
|
||||
if condition == '업무 시간 외':
|
||||
hours = rule.get('hours', {})
|
||||
end_hour = hours.get('end', 9)
|
||||
start_hour = hours.get('start', 18)
|
||||
|
||||
if current_hour >= start_hour or current_hour < end_hour:
|
||||
return rule.get('template', '')
|
||||
|
||||
# 키워드 기반 템플릿
|
||||
keywords = rule.get('keywords', [])
|
||||
if keywords:
|
||||
subject = email_data.get('subject', '').lower()
|
||||
body = email_data.get('body', '').lower()
|
||||
full_text = f"{subject} {body}"
|
||||
|
||||
if any(keyword.lower() in full_text for keyword in keywords):
|
||||
return rule.get('template', '')
|
||||
|
||||
return None
|
||||
|
||||
def create_reply_message(self, to, subject, body, thread_id=None):
|
||||
"""
|
||||
답장 메시지 생성
|
||||
|
||||
Args:
|
||||
to: 받는 사람
|
||||
subject: 제목
|
||||
body: 본문
|
||||
thread_id: 스레드 ID (답장인 경우)
|
||||
|
||||
Returns:
|
||||
Gmail API용 메시지 객체
|
||||
"""
|
||||
message = MIMEText(body, 'plain', 'utf-8')
|
||||
message['to'] = to
|
||||
message['subject'] = f"Re: {subject}" if not subject.startswith('Re:') else subject
|
||||
|
||||
raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode('utf-8')
|
||||
|
||||
email_message = {'raw': raw_message}
|
||||
|
||||
if thread_id:
|
||||
email_message['threadId'] = thread_id
|
||||
|
||||
return email_message
|
||||
|
||||
def send_reply(self, original_msg_id, email_data):
|
||||
"""
|
||||
자동 답장 전송
|
||||
|
||||
Args:
|
||||
original_msg_id: 원본 메시지 ID
|
||||
email_data: 이메일 정보
|
||||
|
||||
Returns:
|
||||
성공 여부
|
||||
"""
|
||||
try:
|
||||
# 답장 템플릿 가져오기
|
||||
template = self.get_reply_template(email_data)
|
||||
|
||||
if not template:
|
||||
return False
|
||||
|
||||
# 발신자 추출
|
||||
sender = email_data.get('sender', '')
|
||||
# 이메일 주소만 추출
|
||||
import re
|
||||
email_match = re.search(r'[\w\.-]+@[\w\.-]+', sender)
|
||||
if not email_match:
|
||||
return False
|
||||
|
||||
to_email = email_match.group(0)
|
||||
subject = email_data.get('subject', '제목 없음')
|
||||
|
||||
# 원본 메시지에서 threadId 가져오기
|
||||
original_message = self.service.users().messages().get(
|
||||
userId='me',
|
||||
id=original_msg_id,
|
||||
format='metadata'
|
||||
).execute()
|
||||
|
||||
thread_id = original_message.get('threadId')
|
||||
|
||||
# 답장 메시지 생성
|
||||
reply_message = self.create_reply_message(
|
||||
to=to_email,
|
||||
subject=subject,
|
||||
body=template,
|
||||
thread_id=thread_id
|
||||
)
|
||||
|
||||
# 메시지 전송
|
||||
sent_message = self.service.users().messages().send(
|
||||
userId='me',
|
||||
body=reply_message
|
||||
).execute()
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 답장 전송 실패: {e}")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 테스트
|
||||
config = {
|
||||
"auto_reply_rules": [
|
||||
{
|
||||
"condition": "업무 시간 외",
|
||||
"hours": {"start": 18, "end": 9},
|
||||
"template": "업무 시간 외 자동 답장입니다."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# 테스트는 실제 service 없이는 불가
|
||||
print("AutoReply 모듈 로드 완료")
|
||||
Reference in New Issue
Block a user