Hello everyone,
I’m working on an automation project code that will help us download email attachments from HubSpot to store them locally as well.
To summarize the logic, the following functions are supposed to retrieve the file URL using its ID, and then download the URL’s contents via a simple GET request.
Here’s the code:
def get_file_download_url(file_id, access_token, logger) : """Fetch the real HubSpot download URL for a file.""" try: url = f"https://api.hubapi.com/files/v3/files/{file_id}" headers = {"Authorization": f"Bearer {access_token}"} resp = requests.get(url, headers=headers) resp.raise_for_status() data = resp.json() return data.get("url"), data.get("name") except Exception as e: logger.error(f"Error fetching file details for {file_id}: {e}") return None, Nonedef download_file_from_hubspot(file_id, access_token, logger) : """Download a HubSpot file by fileId using secure API request.""" try: file_url, file_name = get_file_download_url(file_id, access_token, logger) if not file_url: logger.error(f"No download URL found for file {file_id}") return None with tempfile.NamedTemporaryFile(delete=False) as tmp: tmp_path = tmp.name logger.debug(f"Downloading {file_name or file_id} to {tmp_path}") headers = {"Authorization": f"Bearer {access_token}"} with requests.get(file_url, headers=headers, stream=True, timeout=20) as r: r.raise_for_status() with open(tmp_path, "wb") as f: for chunk in r.iter_content(chunk_size=8192) : if chunk: f.write(chunk) logger.info(f"Downloaded file {file_name or file_id} successfully.") return tmp_path except requests.exceptions.RequestException as e: logger.error(f"Error downloading HubSpot file {file_id}: {str(e)}") return None
The problem I’ve encountered is that every time the code is executed, no matter which file ID is used, the downloaded file contains only the HTML of the HubSpot authorisation page.
How can I bypass or handle this authorisation page? Is there a better way to download email attachments via API?
Thanks to everyone in advance.