How to set a custom sender address using the Gmail API with a delegated service account in Python

I am building a Python web application that sends emails via the Gmail API. I utilize a service account that has domain-wide access to impersonate a specific user ([email protected]).

While the emails are sent without any issues, I want them to display a custom sender name, such as "Custom Sender" <[email protected]>, instead of the impersonated user’s email address.

Whenever I attempt to assign a custom sender in the MIME message, it seems to be ignored, and the emails still reflect [email protected] as the sender. It seems the API may be overriding the specified sender information due to the impersonation.

Is there a known method to define a different sender address when using a service account for impersonation? Are there built-in restrictions that are causing this behavior?

Below is my current code snippet:

import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from googleapiclient.discovery import build
from google.oauth2 import service_account

# Load service account credentials
credentials = service_account.Credentials.from_service_account_file(
    'path/to/credentials.json',
    scopes=['https://www.googleapis.com/auth/gmail.send']
)
credentials = credentials.with_subject('[email protected]')  # User impersonation

# Initialize Gmail service
service = build('gmail', 'v1', credentials=credentials)

# Create the email message
message = MIMEMultipart('alternative')
message.attach(MIMEText("<h1>Test email content</h1>", 'html'))
message.attach(MIMEText("Test email content", 'plain'))
message['Subject'] = 'Test Email Subject'
message['Bcc'] = '[email protected]'

message['Reply-To'] = '[email protected]'  # This is accepted
message['From'] = '"Custom Sender" <[email protected]>'  # This gets overridden

# Sending the email
raw_message = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()}
service.users().messages().send(userId="me", body=raw_message).execute()

The email I receive states:

MIME-Version: 1.0
Reply-To: [email protected]
From: [email protected]

I encountered this exact issue about six months ago when working on an automated notification system. Google’s security policies prevent modification of the From address when using service account delegation - it’s hardcoded to prevent email spoofing attacks. The only reliable solution I found was configuring proper send-as addresses through the Google Workspace admin panel for the impersonated user. You need admin access to add [email protected] as an authorized send-as address for [email protected]. Once configured, the Gmail API will respect your From header since the address is whitelisted. Without this setup, you’re stuck with the authenticated user’s address regardless of what you specify in the MIME headers.

This happens because Google enforces sender authentication when using delegated credentials. The Gmail API will always override the From header with the actual authenticated user’s address to prevent spoofing. However, there are two approaches that might work for your use case. First, you can set up send-as aliases in the Google Workspace admin console for the impersonated user - this allows that user to legitimately send from different addresses. Second, consider using the display name portion while keeping the actual email address, something like message[‘From’] = ‘Custom Sender [email protected]’. The recipient will see “Custom Sender” as the sender name but the actual email address remains unchanged. I’ve found this second approach works well when you just need to customize how the sender appears to recipients without changing the underlying email address.

yeah gmail api basically forces the From header to match the authenticated user when using service accounts. youve hit a known limitation - the api overwrites whatever you put in the From field with the impersonated user’s email. only workaround ive seen is setting up actual email aliases in gsuite/workspace admin console for that domain.