Published: 2024-09-13 Last Update: 2024-09-13

Remove PDF Password using Google Apps Script and Google Cloud Function

Take note, this is not a tutorial for removal of password of a document that you don’t know the password of. This is to remove the password of a PDF file that you already know the password of.

In this tutorial, we will use a PDF file attachment from Gmail.

Before we start, it is recommended that you read the whole document first before following the steps so that you’d get the overall picture first.

Overall flow:

  • You receive an email (Gmail) that has a PDF (with password) attachment.
    • The code provided here specifically works for Metrobank credit card bills.
  • Google Apps Script gets the PDF attachment from Gmail.
  • Google Apps Script sends the PDF to another program (Google Cloud Function) to remove the password
  • The program sends back the contents of the PDF
  • Google Apps Script saves the PDF (without password) to Google Drive.

Prerequisite

Debit/Credit Card. The setup that we will do is entirely free. It’s just that we will use a feature in Google Cloud that requires us to set up a billing account.

Important

I am not responsible if your credit card is charged for this. If you follow the steps correctly, it’s basically free. Thus, it is important to read the whole document first before setting everything up.

Setup

Make a copy of the Apps Script

https://drive.google.com/drive/folders/1es0h8CXwAJ0kfb8VwqiFvOyF2MjHrS9h?usp=sharing

Or copy the code here.

Right click then Make a copy.

make a copy

Go to Home. Here’s your copied file. Rename/Move it however you want.

Sign in to Google Cloud

Go to Google Cloud and sign in using your Google account.

Create a GCP Project

Create a project if you don’t already have one or create a new one regardless.

Enter a Project name then click CREATE. Any name you want is okay. This is just an example.

Select the Project

To select the created project, on the upper left, click the dropdown.

Click the project name that we just created.

On the upper left, it should now display our recently created project.

Create Cloud Function

Take note, before you can create a cloud function, you need to add a billing account. This setup that we will do is entirely free. It’s just that a billing account is required for this feature. If you can’t set up a billing account for some reason or you don’t want to set it up, then you cannot proceed.

To set it up, go to Billing then ADD BILLING ACCOUNT. I will not provide all the steps to add a billing account. Just follow the instructions. It’s pretty straightforward.

After you set up the billing account, in the search bar, search for function then click Cloud Run functions.

Click CREATE FUNCTION.

Click ENABLE. Wait for it to finish.

Ensure that these are setup.

  • Environment: Cloud Run function
  • Function name: Name it whatever you want
  • Region: asia-east1 (Taiwan)
    • Select any region you want but this is best if you are in the Philippines
  • Trigger type: HTTPS
  • Authentication: Require authentication

Under RUNTIME, select the least Memory allocated and CPU. You can leave the default if you want.

At the bottom, click Next.

If prompted, click ENABLE. Wait for it to finish.

Select Python 3.12 as Runtime.

Enter main as the Entry point.

In main.py replace existing code and paste this code:

import base64
import os
from io import BytesIO

import functions_framework
from flask import jsonify, send_file
from PyPDF2 import PdfReader, PdfWriter


@functions_framework.http
def main(request):
    payload = request.get_json()

    # Decode the base64 PDF file
    try:
        file_data = base64.b64decode(payload["file"])
    except Exception:
        return jsonify({"detail": "Invalid base64 file encoding"}), 400

    password = payload["password"]
    encrypted_pdf_path = f"/tmp/encrypted_{payload['filename']}"

    # Write the encrypted file to disk
    try:
        with open(encrypted_pdf_path, "wb") as f:
            f.write(file_data)
    except Exception:
        return jsonify({"detail": "Failed to write file to disk"}), 500

    # Decrypt the PDF and return as bytes
    try:
        with open(encrypted_pdf_path, "rb") as infile:
            reader = PdfReader(infile)
            if reader.is_encrypted:
                try:
                    reader.decrypt(password)
                except Exception:
                    return jsonify({"detail": "Incorrect password"}), 400

            writer = PdfWriter()
            for page in reader.pages:
                writer.add_page(page)

            decrypted_pdf_buffer = BytesIO()
            writer.write(decrypted_pdf_buffer)
            decrypted_pdf_buffer.seek(0)

        return send_file(
            decrypted_pdf_buffer,
            as_attachment=True,
            download_name=f"decrypted_{payload['filename']}",
            mimetype="application/pdf",
        )

    except Exception as e:
        return jsonify({"detail": f"Error processing PDF: {e}"}), 500
    finally:
        # Clean up the temporary files
        if os.path.exists(encrypted_pdf_path):
            try:
                os.remove(encrypted_pdf_path)
            except Exception:
                pass

In requirements.txt, add this text:

PyPDF2==3.0.1

At the bottom, click DEPLOY. Wait for it to finish.

Once finished, it will have a check mark.

Copy the URL. We will use this later.

Permission Access

Go to APIs & Services then Credentials.

Click CREATE CREDENTIALS.

Select Service account.

Enter details. You can put whatever you want. Then click CREATE AND CONTINUE.

In the Select a role…

…search for cloud invoker and select Cloud Run Invoker.

Then click CONTINUE.

Click DONE.

Access Key (Credentials)

Back to Credentials, click the created service account.

Go to KEYS, click ADD KEY, then Create new key.

Click CREATE. This will download a json file.

IMPORTANT: No one should have access to this json file other than you. Other people might be able to invoke the cloud function if they get ahold of this file.

Upload the json file somewhere in your Google Drive. Take note to upload this to the same Google account that you will use to run the Apps Script.

Get the file ID. To get it, right click the file, click Share, then Copy link.

In the copied link, this part is the file ID. Copy it and paste it somewhere. We’re going to use it for later.

Google Apps Script

Open the Apps Script you copied earlier. Go to Project Settings.

At the bottom, click Add script property.

Set these properties:

  • CLOUD_FUNCTION_URL: we copied this earlier
  • CREDENTIALS_FILE_ID: we also copied this earlier
  • METROBANK_PASSWORD: password of your Metrobank PDF bill

Once saved, go back to Editor.

Select createTrigger in the dropdown then click Run. This trigger will run the remove pdf password function now (not now now, but maybe within 5 minutes), and once everyday at 8am.

If you just want to run it now, run main instead of createTrigger.

Click Review permissions.

Choose or sign in to your Google account.

Click Advanced.

Then click Go to (unsafe).

Click Allow.

At the bottom, you will see that it started and completed.

Go to Triggers.

As mentioned, this might take a while. Somewhere between 1 second to 5 minutes.

If you see Last run: Disabled and Error rate: 0%, this means that the first trigger ran just fine.

In the Home of your Google Drive, you should see a decrypted_ file.

The file should open without prompting for password.