Correu i WhatsApp
L’app de gestió ja pot enviar i rebre correu i enviar i rebre WhatsApp. Tot es configura i es consulta des de dues pantalles noves dins de /compta/, i els avisos automàtics (confirmacions, recordatoris, tiquets) surten sols quan es creen cites, vendes o fitxes de client.
Què hem muntat
Tres serveis en segon pla i un connector dins de WordPress:
| Peça | Què fa | On escolta |
|---|---|---|
| Mailpit | Servidor de correu local: rep tot el correu, el desa i en mostra la safata | 127.0.0.1:1025 (SMTP) i 127.0.0.1:8025 (safata i API) |
| Pont de WhatsApp | Es vincula a WhatsApp Web amb un codi QR i envia/rep missatges | 127.0.0.1:3001 |
| Tasques de WordPress | Importa el correu i envia els recordatoris cada minut | — |
Plugin compt-comunicacions |
Connecta tot això amb l’app: ajustos, bústia, plantilles i automatitzacions | — |
Per què no hi ha Postfix
En aquest entorn no hi ha root: sudo està bloquejat pel flag no new privileges, així que no s’hi poden instal·lar paquets de sistema com Postfix o Dovecot. La solució és fer servir serveis que corren en espai d’usuari, gestionats amb systemd d’usuari (amb Linger=yes, o sigui que sobreviuen al tancament de sessió i als reinicis).
Mailpit és un binari únic que fa d’MTA de proves: accepta el correu pel port 1025 i el desa en una base de dades SQLite, amb safata web i API HTTP incloses.
El servidor de correu local
| Servei | Unitat systemd | Comanda |
|---|---|---|
| Mailpit | mailpit.service |
systemctl --user restart mailpit |
| Pont de WhatsApp | whatsapp-bridge.service |
systemctl --user restart whatsapp-bridge |
| Tasques de WordPress | compt-comms-cron.timer |
systemctl --user list-timers |
La safata de Mailpit es pot obrir directament a http://127.0.0.1:8025. Els registres són a /var/www/html/comms/logs/.
# Estat dels tres serveis
systemctl --user status mailpit whatsapp-bridge compt-comms-cron.timer
# Registres
tail -f /var/www/html/comms/logs/mailpit.log
tail -f /var/www/html/comms/logs/whatsapp.log
tail -f /var/www/html/comms/logs/wp-cron.log
Enviar correu: local o SMTP extern
El connector intercepta phpmailer_init i decideix per on surt el correu segons el mode triat a la pantalla de configuració:
- Servidor local — tot el correu va a Mailpit (
127.0.0.1:1025). És el mode per defecte i serveix per desenvolupar i provar sense enviar res de veritat. - SMTP extern — s’envia pel proveïdor que triïs (Gmail amb contrasenya d’aplicació, Brevo, Mailgun…): host, port, xifrat (STARTTLS o SSL), usuari i contrasenya.
També es filtren wp_mail_from i wp_mail_from_name, i es força Reply-To. Detall important après d’una prova: PHPMailer rebutja adreces sense domini amb punt, així que un remitent no-reply@nitidastudio.synology.me falla; per defecte s’usa un domini vàlid i, si el configurat no ho és, es cau a no-reply@<domini>.
Com que tot passa per wp_mail(), els correus de WooCommerce també surten per aquí.
Rebre correu
Mailpit envia un webhook a WordPress cada cop que arriba un correu nou:
GET/POST https://nitidastudio.synology.me/?compt_comms_mailpit=<testimoni>
El plugin valida el testimoni, demana el missatge sencer a l’API de Mailpit i el desa a la taula wp_comms_missatges. Com a xarxa de seguretat, el cron també fa un sondeig cada minut, de manera que cap correu no es perd si el webhook falla. Si el remitent coincideix amb l’email (o el telèfon) d’un client, el missatge s’enllaça sol a la seva fitxa; si no, es pot vincular a mà des de la bústia.
El pont de WhatsApp
És un petit servei en Node que fa servir la llibreria Baileys (WhatsApp Web). No cal compte de negoci ni API oficial: es vincula el mòbil escanejant un codi QR.
# Vincular (una sola vegada)
Obre /compta/comunicacions/ i escaneja el QR amb:
WhatsApp → Dispositius vinculats → Vincular un dispositiu
# Canviar de mòbil
/var/www/html/comms/reset-whatsapp.sh
El pont exposa una API senzilla, sempre a localhost i protegida amb un testimoni compartit (X-Compt-Token):
| Endpoint | Què fa |
|---|---|
GET /health |
Estat: connectat, número vinculat, si hi ha QR |
GET /qr.png |
Imatge del codi QR (la que es veu a la pantalla de configuració) |
POST /send |
Enviar un text a un número |
POST /send-media |
Enviar imatge, vídeo, àudio o document |
POST /logout |
Desvincular el dispositiu |
Quan arriba un missatge, el pont l’envia a /wp-json/compt-comms/v1/whatsapp/inbound; el plugin n’extreu el text (conversa, text estès, subtítols d’imatge o document, botons i llistes), l’enllaça al client pel telèfon i el deixa a la bústia. Els missatges de grup i els estats/reaixos s’ignoren.
Les pantalles noves
Al menú de l’app hi ha un grup nou, Comunicacions, amb dues entrades:
/compta/comunicacions/— estat dels serveis, QR de WhatsApp, configuració de correu i de WhatsApp (pont local, Meta Cloud API o Twilio), automatitzacions i plantilles, amb botons per enviar correus i WhatsApps de prova i per sincronitzar la bústia./compta/missatges/— bústia unificada: filtres per canal, sentit i estat, cerca, conversa per fils, resposta directa, vinculació a client i redacció de missatges nous.
Les rutes funcionen com la resta de l’app: s’afegeixen a astrolus_crud_slugs() i una entitat virtual a astrolus_entities(), i el plugin enganxa un filtre a template_include que carrega les seves plantilles. Els avisos de resultat es mostren amb paràmetres ?compt_msg=.
Automatitzacions
El tema ara dispara accions en desar registres (astrolus_entity_saved_<taula>), i el plugin les escolta:
| Avis | Quan surt | Canal per defecte |
|---|---|---|
| Benvinguda | En crear la fitxa d’un client | Correu i WhatsApp |
| Confirmació de cita | En crear una cita | Correu i WhatsApp |
| Recordatori de cita | 24 h abans (configurable) | Correu i WhatsApp |
| Tiquet o factura | En registrar una venda | Correu |
| Avís a l’equip | Cites i vendes noves | Correu (als empleats actius) |
Cada automatització es pot activar o desactivar i canviar de canal des de la pantalla de configuració. Els textos són plantilles editables amb variables com {client_nom}, {data}, {hora}, {servei}, {import} o {linies}. Els enviaments queden registrats a wp_comms_log per no repetir-se: el recordatori, per exemple, només s’envia un cop per cita.
Com ho hem verificat
- Correu de prova enviat des de la pantalla → capturat per Mailpit → importat sol a la bústia.
- Correu entrant des del correu d’una clienta → enllaçat automàticament a la seva fitxa.
- Cita creada → confirmació a la clienta i avís a l’equip; el recordatori surt dins la finestra de 24 h i no es duplica si es torna a executar.
- Venda creada → tiquet a la clienta i avís a l’equip.
- Pont de WhatsApp amb QR vàlid; sense vincular, l’enviament retorna un error controlat i queda registrat.
Seguretat
- Els tres serveis escolten només a
127.0.0.1: des d’una altra màquina de la xarxa no s’hi arriba. - La carpeta de serveis (
/var/www/html/comms/) està bloquejada per web amb un.htaccessque retorna 403; a dins hi ha els testimonis i les credencials de WhatsApp. - Els endpoints REST exigeixen el testimoni compartit i retornen 401 sense ell.
- Les pantalles de Comunicacions només són accessibles amb sessió de WordPress iniciada.
- La carpeta
comms/whatsapp/auth/conté la sessió de WhatsApp: no s’ha de versionar mai.
Què queda pendent
- Vincular el WhatsApp: fins que no s’escaneja el QR, els enviaments de WhatsApp queden registrats com a error.
- Enviar correu de veritat: cal omplir el mode SMTP extern amb credencials.
- Rebre correu d’Internet (per exemple
info@elteudomini.cat) requereix un domini amb registres MX i un servidor amb el port 25 obert; aquí no és possible, però en un VPS es podria instal·lar Postfix i Dovecot o contractar un servei de correu. - El pont de WhatsApp fa servir WhatsApp Web, que no és l’API oficial: va molt bé per a un ús normal, però per a volums alts o números dedicats és millor Meta Cloud API o Twilio, totes dues ja suportades a la configuració.
- Els fitxers multimèdia entrants de WhatsApp es registren amb les seves dades (tipus i nom), però encara no es descarrega el contingut.
Fitxers clau
/var/www/html/comms/
├── bin/mailpit # servidor de correu
├── mailpit-data/ # missatges de Mailpit
├── whatsapp/server.js # pont de WhatsApp (Node + Baileys)
├── whatsapp/config.json # port, testimonis i URLs dels webhooks
├── units/ # unitats systemd
├── logs/ # registres
└── README.md # documentació completa
wp-content/plugins/compt-comunicacions/
├── includes/class-store.php # taules de missatges, registre i cua
├── includes/class-settings.php # ajustos i plantilles
├── includes/class-mailer.php # SMTP i plantilles de correu
├── includes/class-whatsapp.php # pont local, Meta i Twilio
├── includes/class-inbound.php # webhooks i importació de correu
├── includes/class-automations.php # avisos automàtics
├── includes/class-ui.php # rutes, accions i avisos
└── templates/ # pantalles de configuració i bústia