Skip to content

cansinacarer/maillistshield-com

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

466 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MailListShield Logo MailListShield Logo

An email validation SaaS built with microservices architecture

Live Demo API Docs Developer Docs DeepWiki Mail List Shield - Remove spam traps and invalid addresses from your email list | Product Hunt

Uptime Last Commit Test Coverage Code Style

Build & Deploy Pre-Commit Hooks Run Tests Semantic Release Build & Deploy Sphinx Docs

Architecture

sequenceDiagram
  participant flask as 🌢️ 1. Flask Application
  participant db as 🐘 Postgres Database
  participant s3 as ☁️ S3 Bucket
  participant fis as πŸ“ 2. File Intake Service
  participant f2vqp as πŸ“€ 3. File to Validation Queue Publisher
  participant rabbit as 🐰 RabbitMQ
  participant vo as βš™οΈ 5. Validation Orchestrator
  participant evw as βœ‰οΈ 4. Email Validation Worker
  participant rfg as πŸ“Š 6. Results File Generator

  flask ->> s3: Uploads a batch validation job to validation/uploaded/
  flask ->> db: Records the job as pending_start
  s3 ->> fis: Clean up the file, calculate cost
  fis ->> db: Deduct credits from user, update status to file_accepted
  fis ->> s3: Upload cleaned file to validation/in-progress/
  s3 ->> f2vqp: Parse the cleaned file
  f2vqp ->> rabbit: Create a queue per file, publish each row as a message
  f2vqp ->> db: Update status to file_queued
  rabbit ->> vo: Consume N message per queue with Round-Robin
  vo ->> evw: API call to send each message, retrieve result
  vo ->> db: Update progress
  db ->> flask: Update progress in the UI
  vo ->> rabbit: Enqueue the results in each files' queue
  rabbit ->> rfg: Drain results queue of the file when expected message count is reached, build result file
  rfg ->> s3: Upload the result file to /validation/completed
  rfg ->> db: Set status to file_validation_in_progress or file_completed, save the name of the results file
  db ->> flask: Generate download link for results file
Loading

This application consists of 6 event driven services:

  1. Flask SaaS (this repository)
  2. File Intake Service
  3. File to Validation Queue Publisher
  4. Email Validation Worker
  5. Validation Orchestrator
  6. Results File Generator

See a more detailed architecture diagram β†’

Tech Stack

Category Technologies
Backend Python, Flask
Database PostgreSQL, SQLAlchemy ORM
Message Queue RabbitMQ
Infrastructure Docker, AWS S3, CapRover (PaaS deployment)
Security OAuth 2.0, TOTP 2FA, reCAPTCHA, CSRF/XSS protection
Observability Loki, Grafana, Uptime Kuma
CI/CD GitHub Actions, Semantic Release
Payments Stripe (subscriptions + one-time purchases)

Database Model

See the ER diagram
    erDiagram
        
        Users {
            int id PK
            string email
            string password
            string role
            string stripe_customer_id
            int tier_id FK
            bigint credits
            datetime cancel_at
            string firstName
            string lastName
            int newsletter
            datetime member_since
            datetime last_login
            string email_confirmation_code
            datetime last_confirmation_codes_sent
            int number_of_email_confirmation_codes_sent
            int email_confirmed
            string google_avatar_url
            boolean avatar_uploaded
            string totp_secret
            int totp_enabled
        }
        
        Tiers {
            int id PK
            string name
            string label
            string stripe_price_id
        }

        APIKeys {
            int id PK
            int user_id FK
            string key_hash
            string label
            datetime created_at
            datetime expires_at
            datetime last_used
            boolean is_active
        }

        BatchJobs {
            int id PK
            string uid
            int user_id FK
            string status
            string original_file_name
            string uploaded_file
            string accepted_file
            string results_file
            int row_count
            bigint last_pick_row
            datetime last_pick_time
            string source
            int header_row
            string email_column
            datetime uploaded
            datetime started
            datetime finished
            string result
        }

        Users }o--|| Tiers : "has"
        Users ||--o{ APIKeys : "owns"
        Users ||--o{ BatchJobs : "creates"
Loading

Features of the Flask Application

πŸ§‘β€πŸ’» Developer Experience

  • Dev containers:

    • Flask container with pre-configured with:

      • VSCode launch.json for debugging the Flask app,
      • Prettier for HTML, CSS, and JS formatting,
      • Pre-commit hooks for code quality checks,
      • Markdownlint for Markdown formatting,
      • Black for Python code formatting,
      • Commitlint for commit message linting.
    • Postgres as a development database,

    • pgAdmin pre-connected to the development,

    • docs serving the built html files of the Sphinx documentation..

  • CI/CD pipelines with GitHub Actions to:

    • Run pre-commit hooks,
    • Run tests,
    • Automate semantic release for versioning and changelog generation,
    • Build and deploy the documentation,
    • Build and deploy the app to production.

☁️ Deployment

  • 🐳 Dockerized Flask for stateless continuous deployment for scalability,
  • πŸ—„οΈ Database model abstracted with ORM,
  • πŸ“¦ S3 object storage with pre-signed URLs.

πŸ’³ Stripe Integrations

  • Subscriptions,

    • Different subscription tiers,
    • Billing page with Invoices,
    • Integration mechanism:
      • To begin a subscription, we send the user to Stripe with a checkout session,
      • Then listen to Stripe webhook events to process the results,
      • We set the Products in Stripe, then insert their prices into the Tiers table.
  • One-off credit purchases for pre-paid metered usage.

πŸ”’ Authentication

  • Sign up flow,

    • Sign up with Google option,
    • Email validation requirement,
  • Two factor authentication (TOTP only),

  • Forgot password flow,

  • reCAPTCHA v2 for sign up and login forms,

  • Account details page where the user can:

    • Upload a profile picture (stored in S3),
    • Change profile details like first & last name.

πŸ“§ Transactional Emails with SMTP

  • About Stripe subscription changes:

    • Confirmation,
    • Cancellation,
    • Expiration.
  • Email verification on registration,

  • Forgot password.

🚨 Security

  • Cross-Site Request Forgery (CSRF) protection in all forms,
  • Rate limiting: App-wide and form specific limits,
  • Cross-Site Scripting (XSS) protection,
  • Cross-Origin Resource Sharing (CORS) protection.