Los avisos de objetivos salen por Apps Script con MailApp, no por el worker; y por qué
Decidido el 2-sep-2026 con Gabriel: cuando un líder propone un objetivo le llega un mail a
Dirección, y cuando Dirección aprueba o devuelve le llega al líder.
Sale del Apps Script de la planilla BASE OBJETIVOS, no del worker. El worker no puede
mandar mail sin contratar un proveedor y guardar una API key; el Apps Script usa MailApp,
manda desde plant.com.ar y no necesita ninguna credencial nueva. Trigger cada 15 minutos
(pi_avisos), separado del refresco diario de la planilla (pi_actualizar), para que los
avisos no esperen 24 horas.
Se agregó al scope de OAuth antes de la primera autorización, a propósito: si se agregaba
después, Gabriel tenía que volver a autorizar.
Dedup: Script Property PI_ULTIMO_AVISO guarda el último n de la bitácora notificado.
En la primera corrida se pone al día sin mandar la historia por mail — si no, salían 7
mails de eventos viejos de golpe.
Se agregó el motivo de devolución al panel (/aprobar acepta motivo, va al evento y al
mail). Sin eso el mail decía "te lo devolvieron" y nada más, que es peor que no avisar.
Los mails siguen las reglas de Gmail que ya costaron un bloque invisible: Verdana, **fondo claro
con texto oscuro siempre**, bloques de color con <table bgcolor> + style, jerarquía con
border-left:5px, y sin URLs (Gmail las reescribe y mutila el texto visible). Se referencia
"el panel de Objetivos" por nombre. Hay pi_mailPrueba() que manda las tres plantillas con
datos reales a quien la corre, para revisarlas antes de que le lleguen al equipo.
Remitente: avisos@plant.com.ar — es la decisión D8 del plan de tableros. Quedó
registrado ahí que un Grupo de Google o un alias es gratis (no consume licencia de Workspace;
sólo una cuenta completa nueva paga), y que la idea es un remitente no-reply para que los líderes
no le contesten al mail.
No usar GmailApp. Para mandar con otro remitente exige el scope https://mail.google.com/,
que en la pantalla de consentimiento dice *"leer, redactar, enviar y eliminar permanentemente
correos de Gmail"* — acceso total a la casilla del CEO para un script que manda tres avisos por mes.
Gabriel estuvo a punto de aceptarlo; frenarlo fue lo correcto.
En su lugar: API de Gmail directa con UrlFetchApp + ScriptApp.getOAuthToken(), y los scopes
declarados a mano en appsscript.json (hay que activar "Mostrar el archivo de manifiesto" en
Configuración del proyecto). Quedan seis, todos mínimos: spreadsheets.currentonly,
script.external_request, script.scriptapp, userinfo.email, gmail.send (mandar, no leer
ni borrar) y gmail.settings.basic (ver qué remitentes están habilitados).
POST /gmail/v1/users/me/messages/send con un RFC822 crudo en base64 web-safe; el asunto va en
RFC 2047 para que no se rompan los acentos. Gmail valida que el From sea un remitente habilitado.
El remitente sólo funciona si la dirección está dada de alta como "Enviar como"
en la cuenta que autorizó el script. Si no lo está, pi_enviar() manda
igual desde la cuenta y lo deja anotado en el log con replyTo al alias — un aviso que llega con
el remitente equivocado es mejor que uno que no llega. Se cambia sin tocar código con la propiedad
PI_REMITENTE. pi_alias() lista qué direcciones puede usar la cuenta.
No-reply: el Reply-To apunta siempre a avisos@, salga de donde salga, para que una
respuesta nunca caiga en la casilla personal; y el pie del mail lo dice ("no respondas a este
correo, la casilla no se lee").
Cambiar los scopes obliga a re-autorizar.
avisos@plant.com.ar es un Grupo de Google en modo "solo anuncio", no una casilla. Ese modo
es justo lo que traba la configuración: Gmail exige mandar un **código de verificación a esa
dirección** para habilitarla en "Enviar como", y un grupo solo-anuncio no le entrega a nadie.
Mauro chocó con lo mismo el 1-sep ("me pide que se verifique desde la casilla").
Se destraba así: en groups.google.com abrir temporalmente "Quién puede publicar" a cualquiera,
estar como miembro con entrega de todos los mensajes, hacer la verificación en Gmail (tildando
"Tratar como alias"), y volver el grupo a solo-anuncio. El alias sobrevive. Hay que hacerlo
por persona: cada cuenta que quiera mandar como avisos@ necesita su propia entrada.
Diseño de los mails: la estructura salió del aviso "Pedidos pendientes categoría A" de Mauro
— cabecera negra con la marca, banda lila con el título, tarjeta blanca sobre fondo gris. Es mejor
que un cuerpo suelto. Lo que NO se le copió: sus dos columnas width="50%" no colapsan en celular,
y sus listas alfabéticas no priorizan (19 marcas sin decir cuál urge). Nuestros mails van con
números y contexto en vez de listas.
Datos/plant-avisos-objetivos-mail