🔍 Code Extractor

function send_email_ms365_v1

Maturity: 78

Sends an email through the Microsoft 365 Graph API with support for HTML content, multiple recipients, CC/BCC, and file attachments.

File:
/tf/active/vicechatdev/CDocs single class/utils/notifications.py
Lines:
405 - 499
Complexity:
moderate

Purpose

This function provides a complete email sending solution using Microsoft 365's Graph API. It handles authentication token retrieval, constructs properly formatted email messages with HTML content, manages multiple recipient types (to, cc, bcc), and supports file attachments by encoding them in base64 format. The function is designed for enterprise applications that need to send emails through Microsoft 365 infrastructure with full feature support including attachments and multiple recipient types.

Source Code

def send_email_ms365(to_addresses: List[str], 
                    subject: str, 
                    body_html: str, 
                    body_text: str = None,
                    cc_addresses: List[str] = None,
                    bcc_addresses: List[str] = None,
                    attachments: List[Dict[str, Any]] = None) -> bool:
    """
    Send email through Microsoft 365 Graph API.
    
    Args:
        to_addresses: List of recipient email addresses
        subject: Email subject
        body_html: HTML body content
        body_text: Optional plain text body
        cc_addresses: Optional list of CC recipients
        bcc_addresses: Optional list of BCC recipients
        attachments: Optional list of attachments as dictionaries with keys:
                    'filename', 'content' (bytes), 'content_type'
                    
    Returns:
        Boolean indicating success
    """
    try:
        # Get token
        token = get_ms365_token()
        if not token:
            logger.error("Failed to get MS365 token")
            return False
            
        # Prepare headers
        headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
        
        # Prepare email data
        email_data = {
            'message': {
                'subject': subject,
                'body': {
                    'contentType': 'HTML',
                    'content': body_html
                },
                'toRecipients': [{'emailAddress': {'address': email}} for email in to_addresses]
            },
            'saveToSentItems': 'true'
        }
        
        # Add CC if provided
        if cc_addresses:
            email_data['message']['ccRecipients'] = [
                {'emailAddress': {'address': email}} for email in cc_addresses
            ]
            
        # Add BCC if provided
        if bcc_addresses:
            email_data['message']['bccRecipients'] = [
                {'emailAddress': {'address': email}} for email in bcc_addresses
            ]
            
        # Add attachments if provided
        if attachments:
            email_data['message']['attachments'] = []
            for attachment in attachments:
                # Convert content to base64
                content_bytes = attachment['content']
                if isinstance(content_bytes, str):
                    content_bytes = content_bytes.encode('utf-8')
                content_b64 = base64.b64encode(content_bytes).decode('utf-8')
                
                attachment_data = {
                    '@odata.type': '#microsoft.graph.fileAttachment',
                    'name': attachment['filename'],
                    'contentType': attachment.get('content_type', 'application/octet-stream'),
                    'contentBytes': content_b64
                }
                email_data['message']['attachments'].append(attachment_data)
        
        # Send email through MS Graph API
        response = requests.post(
            'https://graph.microsoft.com/v1.0/users/' + settings.MS365_SENDER_EMAIL + '/sendMail',
            headers=headers,
            json=email_data
        )
        
        if response.status_code >= 200 and response.status_code < 300:
            return True
        else:
            logger.error(f"MS365 API error: {response.status_code}, {response.text}")
            return False
            
    except Exception as e:
        logger.error(f"Error sending email through MS365: {e}")
        return False

Parameters

Name Type Default Kind
to_addresses List[str] - positional_or_keyword
subject str - positional_or_keyword
body_html str - positional_or_keyword
body_text str None positional_or_keyword
cc_addresses List[str] None positional_or_keyword
bcc_addresses List[str] None positional_or_keyword
attachments List[Dict[str, Any]] None positional_or_keyword

Parameter Details

to_addresses: List of email addresses for primary recipients. Must be valid email address strings. At least one recipient is required for the email to be sent.

subject: The subject line of the email as a string. Can be any text content that will appear in the email subject.

body_html: The main email body content in HTML format. This is the primary content that will be displayed to recipients. HTML tags and formatting are supported.

