I'm currently using MS Graph API to send emails, but this doesn't include email signatures. I have explored/me/mailBoxSettings
API to check for signatures, but it doesn't have any info about signatures. I need to create a Django API for a React frontend client to send emails.
Do I need to explore third-party services like SendGrid or custom SMTP server?
I found a way rather a workaround to fetch the signature by using the sent items of user's mailbox. Approach:
https://graph.microsoft.com/v1.0/me/mailFolders/sentitems/messages?$top=10
Signature
as id. def send_email(self, access_token, to_email, subject, body):
"""
Send email using access token and include the signature image as an inline attachment.
:param access_token: OAuth access token
:param to_email: Recipient email address
:param subject: Email subject
:param body: Email body
:return: Boolean indicating success
"""
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
inline_attachments = []
try:
# Step 1: Fetch the last sent email to extract the signature
response = requests.get(
f'https://graph.microsoft.com/v1.0/me/mailFolders/sentitems/messages?$top=1',
headers=headers
)
# print(f"response: {response.json()}")
if response.status_code == 200:
response_body = response.json()['value'][0]['body']['content']
message_id = response.json()['value'][0]['id']
sender_name = response.json()['value'][0]['sender']['emailAddress']['name']
user_name=sender_name.split(", ")
print(f"User name: {user_name}")
soup = BeautifulSoup(response_body, 'html.parser')
# Step 2: Extract the signature element
signature_elements = soup.find_all(id="Signature")
# print(f"signature elements: {signature_elements}")
signature_element = None
for signature in signature_elements:
print(f"Signature text: {signature.get_text()}")
for name in user_name:
if name in signature.get_text():
print(f"Matching signature found.{name}")
signature_element = signature
break
if signature_element:
# print(f"Signature HTML found.{signature_element}")
# Step 3: Handle inline images in the signature
img_tags = signature_element.find_all("img", {"src": lambda x: x and x.startswith("cid:")})
for img_tag in img_tags:
cid = img_tag["src"].replace("cid:", "") # Extract the Content-ID
# Fetch the attachment using the Content-ID
attachment_response = requests.get(
f'{self.graph_endpoint}/me/messages/{message_id}/attachments',
headers=headers
)
if attachment_response.status_code == 200:
attachments = attachment_response.json().get("value", [])
for attachment in attachments:
if attachment.get("contentId") == cid:
# Decode the base64 content of the attachment
image_data = attachment.get("contentBytes")
content_type = attachment.get("contentType")
# Add the image as an inline attachment
inline_attachment = {
"@odata.type": "#microsoft.graph.fileAttachment",
"name": attachment.get("name"),
"contentBytes": image_data,
"contentType": content_type,
"contentId": cid,
"isInline": True
}
inline_attachments.append(inline_attachment)
break
# Convert the signature element back to HTML
user_signature = str(signature_element)
else:
print("No signature found in the email.")
user_signature = None
else:
print(f"Failed to fetch the last sent email. Status code: {response.status_code}")
user_signature = None
# Step 4: Append the signature to the email body
if user_signature:
body += f"<br>{user_signature}"
# Step 5: Construct the email message
email_message = {
"message": {
"subject": subject,
"body": {
"contentType": "HTML",
"content": body
},
"toRecipients": [
{
"emailAddress": {
"address": to_email
}
}
],
"attachments": inline_attachments # Add inline attachments here
},
"saveToSentItems": "true"
}
# Step 6: Send the email
mail_response = requests.post(
f'https://graph.microsoft.com/v1.0/me/sendMail',
json=email_message,
headers=headers
)
if mail_response.status_code in [200, 201, 202]:
print("Email sent successfully with inline image!")
return True
else:
print(f"Failed to send email. Status code: {mail_response.status_code}")
print("Response:", mail_response.text)
return False
except Exception as e:
print(f"Error in sending email: {str(e)}")
return False