Bulk Messaging System

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

Renderer process architecture

Introduction#

Renderer-side architecture: BulkMailer owns tab state and IPC calls; forms stay presentational where possible.

Project structure#

The renderer process is organized around a small React application bootstrapped in Electron. The UI is composed of a single-page layout with a sidebar navigation, top bar, and tabbed content areas for Gmail, SMTP, and WhatsApp messaging. Business logic is delegated to Electron main process handlers via IPC.

Core components#

  • main.jsx: Creates the React root and renders the App component.
  • App.jsx: Minimal wrapper that renders the central BulkMailer component.
  • BulkMailer.jsx: Central orchestrator managing shared state, tab routing, and Electron IPC interactions. It wires UI forms to backend services and manages real-time updates from WhatsApp events.
  • Sidebar.jsx: Navigation controls switching between Gmail, SMTP, and WhatsApp tabs.
  • TopBar.jsx: Dynamic header reflecting the active tab.
  • WhatsAppForm.jsx: Full-featured WhatsApp UI with QR display, contact management, message composition, and activity logs.
  • GmailForm.jsx: Gmail authentication and bulk email composition with import and progress reporting.
  • SMTPForm.jsx: SMTP configuration and bulk email composition with import and progress reporting.
  • preload.js: Exposes a controlled electronAPI to the renderer process via contextBridge.
  • main.js: Registers IPC handlers for Gmail, SMTP, WhatsApp, and file operations.
  • gmail-handler.js: Implements Gmail OAuth flow and bulk email sending with progress events.
  • smtp-handler.js: Implements SMTP transport verification and bulk sending with progress events.
  • pyodide.js: Loads Pyodide and executes Python phone number parsing logic.
  • parse_manual_numbers.py: Parses manual phone numbers and normalizes them.

Architecture overview#

The renderer process follows a unidirectional data flow:

  • UI components render based on React state.
  • User actions trigger BulkMailer methods that call electronAPI (IPC invocations).
  • Electron main process handlers execute business logic and emit events back to the renderer.
  • Real-time updates are subscribed to via onX callbacks exposed through electronAPI.

Detailed component analysis#

Component hierarchy and communication#

  • Entry points: main.jsx creates the root; App.jsx renders BulkMailer.
  • BulkMailer composes Sidebar, TopBar, and conditionally renders the active form (WhatsAppForm, GmailForm, SMTPForm).
  • Forms receive props for state and callbacks, enabling centralized state management in BulkMailer.
  • WhatsAppForm maintains its own local logs and displays results from BulkMailer.

State management patterns#

  • Centralized state in BulkMailer: activeTab, Gmail auth flag, email list, subject, message, delay, SMTP config, sending flags, and results arrays.
  • Form components receive state and setters as props, enabling unidirectional data flow.
  • WhatsApp-specific state (contacts, message, status, QR, sending, results) is isolated within BulkMailer but surfaced to the form.
  • Local state in forms: WhatsAppForm maintains its own log entries and toggles for manual input.

Key patterns:

  • useState for primitive and object state.
  • useEffect for initialization and event subscriptions (WhatsApp status, QR, send status).
  • Callback props for actions, keeping UI pure and testable.

Electron IPC integration#

  • Preload bridge exposes electronAPI with typed methods and event listeners.
  • Renderer invokes ipcRenderer.invoke for request/response flows (authentication, sending, file import).
  • Main process registers ipcMain.handle for each capability and emits events for streaming updates.
  • Handlers execute business logic and return structured results; progress events are sent via event.sender.send.

UI rendering pipeline and lifecycle#

  • Bootstrapping: main.jsx mounts App; App renders BulkMailer.
  • Mounting effects: BulkMailer checks Gmail auth and subscribes to WhatsApp events on mount.
  • Event cleanup: Effects return removal functions to avoid leaks.
  • Tab rendering: Active tab determines which form is rendered; forms receive only necessary props.
  • WhatsApp lifecycle: Start client initializes a Client with LocalAuth; QR and status events are emitted; send messages loop with delays; logout clears session and cache.

WhatsApp integration details#

  • QR generation: Main process converts QR string to data URL and sends to renderer.
  • Status updates: Ready, authenticated, disconnected, and error statuses are broadcast.
  • Message sending: Iterates contacts, checks registration, sends with delays, and emits per-contact progress.
  • Contacts import: Supports CSV and TXT; TXT format allows “number,name” or “name,number”.
  • Manual numbers: Uses Pyodide to run Python parser for flexible input formats.

Gmail and SMTP integration details#

  • Gmail:
  • OAuth2 flow with BrowserWindow and redirect handling.
  • Stores tokens via electron-store; verifies presence before sending.
  • Emits email-progress events for granular feedback.
  • SMTP:
  • Validates config, creates Nodemailer transport, verifies connectivity.
  • Sends HTML emails with rate-limiting delays.
  • Optionally persists partial config for convenience.

Dependency analysis#

  • UI depends on BulkMailer for state and IPC orchestration.
  • Forms depend on props passed by BulkMailer; they remain presentation-focused.
  • Preload bridge mediates all IPC calls; main.js centralizes handler registration.
  • Handlers encapsulate business logic and external service integrations.
  • Pyodide enables Python-based phone number parsing without Node native modules.

Performance considerations#

  • Rate limiting: Both Gmail and SMTP handlers introduce delays between messages to respect provider limits.
  • Streaming progress: email-progress events keep UI responsive and informed during long operations.
  • Conditional rendering: Only the active tab is mounted, reducing DOM and memory overhead.
  • Cleanup: useEffect return functions unsubscribe event listeners to prevent leaks.
  • Lazy loading: Pyodide is loaded on demand to minimize initial bundle size.
  • Headless browser: WhatsApp client runs headless to reduce resource usage.

Recommendations:

  • Debounce or batch form updates where appropriate.
  • Virtualize large result lists in activity logs.
  • Persist frequently used SMTP config securely.
  • Consider caching parsed contacts to avoid repeated Python parsing.

Troubleshooting guide#

Common issues and resolutions:

  • Electron API not available: Ensure preload bridge is loaded and contextIsolation is enabled.
  • Gmail authentication failures: Verify environment variables and network access for OAuth redirect.
  • WhatsApp QR not appearing: Confirm QR code generation and event emission; retry connection if needed.
  • SMTP connection errors: Validate host/port/security settings; ensure TLS configuration matches provider.
  • Phone number parsing errors: Check manual input format and confirm Pyodide is loaded.

Diagnostics:

  • Check console logs for error messages from handlers.
  • Monitor email-progress and WhatsApp status events.
  • Verify file import filters and formats (CSV/TXT).

Conclusion#

Keep service-specific state next to the form that uses it, and lift only what BulkMailer needs for tab chrome and shared status.