Files
OCR/backend/mail_service.py

96 lines
3.7 KiB
Python

import os
import datetime
import mimetypes
import time
from imap_tools import MailBox, AND
from sqlalchemy.orm import Session
from database import SessionLocal, Email, Attachment
from dotenv import load_dotenv
load_dotenv()
MAIL_SERVER = os.getenv("MAIL_SERVER")
MAIL_USERNAME = os.getenv("MAIL_USERNAME")
MAIL_PASSWORD = os.getenv("MAIL_PASSWORD")
MAIL_PORT = int(os.getenv("MAIL_PORT", 993))
def fetch_and_store_emails():
"""
Connects to Gmail, fetches UNREAD emails, stores them in DB, and marks as READ.
"""
print(f"[{datetime.datetime.now()}] Checking for new emails...")
if not MAIL_USERNAME or not MAIL_PASSWORD or MAIL_USERNAME == "your-email@gmail.com":
print("Skipping Email Sync: Credentials not configured.")
return {"status": "skipped", "message": "Credentials not configured"}
db: Session = SessionLocal()
count = 0
try:
# Connect to Inbox
# imap-tools MailBox defaults to SSL (port 993) if not specified, but we make it explicit here.
with MailBox(MAIL_SERVER, port=MAIL_PORT).login(MAIL_USERNAME, MAIL_PASSWORD, initial_folder='INBOX') as mailbox:
# Fetch UNREAD emails
for msg in mailbox.fetch(AND(seen=False)):
print(f"Processing Email: {msg.subject}")
# Check if already exists (optional, but good practice if marking read fails)
# For now using simplistic approach: if we fetch it, we save it.
new_email = Email(
subject=msg.subject,
sender=msg.from_,
body=msg.text or msg.html,
received_date=msg.date,
is_read=False # Consumed by app, but 'seen' on server
)
db.add(new_email)
db.commit() # Commit to get ID
db.refresh(new_email)
# Process Attachments
for i, att in enumerate(msg.attachments):
filename = att.filename
if not filename:
# Fallback for missing filename
ext = mimetypes.guess_extension(att.content_type) or ".bin"
timestamp = int(time.time())
filename = f"attachment_{timestamp}_{i}{ext}"
print(f" - Attachment: {filename}")
new_attachment = Attachment(
email_id=new_email.id,
filename=filename,
content_type=att.content_type,
file_content=att.payload # raw bytes
)
db.add(new_attachment)
db.commit()
# Mark as Read on Server (Auto-done by fetch unless bulk=True or mark_seen=False)
# imap-tools fetches are auto-seen by default.
count += 1
print(f"Sync Complete. {count} new emails.")
return {"status": "success", "count": count}
except Exception as e:
error_msg = str(e)
print(f"Error fetching emails: {error_msg}")
if "AUTHENTICATIONFAILED" in error_msg or "Invalid credentials" in error_msg:
return {
"status": "error",
"message": f"Authentication Failed: {error_msg}. \n[HINT]: If using Gmail, you MUST use an 'App Password', not your login password. Also ensure IMAP is enabled in Gmail Settings."
}
return {"status": "error", "message": error_msg}
finally:
db.close()
if __name__ == "__main__":
fetch_and_store_emails()