DEV Community

Cover image for How I Built a Gmail Automation Chrome Extension Using JavaScript and Flask
Tiny Task Pro
Tiny Task Pro

Posted on

How I Built a Gmail Automation Chrome Extension Using JavaScript and Flask

Building browser automation software sounds simple until you start dealing with real-world limitations.

Over the past few months, I've been developing TinyTask Mailer Pro, a Chrome extension that automates Gmail campaigns while keeping the user in control. It integrates Google Sheets, manages campaign progress, supports licensing, and communicates with a Flask backend for usage tracking.

This article isn't about sending spam or bypassing Gmail restrictions. Instead, it's about the engineering decisions, architecture, and lessons I learned while building a production-ready automation tool.

Why Build a Gmail Automation Extension?

Many small businesses, freelancers, recruiters, and sales teams spend hours performing repetitive tasks like:

Opening Gmail
Copying recipient emails
Writing personalized messages
Sending emails one by one
Tracking progress manually

I wanted to build a tool that reduces repetitive work while still keeping the user involved in the process.

The goal was to save time—not replace responsible email practices.

Tech Stack

Here's what powers the project:

Frontend
HTML
CSS
JavaScript
Chrome Extension APIs
Backend
Python
Flask
Gunicorn
Nginx
SQLite
Deployment
Ubuntu VPS
HTTPS API
License server

This combination turned out to be lightweight, affordable, and easy to maintain.

Overall Architecture
Google Sheets


Chrome Extension


Gmail Web Interface


Flask API


SQLite Database

The extension handles browser automation while the backend remains the source of truth for:

License validation
Machine activation
Daily quotas
Usage statistics
Account management

Keeping responsibilities separated made debugging significantly easier.

Reading Data from Google Sheets

Instead of importing CSV files repeatedly, the extension reads campaign data directly from Google Sheets.

Typical columns include:

Name
Email
Subject
Message

This allows users to edit campaigns without rebuilding or re-uploading anything.

Whenever changes are made in Google Sheets, the extension can work with the updated data.

Personalizing Every Email

Nobody likes receiving generic emails.

Each message supports placeholders like:

Hello {Name},

which become

Hello Sarah,

during the sending process.

Simple personalization greatly improves the user experience while keeping implementation straightforward.

Managing Long Campaigns

One challenge appeared very quickly.

What happens if:

Chrome crashes?
Windows restarts?
The browser closes?
The user clicks Stop?

Losing campaign progress wasn't acceptable.

Instead of storing temporary variables in memory, campaign progress is saved using chrome.storage.local.

Information such as:

Current row
Emails sent
Pending emails
Delay settings
Campaign status

can all survive browser restarts.

This became one of the most valuable improvements in the project.

Building Resume Support

Resume functionality sounds simple.

It isn't.

The extension needs to restore:

Current spreadsheet row
Campaign status
Delay timer
Statistics
Current Gmail account

without accidentally sending duplicate emails.

Carefully restoring state while preventing duplicates required much more testing than expected.

Random Delays Matter

Sending hundreds of emails instantly isn't realistic.

Instead, every send operation waits for a randomized interval.

For example:

7 seconds
12 seconds
9 seconds
14 seconds

rather than

10
10
10
10

The goal isn't to "beat" Gmail—it's simply to avoid robotic timing and create a smoother workflow.

Designing the License System

I didn't want all business logic inside the extension.

Instead, the backend validates every license.

The Flask API checks:

License validity
Activated machine
Daily limits
Remaining quota
Expiration status

This keeps sensitive logic off the client side.

Why Use Flask?

I considered several backend frameworks.

Flask won because it offers:

Minimal setup
Fast development
Excellent documentation
Easy REST API creation
Great Python ecosystem

For a lightweight licensing server, it was exactly what I needed.

Keeping the Backend Simple

The database is intentionally straightforward.

Example tables include:

Licenses
Activations
Gmail usage
Admin users

Simple schemas are often easier to maintain than highly complex designs.

Problems I Didn't Expect

Building browser automation introduced challenges I hadn't anticipated.

Some examples:

Gmail UI Changes

Small interface updates can break selectors.

Building resilient selectors became essential.

Asynchronous Timing

Browser automation depends heavily on waiting for elements.

Too early?

The element doesn't exist.

Too late?

The workflow becomes slow.

Finding the right balance required many iterations.

Extension State

Managing state across popup scripts, background scripts, and content scripts was harder than expected.

Keeping everything synchronized became one of the biggest engineering tasks.

What I Learned

A few lessons stand out.

Keep State in One Place

Duplicated state causes bugs.

Using a single source of truth simplified debugging dramatically.

Log Everything

Detailed logging reduced debugging time from hours to minutes.

Expect UI Changes

If you're automating websites, assume they'll change.

Design your automation to fail gracefully.

Build for Recovery

Users will eventually close their browser, lose internet connectivity, or restart their computer.

Recovery is more important than perfection.

Future Improvements

The project is still evolving.

Some features I'm exploring include:

Better campaign analytics
Improved scheduling
More reporting options
Enhanced dashboard metrics
Additional workflow automation

Every version teaches something new.

Final Thoughts

Building browser automation software has been one of the most rewarding projects I've worked on.

It combines frontend development, backend APIs, browser internals, state management, deployment, and user experience into a single product.

If you're interested in Chrome extension development, my advice is simple:

Start with a small feature.

Ship it.

Test it with real users.

Then improve it one iteration at a time.

That's exactly how this project has grown.

If you'd like to see the project that inspired this article, you can explore TinyTask Mailer Pro and other productivity tools at https://tinytask.org.

I'm also interested in hearing how others approach browser automation. What challenges have you run into while building Chrome extensions?

Top comments (0)