Analiza y etiqueta mensajes de Gmail con Gemini y Vertex AI

Esta solución usa Vertex AI y Gemini para analizar los mensajes de Gmail y etiquetarlos según su sentimiento.

Nivel de programación: Intermedio
Duración: 30 minutos
Tipo de proyecto: Complemento de Google Workspace

  • Un complemento de Google Workspace que extiende Gmail en una barra lateral.
    Figura 1: El complemento Análisis de sentimiento muestra una barra lateral en Gmail en la que los usuarios pueden solicitarle a Gemini que analice y aplique etiquetas a los mensajes según el sentimiento.
  • Un mensaje de Gmail con sentimiento neutral.
    Figura 2: El complemento etiqueta un mensaje de Gmail con la etiqueta TONO NEUTRAL 😐.
  • Un mensaje de Gmail con un sentimiento positivo.
    Figura 3: El complemento etiqueta un mensaje de Gmail con la etiqueta TONO FELIZ 😊.
  • Un mensaje de Gmail con un sentimiento de molestia.
    Figura 4: El complemento etiqueta un mensaje de Gmail con la etiqueta TONO MOLESTO 😡.

Objetivos

  • Comprende qué hace la solución.
  • Comprende qué hacen los servicios de Google dentro de la solución.
  • Configura el entorno.
  • Configura el proyecto de Google Apps Script.
  • Ejecuta la secuencia de comandos.

Acerca de esta solución

Captura de pantalla del complemento de Google Workspace de Análisis de opiniones

Esta solución es un complemento de Google Workspace que aplica etiquetas según el sentimiento de los mensajes de Gmail. Para analizar el contenido del mensaje, el complemento usa Vertex AI para solicitarle al modelo de Gemini 2.5 Flash que devuelva uno de los siguientes sentimientos:

  • Positivo
  • Negativo
  • Neutral

Con la respuesta de Gemini, el complemento aplica una etiqueta de Gmail correspondiente al mensaje.

Para limitar la solicitud a la API de Vertex AI, este complemento solo analiza y aplica etiquetas a los 10 mensajes más recientes de la carpeta Recibidos del usuario de Gmail. Para obtener más información sobre las cuotas y los límites, consulta la documentación de Vertex AI.

Cómo funciona

Esta solución se compiló en Google Apps Script y usa los siguientes servicios y productos de Google:

Requisitos previos

Configura tu entorno

En esta sección, se explica cómo configurar tu entorno en la consola de Google Cloud y en Apps Script.

Configura tu proyecto de Cloud en la consola de Google Cloud

En esta sección, se muestra cómo habilitar la API de Vertex AI y configurar la pantalla de consentimiento de OAuth en tu proyecto de Cloud.

Habilita la API de Vertex AI

  1. En la consola de Google Cloud, abre tu proyecto de Google Cloud y habilita la API de Vertex AI:

    Habilitar la API

  2. Confirma que habilitarás la API en el proyecto de Cloud correcto y, luego, haz clic en Siguiente.

  3. Confirma que habilitarás la API correcta y, luego, haz clic en Habilitar.

Cómo configurar la pantalla de consentimiento de OAuth

Los complementos de Google Workspace requieren una configuración de pantalla de consentimiento. Configurar la pantalla de consentimiento de OAuth de tu complemento define lo que Google muestra a los usuarios.

  1. En la consola de Google Cloud, ve a Menú > > Branding.

    Ir a Desarrollo de la marca

  2. Si ya configuraste el , puedes configurar los siguientes parámetros de configuración de la pantalla de consentimiento de OAuth en Branding, Audience y Data Access. Si ves un mensaje que dice aún no se configuró, haz clic en Comenzar:
    1. En Información de la app, en Nombre de la app, ingresa un nombre para la app.
    2. En Correo electrónico de asistencia del usuario, elige una dirección de correo electrónico de asistencia a la que los usuarios puedan comunicarse contigo si tienen preguntas sobre su consentimiento.
    3. Haz clic en Siguiente.
    4. En Público, selecciona Interno.
    5. Haz clic en Siguiente.
    6. En Información de contacto, ingresa una dirección de correo electrónico en la que puedas recibir notificaciones sobre cualquier cambio en tu proyecto.
    7. Haz clic en Siguiente.
    8. En Finalizar, revisa la Política de Datos del Usuario de los Servicios de las APIs de Google y, si la aceptas, selecciona Acepto la Política de Datos del Usuario de los Servicios de las APIs de Google.
    9. Haz clic en Continuar.
    10. Haz clic en Crear.
  3. Por el momento, puedes omitir la adición de permisos. En el futuro, cuando crees una app para usarla fuera de tu organización de Google Workspace, deberás cambiar el Tipo de usuario a Externo. Luego, agrega los permisos de autorización que requiere tu app. Para obtener más información, consulta la guía completa Configura el consentimiento de OAuth.

