You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
# backend/app/connectors/mail/real_imap.py — IMAP(HEY/일반) sync 커넥터 (phase-13)
|
|
# 로컬 우선 대안: OAuth 불필요. UID SEARCH SINCE 증분 → 동일 normalize_email 로 귀결.
|
|
import email as email_lib
|
|
import imaplib
|
|
from datetime import UTC, datetime
|
|
|
|
from sqlmodel import Session
|
|
|
|
from ...crypto import decrypt_token # token_enc 에 {host,user,password} 저장
|
|
from ..base import BaseConnector, NormalizedRecord, RawRecord
|
|
from .normalize import normalize_email, upsert_email
|
|
|
|
|
|
class ImapConnector(BaseConnector):
|
|
domain = "mail"
|
|
entity_type = "email"
|
|
|
|
def fetch(self, session: Session, *, full: bool = False):
|
|
creds = decrypt_token(self.account.token_enc)
|
|
if not creds:
|
|
raise PermissionError("imap credentials missing")
|
|
m = imaplib.IMAP4_SSL(creds["host"])
|
|
m.login(creds["user"], creds["password"])
|
|
m.select("INBOX")
|
|
crit = "ALL" if full else "UNSEEN"
|
|
_typ, data = m.search(None, crit)
|
|
for uid in data[0].split():
|
|
_t, msgdata = m.fetch(uid, "(RFC822)")
|
|
raw_bytes = msgdata[0][1]
|
|
msg = email_lib.message_from_bytes(raw_bytes)
|
|
payload = {
|
|
"from": msg.get("From", ""),
|
|
"subject": msg.get("Subject", ""),
|
|
"to": msg.get("To", "나"),
|
|
"preview": (
|
|
(msg.get_payload(decode=False) or "")[:120] if not msg.is_multipart() else ""
|
|
),
|
|
"date": msg.get("Date", "방금"),
|
|
}
|
|
yield RawRecord(
|
|
external_id=msg.get("Message-ID", uid.decode()),
|
|
payload=payload,
|
|
etag=msg.get("Date", ""),
|
|
external_updated_at=datetime.now(UTC),
|
|
)
|
|
m.logout()
|
|
|
|
def normalize(self, raw: RawRecord) -> NormalizedRecord:
|
|
return normalize_email(self.account, raw, provider="imap")
|
|
|
|
def write(self, session: Session, norm: NormalizedRecord):
|
|
return upsert_email(session, norm)
|
|
|
|
def event_for(self, norm, entity_id):
|
|
return "mail.received"
|