Search code examples
pythongoogle-apigmailgmail-apigoogle-api-python-client

set custom labels for outgoing gmail api messages in python


I am trying to send emails using the Gmail API client for python (which is part of the Google APIs client). I have gone through the quickstart guide and succeeded in configuring the client so my messages reach their recipients correctly. However, these messages end up in my own email's inbox as well.

Here is the code snippet that generates a message:

def create_message(to, subject, message_text, attachments=None):
    message = MIMEText(message_text) if not attachments else MIMEMultipart()

    # set message metadata
    message['to'] = to
    message['subject'] = subject

    if attachments:
        msg = MIMEText(message_text)
        message.attach(msg)

        for attachment in attachments:
            main_type, sub_type = attachment.content_type.split('/', 1)

            if main_type == 'text':
                msg = MIMEText(await attachment.read(), _subtype=sub_type)
            elif main_type == 'image':
                msg = MIMEImage(await attachment.read(), _subtype=sub_type)
            elif main_type == 'audio':
                msg = MIMEAudio(await attachment.read(), _subtype=sub_type)
            else:
                msg = MIMEBase(main_type, sub_type)
                msg.set_payload(attachment.read())

            msg.add_header('Content-Disposition', 'attachment', filename=attachment.filename)

            message.attach(msg)

    return message

and this is the code snippet that sends the message (assuming that service is a pre-configured instance of the Gmail API)

message = create_message(to, subject, content, attachments)
body = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode('utf8')}

result = (service.users().messages().send(userId='me', body=body).execute())
print(result)

Interestingly, result shows that the message (by default) has the following labels attached to it:

{
...
    "labelIds": [
        "UNREAD",
        "SENT",
        "INBOX"
    ]
...
}

INBOX label is causing the message to appear on my own inbox. My question is how can I set labels for outgoing messages before sending them ? I have gone through the API documentation but it didn't mention how to set custom labels. The only workaround that I could think of is to re-query my inbox with the messageId and remove unnecessary labels.


Solution

  • I have found a decent workaround for the time being:

    Gmail API provides a method modify that updates the label of a message given its ID. So what I did is extract the id from result and pass it to modify alongside the labels to be removed.

    message = create_message(to, subject, content, attachments)
    body = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode('utf8')}
    
    result = service.users().messages().send(userId='me', body=body).execute()
    result = (service.users().messages().modify(
                userId='me',
                id=result['id'], # extracts the sent message id
                body={"removeLabelIds": ["INBOX", "UNREAD"]}, # sets which labels to remove
        )).execute()
    print(result)