(20241126) Message-listing done.
This commit is contained in:
+136
-11
@@ -60,11 +60,14 @@ import asyncio
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
# For working with datatypes:
|
# For working with datatypes:
|
||||||
from typing import Dict, Literal, List
|
from typing import Dict, Literal, List, Any
|
||||||
|
|
||||||
# For debugging:
|
# For debugging:
|
||||||
from icecream import IceCreamDebugger
|
from icecream import IceCreamDebugger
|
||||||
|
|
||||||
|
# For computational help:
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
# ***** ****
|
# ***** ****
|
||||||
@@ -507,7 +510,7 @@ class AsyncGMailClient:
|
|||||||
# ┛ ┗┗ ┛┛┗┻┗┫┗ ┛
|
# ┛ ┗┗ ┛┛┗┻┗┫┗ ┛
|
||||||
# ┛
|
# ┛
|
||||||
|
|
||||||
async def __list_messages_in_page(
|
async def __list_messages_on_page(
|
||||||
self,
|
self,
|
||||||
count: int = 100,
|
count: int = 100,
|
||||||
query: str = None,
|
query: str = None,
|
||||||
@@ -515,7 +518,25 @@ class AsyncGMailClient:
|
|||||||
include_spam_and_trash: bool = False,
|
include_spam_and_trash: bool = False,
|
||||||
next_page_token: str = None,
|
next_page_token: str = None,
|
||||||
raise_exception: bool = False
|
raise_exception: bool = False
|
||||||
):
|
) -> Dict[str, Any] | None:
|
||||||
|
|
||||||
|
"""
|
||||||
|
To enlist messages on one page. Google allows at most 500 results on one page. This method respects that
|
||||||
|
pagination limit and returns only what Google gives. This method should be used internally by the class and the
|
||||||
|
class should expose another method that calls this one in loop to get any arbitrary no. of messages as the user
|
||||||
|
desires.
|
||||||
|
DOCUMENTATION:
|
||||||
|
1. https://developers.google.com/gmail/api/reference/rest/v1/users.messages/list
|
||||||
|
2. https://developers.google.com/gmail/api/reference/rest/v1/users.messages#Message
|
||||||
|
:param count: The no. of messages to fetch.
|
||||||
|
:param query: Any query filter that is supported by GMail.
|
||||||
|
:param label_ids: The list of labels' ids that the mails must have on them.
|
||||||
|
:param include_spam_and_trash: Whether, or not, you would like to include mails categorized as spam and trash.
|
||||||
|
:param next_page_token: The token to fetch the next set of results.
|
||||||
|
:param raise_exception: If set to True, any exceptions that occur will be propagated, else they wil be
|
||||||
|
suppressed.
|
||||||
|
:return: The messages that matched the given conditions if the call was successful, else None.
|
||||||
|
"""
|
||||||
|
|
||||||
# Start by assuming failure:
|
# Start by assuming failure:
|
||||||
page_messages = None
|
page_messages = None
|
||||||
@@ -526,14 +547,21 @@ class AsyncGMailClient:
|
|||||||
await self.__ensure_token()
|
await self.__ensure_token()
|
||||||
|
|
||||||
# Build the needed params:
|
# Build the needed params:
|
||||||
params_json = {"count": count}
|
params_json = {
|
||||||
|
"maxResults": count,
|
||||||
|
"includeSpamTrash": include_spam_and_trash
|
||||||
|
}
|
||||||
if query: params_json["q"] = query
|
if query: params_json["q"] = query
|
||||||
if next_page_token: params_json["pageToken"] = next_page_token
|
if next_page_token: params_json["pageToken"] = next_page_token
|
||||||
if label_ids: params_json["labelIds"] = label_ids if isinstance(label_ids, list) else [label_ids]
|
if label_ids: params_json["labelIds"] = label_ids if isinstance(label_ids, list) else [label_ids]
|
||||||
if include_spam_and_trash: params_json["includeSpamTrash"] = include_spam_and_trash
|
|
||||||
|
|
||||||
# Make the API call:
|
# Make the API call:
|
||||||
if not self._debug_only_errors: self._printer("Listing All Labels.", self.__user_email)
|
if not self._debug_only_errors: self._printer(
|
||||||
|
"Listing Messages for Page.",
|
||||||
|
self.__user_email,
|
||||||
|
count,
|
||||||
|
next_page_token
|
||||||
|
)
|
||||||
api_response = await self.__http_client.get(
|
api_response = await self.__http_client.get(
|
||||||
url = f"https://gmail.googleapis.com/gmail/v1/users/{self.__user_email}/messages",
|
url = f"https://gmail.googleapis.com/gmail/v1/users/{self.__user_email}/messages",
|
||||||
headers = {"Authorization": f"Bearer {self.__credentials.token}"},
|
headers = {"Authorization": f"Bearer {self.__credentials.token}"},
|
||||||
@@ -541,19 +569,114 @@ class AsyncGMailClient:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# If the API call failed:
|
# If the API call failed:
|
||||||
if api_response.status_code not in [200]: return labels
|
if api_response.status_code not in [200]: return page_messages
|
||||||
|
|
||||||
# Else we format the response:
|
# Else we format the response:
|
||||||
labels = {label.pop("name"): label for label in api_response.json().get("labels", [])}
|
api_json = api_response.json()
|
||||||
|
page_messages = {
|
||||||
|
"messages": {m.pop("id"): m for m in api_json.get("messages", [])},
|
||||||
|
"nextPageToken": api_json.get("nextPageToken"),
|
||||||
|
"resultSizeEstimate": api_json["resultSizeEstimate"],
|
||||||
|
}
|
||||||
|
|
||||||
# In case something goes wrong along the way:
|
# In case something goes wrong along the way:
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
if raise_exception: raise
|
if raise_exception: raise
|
||||||
self._printer(exception)
|
self._printer(exception)
|
||||||
labels = None
|
page_messages = None
|
||||||
|
|
||||||
# Done here:
|
# Done here:
|
||||||
return labels
|
return page_messages
|
||||||
|
|
||||||
|
async def list_messages(
|
||||||
|
self,
|
||||||
|
count: int = 100,
|
||||||
|
query: str = None,
|
||||||
|
label_ids: List[str] | str = None,
|
||||||
|
include_spam_and_trash: bool = False,
|
||||||
|
raise_exception: bool = False
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
|
||||||
|
"""
|
||||||
|
To enlist mail messages from a user's account.
|
||||||
|
DOCUMENTATION:
|
||||||
|
1. https://developers.google.com/gmail/api/reference/rest/v1/users.messages/list
|
||||||
|
2. https://developers.google.com/gmail/api/reference/rest/v1/users.messages#Message
|
||||||
|
:param count: The no. of messages to fetch.
|
||||||
|
:param query: Any query filter that is supported by GMail.
|
||||||
|
:param label_ids: The list of labels' ids that the mails must have on them.
|
||||||
|
:param include_spam_and_trash: Whether, or not, you would like to include mails categorized as spam and trash.
|
||||||
|
:param raise_exception: If set to True, any exceptions that occur will be propagated, else they wil be
|
||||||
|
suppressed.
|
||||||
|
:return: The messages that matched the given conditions if the call was successful, else None.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Start by assuming failure:
|
||||||
|
messages = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Standard token-refresh check:
|
||||||
|
await self.__ensure_token()
|
||||||
|
|
||||||
|
# We convert the messages to a dict:
|
||||||
|
messages = {
|
||||||
|
"messages": {},
|
||||||
|
"nextPageToken": None,
|
||||||
|
"resultSizeEstimate": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Let's figure out how many times we'll have to loop through the process to retrieve the target no. of
|
||||||
|
# messages. Google allows you to fetch info about at most 500 messages in one go.
|
||||||
|
max_per_call = 500 # ... because Google allows at most 500 entries in one call.
|
||||||
|
iterations_needed = int(math.ceil(count / max_per_call))
|
||||||
|
last_iteration_count = count - int((max_per_call * (iterations_needed - 1)))
|
||||||
|
|
||||||
|
# Run the loop those many times:
|
||||||
|
next_page_token = None
|
||||||
|
results_size_estimate = 0
|
||||||
|
for iteration_no in range(iterations_needed):
|
||||||
|
|
||||||
|
# Figure out the count for this page:
|
||||||
|
if iterations_needed > 1:
|
||||||
|
if iteration_no < (iterations_needed - 1): iteration_count = max_per_call
|
||||||
|
else: iteration_count = last_iteration_count
|
||||||
|
else: iteration_count = count
|
||||||
|
|
||||||
|
# Retrieve the messages for this page:
|
||||||
|
iteration_messages = await self.__list_messages_on_page(
|
||||||
|
count = iteration_count,
|
||||||
|
query = query,
|
||||||
|
label_ids = label_ids,
|
||||||
|
include_spam_and_trash = include_spam_and_trash,
|
||||||
|
next_page_token = next_page_token,
|
||||||
|
raise_exception = True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if no data was received:
|
||||||
|
if iteration_messages is None: break
|
||||||
|
if not iteration_messages.get("messages"): break
|
||||||
|
|
||||||
|
# Now that we know that messages were received:
|
||||||
|
for k, v in iteration_messages["messages"].items(): messages["messages"][k] = v
|
||||||
|
results_size_estimate += iteration_messages["resultSizeEstimate"]
|
||||||
|
|
||||||
|
# If there is no next page after this, we break out of the loop:
|
||||||
|
next_page_token = iteration_messages["nextPageToken"]
|
||||||
|
if next_page_token is None: break
|
||||||
|
|
||||||
|
# Format the final response:
|
||||||
|
messages["nextPageToken"] = next_page_token
|
||||||
|
messages["resultSizeEstimate"] = results_size_estimate
|
||||||
|
|
||||||
|
# In case something goes wrong along the way:
|
||||||
|
except Exception as exception:
|
||||||
|
if raise_exception: raise
|
||||||
|
self._printer(exception)
|
||||||
|
messages = None
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return messages
|
||||||
|
|
||||||
|
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
@@ -631,7 +754,9 @@ if __name__ == "__main__":
|
|||||||
# label_background_color = "#7a2e0b"
|
# label_background_color = "#7a2e0b"
|
||||||
# )))
|
# )))
|
||||||
|
|
||||||
print(json.to_string(await my_gmail.delete_label(label_id = "Label_6")))
|
# print(json.to_string(await my_gmail.delete_label(label_id = "Label_6")))
|
||||||
|
|
||||||
|
print(json.to_string(await my_gmail.list_messages(count = 10)))
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ class GoogleOAuth(OAuthBase):
|
|||||||
credentials.expiry,
|
credentials.expiry,
|
||||||
timezone = date_time.TIMEZONE_UTC
|
timezone = date_time.TIMEZONE_UTC
|
||||||
)
|
)
|
||||||
|
print("EXP. AT:", expires_at)
|
||||||
|
|
||||||
# Return the assessment based on the evaluation with the timezone considered:
|
# Return the assessment based on the evaluation with the timezone considered:
|
||||||
return True if date_time.get_current_utc_date_time() >= expires_at else False
|
return True if date_time.get_current_utc_date_time() >= expires_at else False
|
||||||
|
|||||||
Reference in New Issue
Block a user