(20241127) Google API OAuth2.0 support ready!

This commit is contained in:
2024-11-27 16:54:08 +05:30
parent 535f998272
commit 485a8bd486
8 changed files with 177 additions and 634 deletions
+28 -8
View File
@@ -34,6 +34,8 @@
# To make sibling directories accessible for imports:
import sys
from http.client import responses
sys.path.append(".")
sys.path.append("..")
@@ -47,7 +49,6 @@ from utils_v2.date_time import date_time
from utils_v2.mail import mail_parser
# My Google utils:
from utils_v2.oauth.services.goog import GoogleOAuth
from utils_v2.goog.base import AsyncGoogleBase
from utils_v2.goog.models.data.auth_tokens import GoogleAuthTokens
from utils_v2.goog.models.data.api_call import GoogleApiResponse
@@ -88,7 +89,12 @@ import base64
# *****************************************************************************************************************
# --- Nothing Yet
# Google Scopes:
SCOPES_GMAIL_MAIL_MANAGEMENT = [
r"https://www.googleapis.com/auth/gmail.modify",
r"https://www.googleapis.com/auth/gmail.labels"
]
SCOPES_GMAIL_FULL = [r"https://mail.google.com/"]
# *****************************************************************************************************************
@@ -618,7 +624,7 @@ class AsyncGMailClient(AsyncGoogleBase):
if api_response.httpCode in [200]:
api_response.success = True
api_json = await api_response.get_json()
raw_message = base64.urlsafe_b64decode(api_json["raw"])
raw_message = base64.urlsafe_b64decode(api_json["raw"]).decode()
if return_raw: api_response.data = raw_message
else:
parsed_message = mail_parser.parse(raw_message)
@@ -897,19 +903,33 @@ if __name__ == "__main__":
# Create an instance of the client:
my_gmail = AsyncGMailClient(
service_name = "gmail",
client_id = secrets_dict["web"]["client_id"],
client_secret = secrets_dict["web"]["client_secret"],
oauth_json = secrets_dict,
http_client = test_client,
redirect_url = r"https://api.thecaoffice.com/converse/mail/callback/gmail",
scopes = [
r"https://www.googleapis.com/auth/gmail.modify",
r"https://www.googleapis.com/auth/gmail.labels"
],
debug = True,
debug_prefix = "GMail (M) | ",
debug_only_errors = False
)
# Request Auth:
# print("AUTH URL:", await my_gmail.get_authorization_url(
# state = "User123-Bhopli"
# ))
# Get tokens from callback:
# print("TOKENS:", await my_gmail.get_authorization_tokens(
# redirect_url = r"https://api.thecaoffice.com/converse/mail/callback/gmail?state=User123-Bhopli..."
# ))
# Create a sample mail:
my_mail = GMailMessage(
from_email = "pskhushal@gmail.com",
to_email = "orangebhopli@gmail.com",
subject = "Re: Bhopli is the best! (Thread Test)",
subject = "Bhopli is the best! (Parts Sequence Test)",
cc_emails = None,
bcc_emails = None
)
@@ -936,7 +956,7 @@ if __name__ == "__main__":
</html>
"""
)
my_mail.add_text("This is how you should pet her 👇")
my_mail.add_text("(3rd part - text) This is how you should pet her 👇")
my_mail.add_inline_image(r"../../../data/images/cat_petting.png")
my_mail.add_attachment(r"../../../data/pdf/sample_label.pdf")
# print(my_mail.get_raw_message(as_base64 = False))
@@ -945,7 +965,7 @@ if __name__ == "__main__":
response = await my_gmail.send_message(
tokens = test_tokens,
message = my_mail,
thread_id = "1936caffb67996d3"
thread_id = None
)
print("SUCCESS:", response.success)
print("SUMMARY:", response.to_markdown())
+17 -3
View File
@@ -180,12 +180,19 @@ class GMailMessage:
self.message.attach(MIMEText(html_text, "html"))
def add_inline_image(self, image_file, content_id = None):
def add_inline_image(
self,
image_file: str | io.BytesIO,
file_name: str = None,
content_id: str = None
):
"""
Add an inline image to the body of the mail.
NOTE: This is NOT the same as sending an image as an attachment.
:param image_file: The image data to attach to the mail body.
:param file_name: The name of the file. This is the same name by which it will be downloaded. You need not
specify this if the input file is specified as a path. Needed when you give the input file as a buffer.
:param content_id: Inline images are inserted via HTML bocks. This field identifies the image resource. If not
specified, I will generate a random string. You may write a custom value here if you know what you are
doing. For most use cases, please ignore this field.
@@ -195,6 +202,7 @@ class GMailMessage:
# Read the image as bytes:
image_bytes = None
if type(image_file) is str:
file_name = file_name or os.path.split(image_file)[-1]
with open(image_file, "rb") as opened_image_file:
image_bytes = opened_image_file.read()
if type(image_file) is io.BytesIO:
@@ -217,7 +225,13 @@ class GMailMessage:
# Then add the image:
image_part = MIMEImage(image_bytes)
image_part.add_header("Content-ID", f"<{content_id}>")
image_part.add_header(
"Content-ID", f"<{content_id}>"
)
image_part.add_header(
"Content-Disposition",
f"inline; filename=\"{file_name}\"",
)
self.message.attach(image_part)
def add_attachment(
@@ -253,7 +267,7 @@ class GMailMessage:
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename= {file_name}",
f"attachment; filename=\"{file_name}\"",
)
self.message.attach(part)