body_text: Optional plain text version of the email body. Currently not used in the implementation but provided for potential fallback scenarios. Defaults to None.

cc_addresses: Optional list of email addresses to be copied (CC) on the email. Each address should be a valid email string. Defaults to None if no CC recipients are needed.

bcc_addresses: Optional list of email addresses to be blind copied (BCC) on the email. Recipients in this list will receive the email but their addresses won't be visible to other recipients. Defaults to None.

attachments: Optional list of dictionaries, where each dictionary represents a file attachment. Each dictionary must contain: 'filename' (str) - name of the file, 'content' (bytes or str) - file content, 'content_type' (str, optional) - MIME type (defaults to 'application/octet-stream'). Content will be automatically base64 encoded.

Return Value

Type: bool

Returns a boolean value: True if the email was successfully sent (HTTP status code 2xx from Microsoft Graph API), False if there was any error including authentication failure, API errors, or exceptions during processing. Check logs for detailed error messages when False is returned.

Dependencies

  • requests
  • msal
  • base64
  • logging

Required Imports

import requests
import base64
import logging
from typing import List, Dict, Any

Usage Example

# Basic email sending
success = send_email_ms365(
    to_addresses=['recipient@example.com'],
    subject='Test Email',
    body_html='<h1>Hello</h1><p>This is a test email.</p>'
)

# Email with CC, BCC, and attachments
with open('report.pdf', 'rb') as f:
    pdf_content = f.read()

attachments = [
    {
        'filename': 'report.pdf',
        'content': pdf_content,
        'content_type': 'application/pdf'
    },
    {
        'filename': 'data.txt',
        'content': b'Sample text content',
        'content_type': 'text/plain'
    }
]

success = send_email_ms365(
    to_addresses=['recipient1@example.com', 'recipient2@example.com'],
    subject='Monthly Report',
    body_html='<p>Please find the attached report.</p>',
    cc_addresses=['manager@example.com'],
    bcc_addresses=['archive@example.com'],
    attachments=attachments
)

if success:
    print('Email sent successfully')
else:
    print('Failed to send email')

Best Practices

  • Ensure get_ms365_token() function is properly implemented and returns valid OAuth2 tokens before calling this function
  • Always check the return value to confirm email was sent successfully before proceeding with dependent operations
  • For attachments, ensure content is in bytes format or will be properly encoded; large attachments may hit API size limits (typically 4MB for Graph API)
  • The body_text parameter is currently unused in the implementation; only body_html is sent to the API
  • Monitor logger output for detailed error messages when emails fail to send
  • Validate email addresses before passing them to the function to avoid API errors
  • Be aware of Microsoft Graph API rate limits when sending bulk emails
  • The function saves sent emails to the Sent Items folder by default (saveToSentItems: true)
  • Attachment content_type defaults to 'application/octet-stream' if not specified; provide specific MIME types for better email client handling
  • Handle exceptions appropriately as the function catches all exceptions and returns False, masking specific error types

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function send_email_ms365 99.1% similar

    Sends an email through Microsoft 365 Graph API with support for HTML content, multiple recipients (to/cc/bcc), and file attachments.

    From: /tf/active/vicechatdev/CDocs/utils/notifications.py
  • function send_email 77.7% similar

    Sends templated emails to one or more recipients using either MS365 or SMTP provider based on configuration, with support for CC, BCC, and attachments.

    From: /tf/active/vicechatdev/CDocs single class/utils/notifications.py
  • function gen_send_email 75.1% similar

    Sends templated emails using either MS365 or SMTP provider, with support for multiple recipients, attachments, and HTML/text rendering.

    From: /tf/active/vicechatdev/CDocs/utils/notifications.py
  • function send_email_smtp 72.6% similar

    Sends emails via SMTP server with support for HTML/text content, multiple recipients (to/cc/bcc), and file attachments.

    From: /tf/active/vicechatdev/CDocs/utils/notifications.py
  • function download_attachments_for_message 61.0% similar

    Downloads file attachments from a Microsoft Graph API email message to a specified local directory, handling duplicate filenames automatically.

    From: /tf/active/vicechatdev/mailsearch/example_script.py
← Back to Browse