Search code examples
python-3.xgmail-api

What are the firewall requirements (Port and Sites) for the python Gmail API and OAuth2.0?


I am planning to use the Gmail API for sending emails.

I will also be using OAuth 2.0 authentication.

The mechanism for authenticating is indicated in the quickstart guide:

from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']


def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        # Call the Gmail API
        service = build('gmail', 'v1', credentials=creds)
        results = service.users().labels().list(userId='me').execute()
        labels = results.get('labels', [])

        if not labels:
            print('No labels found.')
            return
        print('Labels:')
        for label in labels:
            print(label['name'])

    except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
        print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

One example of sending an email:

def gmailAPISendEmail(self, message, userID="me"):
    try:
        service = self.gmailAPIService
        self.GLogger.info("Attempting to send email message")
        try: 
            response = service.users().messages().send(userId=userID, body=message).execute()
        except socket.timeout: 
            pass
        except: 
            self.GLogger.error("Failed to send email message")
            tb = traceback.format_exc()
            self.GLogger.exception(tb)

        try: 
            responseID = str(response['id'])
        except: 
            responseID = "CouldNotParseID"
        
        self.GLogger.info("Successfully sent email message with ID (" + responseID +")")
        return responseID
    except:
        self.GLogger.error("Failed to send email message")
        tb = traceback.format_exc()
        self.GLogger.exception(tb)
        return False

An example of creating an email:

def createEmaiLWithAttachments(self,sendTo, sendFrom, subject,emailMsg , attachments, html=False): 
    try: 
        mimeMessage = MIMEMultipart()
        mimeMessage['to'] = sendTo
        mimeMessage['from'] = sendFrom
        mimeMessage['subject'] = subject
        if html: 
            msg= MIMEText(emailMsg, 'html')
        else: 
            msg= MIMEText(emailMsg)
        mimeMessage.attach(msg)

        for attachment in attachments: 
            attachment_name = attachment[0]
            attachment_instance = attachment[1]
            content_type, encoding = mimetypes.guess_type(attachment_name)
            if content_type is None or encoding is not None:
                content_type = 'application/octet-stream'
            main_type, sub_type = content_type.split('/', 1)    
            if main_type == 'text': 
                msg = MIMEText(attachment_instance, _subtype=sub_type)
            elif main_type == 'image':
                msg = MIMEImage(attachment_instance, _subtype=sub_type)
            elif main_type == 'audio':
                msg = MIMEAudio(attachment_instance, _subtype=sub_type)
            else:
                msg = MIMEBase(main_type, sub_type)
                msg.set_payload(attachment_instance) 
            msg.add_header('Content-Disposition', 'attachment', filename=attachment_name)
            mimeMessage.attach(msg) 

        raw_string = base64.urlsafe_b64encode(mimeMessage.as_string().encode()).decode()
        theMessage = {'raw': raw_string}
        return theMessage
    except: 
        self.GLogger.error("An error occurred in createEmaiLWithAttachments")
        tb = traceback.format_exc()
        self.GLogger.exception(tb)
        return False  

I would like to know what the firewall requirements are?

  • Site/domain requirements
  • Port requirements
  • Protocol type (UDP or TCP)

I tried searching for the port requirements and the site/domain requirements, but I didn't find any information for the Gmail API.

I would need to know the firewall requirements for things such as:

  • Authentication
  • Refresh credentials
  • Send email
  • Fetch emails (messages.list, messages.get, threads.list etc.)

Solution

  • I have opened a Developer Support ticket with Google Workspace Support. An employee from Google who works with APIs has stated the following.

    For general API request/response traffic for Google APIs:

    • Host : *.googleapis.com
    • Port : 443 & 80
    • Protocol : TCP

    For general authentication traffic for Google APIs:

    • Host : *.google.com
    • Port : 443 & 80
    • Protocol : TCP

    The host for the Gmail API request/response traffic specifically, according to here, would be:

    • Host : gmail.googleapis.com
    • Port : 443 & 80
    • Protocol : TCP

    The following is information provided by a contributor to the google-api-python-client Github repository.

    • The python Gmail API uses the endpoints defined in the discovery document for the Gmail V1 API here.
    • The official support page captures the broader Google Workspace firewall settings.
    • The support page is where further questions or clarifications can be obtained.
    • List of IP Addresses needed for Google APIs can be found here. The IP Addresses would need to be allowed for inbound and outbound traffic.
    • This is another resource for API URL requirements.