Crea y configura tu proyecto de Apps Script

Para crear y configurar tu proyecto de Apps Script para el complemento, completa los siguientes pasos:

  1. Haz clic en el siguiente botón para abrir el proyecto de Apps Script Análisis de sentimiento de Gmail con Gemini y Vertex AI.
    Abre el proyecto de Apps Script

  2. Haz clic en Descripción general .

  3. En la página de descripción general, haz clic en Crear una copia Ícono para crear una copia.

  4. Obtén el número de tu proyecto de Cloud:

    1. En la consola de Google Cloud, ve a Menú > IAM y administración > Configuración.

      Ir a Configuración de IAM y administración

    2. En el campo Número del proyecto, copia el valor.
  5. Conecta tu proyecto de Cloud con tu proyecto de Apps Script:

    1. En el proyecto de Apps Script que copiaste, haz clic en Configuración del proyecto El ícono de configuración del proyecto.
    2. En Proyecto de Google Cloud, haz clic en Cambiar proyecto.
    3. En Número de proyecto de GCP, pega el número de proyecto de Cloud.
    4. Haz clic en Establecer el proyecto.

Prueba el complemento

Para probar el complemento, instala una implementación de prueba y, luego, abre el complemento en Gmail:

  1. Crea e instala una implementación de prueba de Apps Script:
    1. En el proyecto de Apps Script que copiaste, haz clic en Editor .
    2. Abre el archivo Code.gs y haz clic en Ejecutar. Cuando se te solicite, autoriza la secuencia de comandos.
    3. Haz clic en Implementar > Probar implementaciones.
    4. Haz clic en Instalar > Listo.
  2. Abre Gmail.

    Ir a Gmail

  3. En la barra lateral derecha, abre el complemento Análisis de sentimiento.

  4. Si se te solicita, autoriza el complemento.

  5. Opcional: Para crear mensajes con los que probar tu complemento, haz clic en Generar correos electrónicos de muestra. Aparecerán tres mensajes en tu carpeta de Recibidos. Si no los ves, actualiza la página.

  6. Para agregar etiquetas, haz clic en Analizar correos electrónicos.

El complemento revisa los 10 mensajes más recientes de tu bandeja de entrada y, luego, aplica una de las siguientes etiquetas según el contenido del mensaje:

  • TONO FELIZ 😊
  • TONO NEUTRO 😐
  • TONO DE ENOJO 😡

Revisa el código

Revisa el código de Apps Script para esta solución:

Ver el código fuente

Code.gs

gmail-sentiment-analysis/Code.gs
/* Copyright 2024 Google LLC  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at      https://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */  /**  * Triggered when the add-on is opened from the Gmail homepage.  *  * @param {Object} e - The event object.  * @returns {Card} - The homepage card.  */ function onHomepageTrigger(e) {   return buildHomepageCard(); }

Cards.gs

