Implement email retrieval functionality and enhance authentication flow in the API
Browse files- app/controllers/mail.py +73 -6
- app/router/auth.py +13 -19
- app/router/mail.py +29 -13
app/controllers/mail.py
CHANGED
@@ -1,20 +1,19 @@
|
|
1 |
"""Module to search and list emails from Gmail."""
|
2 |
-
import os
|
3 |
-
import re
|
4 |
import base64
|
5 |
import hashlib
|
|
|
|
|
6 |
from datetime import datetime, timedelta
|
7 |
from venv import logger
|
8 |
-
from ics import Calendar
|
9 |
|
10 |
-
from
|
11 |
from langchain_community.document_loaders import (
|
|
|
12 |
PyPDFLoader,
|
13 |
UnstructuredExcelLoader,
|
14 |
-
CSVLoader,
|
15 |
UnstructuredImageLoader,
|
16 |
)
|
17 |
-
|
18 |
from models.db import vectorstore
|
19 |
|
20 |
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
|
@@ -230,3 +229,71 @@ def collect(service, query=(datetime.today() - timedelta(days=10)).strftime("aft
|
|
230 |
return f"{len(emails)} emails added to the collection."
|
231 |
else:
|
232 |
logger.info("No emails found after two weeks ago.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
"""Module to search and list emails from Gmail."""
|
|
|
|
|
2 |
import base64
|
3 |
import hashlib
|
4 |
+
import os
|
5 |
+
import re
|
6 |
from datetime import datetime, timedelta
|
7 |
from venv import logger
|
|
|
8 |
|
9 |
+
from ics import Calendar
|
10 |
from langchain_community.document_loaders import (
|
11 |
+
CSVLoader,
|
12 |
PyPDFLoader,
|
13 |
UnstructuredExcelLoader,
|
|
|
14 |
UnstructuredImageLoader,
|
15 |
)
|
16 |
+
from langchain_core.documents import Document
|
17 |
from models.db import vectorstore
|
18 |
|
19 |
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
|
|
|
229 |
return f"{len(emails)} emails added to the collection."
|
230 |
else:
|
231 |
logger.info("No emails found after two weeks ago.")
|
232 |
+
|
233 |
+
|
234 |
+
def get_emails(service, query=(datetime.today() - timedelta(days=10)).strftime("after:%Y/%m/%d"), max_results=10):
|
235 |
+
"""
|
236 |
+
Retrieve a list of emails with subject, to, from, cc, and content.
|
237 |
+
|
238 |
+
Args:
|
239 |
+
mailservice: Authenticated Gmail API service instance
|
240 |
+
max_results: Maximum number of emails to retrieve
|
241 |
+
|
242 |
+
Returns:
|
243 |
+
List of dictionaries containing email details
|
244 |
+
"""
|
245 |
+
try:
|
246 |
+
# List messages
|
247 |
+
response = service.users().messages().list(userId='me', q=query, maxResults=max_results).execute()
|
248 |
+
messages = response.get('messages', [])
|
249 |
+
email_list = []
|
250 |
+
|
251 |
+
if not messages:
|
252 |
+
return email_list
|
253 |
+
|
254 |
+
for message in messages:
|
255 |
+
# Get detailed message data
|
256 |
+
msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute()
|
257 |
+
headers = msg['payload']['headers']
|
258 |
+
|
259 |
+
# Initialize email details
|
260 |
+
email_data = {
|
261 |
+
'subject': '',
|
262 |
+
'from': '',
|
263 |
+
'to': '',
|
264 |
+
'cc': '',
|
265 |
+
'content': '',
|
266 |
+
'snippet': msg['snippet'] if 'snippet' in msg else '',
|
267 |
+
}
|
268 |
+
|
269 |
+
# Extract headers
|
270 |
+
for header in headers:
|
271 |
+
name = header['name'].lower()
|
272 |
+
if name == 'subject':
|
273 |
+
email_data['subject'] = header['value']
|
274 |
+
elif name == 'from':
|
275 |
+
email_data['from'] = header['value']
|
276 |
+
elif name == 'to':
|
277 |
+
email_data['to'] = header['value']
|
278 |
+
elif name == 'cc':
|
279 |
+
email_data['cc'] = header['value']
|
280 |
+
|
281 |
+
# Extract content
|
282 |
+
if 'parts' in msg['payload']:
|
283 |
+
for part in msg['payload']['parts']:
|
284 |
+
if part['mimeType'] == 'text/plain':
|
285 |
+
email_data['content'] = base64.urlsafe_b64decode(part['body']['data']).decode('utf-8')
|
286 |
+
break
|
287 |
+
elif part['mimeType'] == 'text/html':
|
288 |
+
email_data['content'] = base64.urlsafe_b64decode(part['body']['data']).decode('utf-8')
|
289 |
+
break
|
290 |
+
elif 'data' in msg['payload']['body']:
|
291 |
+
email_data['content'] = base64.urlsafe_b64decode(msg['payload']['body']['data']).decode('utf-8')
|
292 |
+
|
293 |
+
email_list.append(email_data)
|
294 |
+
|
295 |
+
return email_list
|
296 |
+
|
297 |
+
except Exception as e:
|
298 |
+
print(f"An error occurred: {e}")
|
299 |
+
return []
|
app/router/auth.py
CHANGED
@@ -2,10 +2,10 @@
|
|
2 |
import os
|
3 |
import json
|
4 |
import pickle
|
5 |
-
from cv2 import log
|
6 |
from fastapi import APIRouter, Request
|
7 |
from fastapi.responses import JSONResponse
|
8 |
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
|
9 |
from googleapiclient.discovery import build
|
10 |
|
11 |
router = APIRouter(tags=["auth"])
|
@@ -74,25 +74,19 @@ async def google_callback(state: str, code: str, scope: str, request: Request):
|
|
74 |
flow.redirect_uri = REDIRECT_URI
|
75 |
flow.fetch_token(code=code)
|
76 |
credentials = flow.credentials
|
|
|
77 |
request.state.session["credential"] = json.loads(credentials.to_json())
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
#
|
89 |
-
# refresh_token=cred_dict["refresh_token"],
|
90 |
-
# token_uri=cred_dict["token_uri"],
|
91 |
-
# client_id=cred_dict["client_id"],
|
92 |
-
# client_secret=cred_dict["client_secret"],
|
93 |
-
# scopes=cred_dict["scopes"],
|
94 |
-
# ))
|
95 |
-
service = build("gmail", "v1", credentials=credentials)
|
96 |
profile = service.users().getProfile(userId="me").execute()
|
97 |
with open(f"cache/{profile['emailAddress']}.pickle", "wb") as token:
|
98 |
pickle.dump(credentials, token)
|
|
|
2 |
import os
|
3 |
import json
|
4 |
import pickle
|
|
|
5 |
from fastapi import APIRouter, Request
|
6 |
from fastapi.responses import JSONResponse
|
7 |
from google_auth_oauthlib.flow import InstalledAppFlow
|
8 |
+
from google.oauth2.credentials import Credentials
|
9 |
from googleapiclient.discovery import build
|
10 |
|
11 |
router = APIRouter(tags=["auth"])
|
|
|
74 |
flow.redirect_uri = REDIRECT_URI
|
75 |
flow.fetch_token(code=code)
|
76 |
credentials = flow.credentials
|
77 |
+
print(credentials.to_json())
|
78 |
request.state.session["credential"] = json.loads(credentials.to_json())
|
79 |
+
cred_dict = (request.state.session.get("credential"))
|
80 |
+
service = build("gmail", "v1", credentials=Credentials(
|
81 |
+
token=cred_dict["token"],
|
82 |
+
# refresh_token=cred_dict["refresh_token"],
|
83 |
+
# token_uri=cred_dict["token_uri"],
|
84 |
+
# client_id=cred_dict["client_id"],
|
85 |
+
# client_secret=cred_dict["client_secret"],
|
86 |
+
# scopes=cred_dict["scopes"],
|
87 |
+
))
|
88 |
+
print(service)
|
89 |
+
# service = build("gmail", "v1", credentials=credentials)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
profile = service.users().getProfile(userId="me").execute()
|
91 |
with open(f"cache/{profile['emailAddress']}.pickle", "wb") as token:
|
92 |
pickle.dump(credentials, token)
|
app/router/mail.py
CHANGED
@@ -46,16 +46,32 @@ def collect(query: MailReqData, request: Request):
|
|
46 |
logger.error("Error collecting mail: %s", e)
|
47 |
return JSONResponse(content={"error": str(e)}, status_code=500)
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
logger.error("Error collecting mail: %s", e)
|
47 |
return JSONResponse(content={"error": str(e)}, status_code=500)
|
48 |
|
49 |
+
@router.get("")
|
50 |
+
def get(query: MailReqData, request: Request):
|
51 |
+
"""
|
52 |
+
Handles the chat POST request.
|
53 |
+
|
54 |
+
Args:
|
55 |
+
query (ReqData): The request data containing the query parameters.
|
56 |
+
|
57 |
+
Returns:
|
58 |
+
str: The generated response from the chat function.
|
59 |
+
"""
|
60 |
+
if os.path.exists(f"cache/{query.email}.pickle"):
|
61 |
+
with open(f"cache/{query.email}.pickle", "rb") as token:
|
62 |
+
credentials = pickle.load(token)
|
63 |
+
else:
|
64 |
+
cred_dict = request.state.session.get("credential")
|
65 |
+
credentials = Credentials(
|
66 |
+
token=cred_dict["token"],
|
67 |
+
refresh_token=cred_dict["refresh_token"],
|
68 |
+
token_uri=cred_dict["token_uri"],
|
69 |
+
client_id=cred_dict["client_id"],
|
70 |
+
client_secret=cred_dict["client_secret"],
|
71 |
+
scopes=cred_dict["scopes"],
|
72 |
+
)
|
73 |
+
mailservice = build("gmail", "v1", credentials=credentials)
|
74 |
+
print("query: ", query.query)
|
75 |
+
result = mail.get_emails(mailservice, query.query)
|
76 |
+
print(result)
|
77 |
+
return JSONResponse(content= result)
|