Bulk Messaging System

An Electron Desktop app for marketing campaign & broadcast management, using either whatsapp, gmail or a SMTP server

Whats app client integration

Introduction#

whatsapp-web.js Client in the main process with LocalAuth, headless Puppeteer, QR events, send loop, and logout cleanup.

Project structure#

The integration spans three primary areas:

  • Electron main process orchestrating WhatsApp Web client lifecycle and IPC
  • React renderer components managing UI state and user interactions
  • Python backend utilities for advanced contact processing and validation

Core components#

  • Electron main process manages the WhatsApp client lifecycle, Puppeteer configuration, event emission, and cleanup.
  • Preload script exposes a secure IPC API to the renderer for WhatsApp operations.
  • React component handles UI rendering, QR display, status updates, and user actions.
  • Pyodide runtime enables Python-powered manual number parsing directly in the browser.
  • Python backend extracts and validates contacts.

Architecture overview#

The integration follows an event-driven model:

  • Renderer triggers client initialization via IPC
  • Main process creates a Client with LocalAuth and headless Puppeteer
  • QR event emits a data URL for the renderer to display
  • Ready and authenticated events clear QR and update status
  • Disconnected and auth_failure events notify the renderer
  • Message sending loops through contacts with personalization and rate limiting
  • Contact import supports CSV and TXT formats with fallback parsing

Detailed component analysis#

Client initialization pattern with LocalAuth and puppeteer#

  • Client creation uses LocalAuth strategy for automatic session persistence and improved security.
  • Puppeteer runs in headless mode with hardened arguments to improve stability on CI and desktop environments.
  • Event handlers are attached immediately after client instantiation to capture qr, ready, authenticated, auth_failure, and disconnected states.
  • Initialization is triggered via IPC from the renderer and guarded against duplicate instances.

Event-Driven architecture#

  • qr: Converts QR string to a data URL and sends it to the renderer; updates status to prompt scanning.
  • ready: Clears QR display and signals readiness.
  • authenticated: Clears QR display and confirms successful authentication.
  • auth_failure: Emits a failure message with the provided reason.
  • disconnected: Emits disconnection reason and resets the client reference.

QR code generation and display mechanism#

  • QR string received from the client is transformed into a data URL using the QRCode library.
  • The renderer displays the QR code image and handles load/error states.
  • On ready or authenticated events, the QR is cleared to prevent stale displays.

Message sending workflow: personalization, rate limiting, error handling#

  • Personalization: Replaces {{name}} with the contact’s name or defaults to “Friend”.
  • Chat ID construction: Builds @c.us IDs for local and international numbers.
  • Rate limiting: Delays between messages using timeouts to reduce spam risk.
  • Error handling: Per-contact try/catch captures registration checks and send failures; updates status and continues.

Contact import functionality: CSV and TXT#

  • CSV import: Uses a streaming parser to read rows and extract number/name pairs.
  • TXT import: Reads file content and splits lines; attempts to parse comma/tab/pipe-separated values or extract phone numbers from lines.
  • Fallback parsing: Attempts pandas-based parsing first, then falls back to manual CSV parsing if needed.
  • Error handling: Returns empty array on errors and logs failures.

Authentication lifecycle management, session persistence, and cleanup#

  • Session persistence: LocalAuth stores session data locally, enabling clean reconnects.
  • Startup cleanup: Removes cached .wwebjs_cache and .wwebjs_auth directories so the client starts clean.
  • Logout procedure: Calls client.logout(), clears client reference, deletes auth/cache files, and resets UI state.
  • Forced cleanup: Even if logout fails, auth/cache files are removed and UI state is reset.

Dependency analysis#

Key external dependencies and their roles:

  • whatsapp-web.js: Provides the WhatsApp Web client and LocalAuth strategy.
  • qrcode: Converts QR strings to data URLs for display.
  • qrcode-terminal: Alternative terminal-based QR generation (present in dependencies).
  • nodemailer/googleapis: Used for email features (not covered in this page).
  • Puppeteer: Headless browser engine configured in the Electron main process.

Performance considerations#

  • Headless browser configuration: Hardened Chromium flags improve stability and reduce resource contention.
  • Rate limiting: Delays between messages help avoid rate limits and detection mechanisms.
  • Streaming parsers: CSV parsing uses streaming to handle large files efficiently.
  • Cleanup: Removing auth/cache directories prevents accumulation of stale session data.

Troubleshooting guide#

Common issues and resolutions:

  • QR code not loading: Verify network connectivity, restart the app, and clear browser cache. The renderer includes retry logic on QR load failure.
  • Authentication failures: Check device link instructions, ensure phone has active internet, and retry. The client emits auth_failure with a reason.
  • Disconnections: The client emits disconnected with a reason; restart the client to reconnect.
  • Contact import errors: Confirm file format compatibility (CSV/TXT), UTF-8 encoding, and proper column headers. The backend includes fallback parsing strategies.
  • Logout issues: The logout handler attempts logout and forces cleanup if it fails, so auth/cache files are removed.

Conclusion#

One client instance at a time. Re-init after logout or auth failure rather than trying to revive a half-dead Client object.