gmail-sentiment-analysis/Cards.gs
/* Copyright 2024-2025 Google LLC  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at      https://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */  /**  * Builds the main card displayed on the Gmail homepage.  *  * @returns {Card} - The homepage card.  */ function buildHomepageCard() {   // Create a new card builder   const cardBuilder = CardService.newCardBuilder();    // Create a card header   const cardHeader = CardService.newCardHeader();   cardHeader.setImageUrl('https://fonts.gstatic.com/s/i/googlematerialicons/mail/v6/black-24dp/1x/gm_mail_black_24dp.png');   cardHeader.setImageStyle(CardService.ImageStyle.CIRCLE);   cardHeader.setTitle("Analyze your Gmail");    // Add the header to the card   cardBuilder.setHeader(cardHeader);    // Create a card section   const cardSection = CardService.newCardSection();    // Create buttons for generating sample emails and analyzing sentiment   const buttonSet = CardService.newButtonSet();    // Create "Generate sample emails" button   const generateButton = createFilledButton('Generate sample emails', 'generateSampleEmails', '#34A853');   buttonSet.addButton(generateButton);    // Create "Analyze emails" button   const analyzeButton = createFilledButton('Analyze emails', 'analyzeSentiment', '#FF0000');   buttonSet.addButton(analyzeButton);    // Add the button set to the section   cardSection.addWidget(buttonSet);    // Add the section to the card   cardBuilder.addSection(cardSection);    // Build and return the card   return cardBuilder.build(); }  /**  * Creates a filled text button with the specified text, function, and color.  *  * @param {string} text - The text to display on the button.  * @param {string} functionName - The name of the function to call when the button is clicked.  * @param {string} color - The background color of the button.  * @returns {TextButton} - The created text button.  */ function createFilledButton(text, functionName, color) {   // Create a new text button   const textButton = CardService.newTextButton();    // Set the button text   textButton.setText(text);    // Set the action to perform when the button is clicked   const action = CardService.newAction();   action.setFunctionName(functionName);   textButton.setOnClickAction(action);    // Set the button style to filled   textButton.setTextButtonStyle(CardService.TextButtonStyle.FILLED);    // Set the background color   textButton.setBackgroundColor(color);    return textButton; }  /**  * Creates a notification response with the specified text.  *  * @param {string} notificationText - The text to display in the notification.  * @returns {ActionResponse} - The created action response.  */ function buildNotificationResponse(notificationText) {   // Create a new notification   const notification = CardService.newNotification();   notification.setText(notificationText);    // Create a new action response builder   const actionResponseBuilder = CardService.newActionResponseBuilder();    // Set the notification for the action response   actionResponseBuilder.setNotification(notification);    // Build and return the action response   return actionResponseBuilder.build(); }

Gmail.gs

gmail-sentiment-analysis/Gmail.gs
/* Copyright 2024-2025 Google LLC  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at      https://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */  /**  * Analyzes the sentiment of the first 10 threads in the inbox  * and labels them accordingly.  *  * @returns {ActionResponse} - A notification confirming completion.  */ function analyzeSentiment() {   // Analyze and label emails   analyzeAndLabelEmailSentiment();    // Return a notification   return buildNotificationResponse("Successfully completed sentiment analysis"); }  /**  * Analyzes the sentiment of emails and applies appropriate labels.  */ function analyzeAndLabelEmailSentiment() {   // Define label names   const labelNames = ["HAPPY TONE 😊", "NEUTRAL TONE 😐", "UPSET TONE 😡"];    // Get or create labels for each sentiment   const positiveLabel = GmailApp.getUserLabelByName(labelNames[0]) || GmailApp.createLabel(labelNames[0]);   const neutralLabel = GmailApp.getUserLabelByName(labelNames[1]) || GmailApp.createLabel(labelNames[1]);   const negativeLabel = GmailApp.getUserLabelByName(labelNames[2]) || GmailApp.createLabel(labelNames[2]);    // Get the first 10 threads in the inbox   const threads = GmailApp.getInboxThreads(0, 10);    // Iterate through each thread   for (const thread of threads) {     // Iterate through each message in the thread     const messages = thread.getMessages();     for (const message of messages) {       // Get the plain text body of the message       const emailBody = message.getPlainBody();        // Analyze the sentiment of the email body       const sentiment = processSentiment(emailBody);        // Apply the appropriate label based on the sentiment       if (sentiment === 'positive') {         thread.addLabel(positiveLabel);       } else if (sentiment === 'neutral') {         thread.addLabel(neutralLabel);       } else if (sentiment === 'negative') {         thread.addLabel(negativeLabel);       }     }   } }  /**  * Generates sample emails for testing the sentiment analysis.  *  * @returns {ActionResponse} - A notification confirming email generation.  */ function generateSampleEmails() {   // Get the current user's email address   const userEmail = Session.getActiveUser().getEmail();    // Define sample emails   const sampleEmails = [     {       subject: 'Thank you for amazing service!',       body: 'Hi, I really enjoyed working with you. Thank you again!',       name: 'Customer A'     },     {       subject: 'Request for information',       body: 'Hello, I need more information on your recent product launch. Thank you.',       name: 'Customer B'     },     {       subject: 'Complaint!',       body: '',       htmlBody: `<p>Hello, You are late in delivery, again.</p> <p>Please contact me ASAP before I cancel our subscription.</p>`,       name: 'Customer C'     }   ];    // Send each sample email   for (const email of sampleEmails) {     GmailApp.sendEmail(userEmail, email.subject, email.body, {       name: email.name,       htmlBody: email.htmlBody     });   }    // Return a notification   return buildNotificationResponse("Successfully generated sample emails"); }

Vertex.gs

gmail-sentiment-analysis/Vertex.gs
/* Copyright 2024-2025 Google LLC  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at      https://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */  // Replace with your project ID const PROJECT_ID = '[ADD YOUR GCP PROJECT ID HERE]';  // Location for your Vertex AI model const VERTEX_AI_LOCATION = 'us-central1';  // Model ID to use for sentiment analysis const MODEL_ID = 'gemini-2.5-flash';  /**  * Sends the email text to Vertex AI for sentiment analysis.  *  * @param {string} emailText - The text of the email to analyze.  * @returns {string} - The sentiment of the email ('positive', 'negative', or 'neutral').  */ function processSentiment(emailText) {   // Construct the API endpoint URL   const apiUrl = `https://${VERTEX_AI_LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION}/publishers/google/models/${MODEL_ID}:generateContent`;    // Prepare the request payload   const payload = {     contents: [       {         role: "user",         parts: [           {             text: `Analyze the sentiment of the following message: ${emailText}`           }         ]       }     ],     generationConfig: {       temperature: 0.9,       maxOutputTokens: 1024,       responseMimeType: "application/json",       // Expected response format for simpler parsing.       responseSchema: {         type: "object",         properties: {           response: {             type: "string",             enum: ["positive", "negative", "neutral"]           }         }       }     }   };    // Prepare the request options   const options = {     method: 'POST',     headers: {       'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`     },     contentType: 'application/json',     muteHttpExceptions: true, // Set to true to inspect the error response     payload: JSON.stringify(payload)   };    // Make the API request   const response = UrlFetchApp.fetch(apiUrl, options);    // Parse the response. There are two levels of JSON responses to parse.   const parsedResponse = JSON.parse(response.getContentText());   const sentimentResponse = JSON.parse(parsedResponse.candidates[0].content.parts[0].text).response;    // Return the sentiment   return sentimentResponse; }

appsscript.json

gmail-sentiment-analysis/appsscript.json
{   "timeZone": "America/Toronto",   "oauthScopes": [     "https://www.googleapis.com/auth/cloud-platform",     "https://www.googleapis.com/auth/gmail.addons.execute",     "https://www.googleapis.com/auth/gmail.labels",     "https://www.googleapis.com/auth/gmail.modify",     "https://www.googleapis.com/auth/script.external_request",     "https://www.googleapis.com/auth/userinfo.email"   ],   "addOns": {     "common": {       "name": "Sentiment Analysis",       "logoUrl": "https://fonts.gstatic.com/s/i/googlematerialicons/sentiment_extremely_dissatisfied/v6/black-24dp/1x/gm_sentiment_extremely_dissatisfied_black_24dp.png"     },     "gmail": {       "homepageTrigger": {         "runFunction": "onHomepageTrigger",         "enabled": true       }     }   },   "exceptionLogging": "STACKDRIVER",   "runtimeVersion": "V8" }

Limpia

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos que usaste en este instructivo, te recomendamos que borres el proyecto de Cloud.

  1. En la consola de Google Cloud, ve a la página Administrar recursos. Haz clic en Menú > IAM y administración > Administrar recursos.

    Ir al administrador de recursos

  2. En la lista de proyectos, selecciona el proyecto que deseas borrar y haz clic en Borrar .
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Próximos pasos