تحليل رسائل Gmail وتصنيفها باستخدام "Gemini في Gmail" وVertex AI

يستخدم هذا الحلّ Vertex AI وGemini لتحليل رسائل Gmail وتصنيفها استنادًا إلى المشاعر التي تعبّر عنها.

مستوى الترميز: متوسط
المدة: 30 دقيقة
نوع المشروع: إضافة Google Workspace

  • إضافة على Google Workspace توسّع نطاق Gmail في شريط جانبي
    الشكل 1: يعرض إضافة تحليل المشاعر شريطًا جانبيًا في Gmail حيث يمكن للمستخدمين الطلب من Gemini تحليل الرسائل وتطبيق تصنيفات عليها استنادًا إلى المشاعر.
  • رسالة Gmail ذات شعور محايد
    الشكل 2: تصنيف الإضافة لرسالة Gmail باستخدام التصنيف أسلوب محايد 😐.
  • رسالة Gmail تتضمّن شعورًا إيجابيًا
    الشكل 3: تصنّف الإضافة رسالة Gmail باستخدام التصنيف نبرة إيجابية 😊.
  • رسالة Gmail تتضمّن شعورًا سلبيًا.
    الشكل 4: تصنيف الإضافة لرسالة Gmail باستخدام التصنيف أسلوب مزعج 😡.

الأهداف

  • فهم ما يفعله الحلّ
  • التعرّف على وظائف خدمات Google ضمن الحلّ
  • إعداد البيئة
  • إعداد مشروع "برمجة تطبيقات Google"
  • شغِّل النص البرمجي.

لمحة عن هذا الحل

لقطة شاشة لإضافة "تحليل المشاعر" في Google Workspace

هذا الحلّ هو إضافة في Google Workspace تعمل على تطبيق تصنيفات استنادًا إلى المشاعر الواردة في رسائل Gmail. لتحليل محتوى الرسالة، تستخدم الإضافة Vertex AI لتقديم طلب إلى نموذج Gemini 2.5 Flash وعرض إحدى الحالات المزاجية التالية:

  • إيجابية
  • سلبية
  • محايد

بعد تلقّي الرد من Gemini، يطبّق التطبيق الإضافي تصنيف Gmail مطابقًا على الرسالة.

لحصر الطلب على Vertex AI API، يحلّل هذا الإضافة الرسائل العشر الأحدث فقط في البريد الوارد لمستخدم Gmail ويطبّق عليها التصنيفات. لمزيد من المعلومات حول الحصص والحدود، يُرجى الانتقال إلى مستندات Vertex AI.

آلية العمل

تم إنشاء هذا الحل في Google Apps Script ويستخدم خدمات ومنتجات Google التالية:

المتطلبات الأساسية

إعداد البيئة

يوضّح هذا القسم كيفية ضبط بيئتك وإعدادها في Google Cloud Console وApps Script.

إعداد مشروعك على السحابة الإلكترونية في Google Cloud Console

يوضّح لك هذا القسم كيفية تفعيل واجهة برمجة التطبيقات Vertex AI API وإعداد شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth في مشروعك على Cloud.

تفعيل واجهة برمجة التطبيقات Vertex AI API

  1. في Google Cloud Console، افتح مشروعك على Google Cloud وفعِّل واجهة Vertex AI API باتّباع الخطوات التالية:

    تفعيل واجهة برمجة التطبيقات

  2. تأكَّد من أنّك بصدد تفعيل واجهة برمجة التطبيقات في مشروع Cloud الصحيح، ثم انقر على التالي.

  3. تأكَّد من تفعيل واجهة برمجة التطبيقات الصحيحة، ثم انقر على تفعيل.

إعداد شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth

تتطلّب إضافات Google Workspace إعداد شاشة موافقة. يؤدي ضبط شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth الخاصة بالإضافة إلى تحديد ما تعرضه Google للمستخدمين.

  1. في "وحدة تحكّم Google Cloud"، انتقِل إلى "القائمة" > > تحديد هوية العلامة التجارية.

    الانتقال إلى "الهوية البصرية للعلامة التجارية"

  2. إذا سبق لك ضبط ، يمكنك ضبط إعدادات "شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth" التالية في العلامة التجارية والجمهور والوصول إلى البيانات. إذا ظهرت لك الرسالة لم يتم الإعداد بعد، انقر على البدء:
    1. ضمن معلومات التطبيق، في اسم التطبيق، أدخِل اسمًا للتطبيق.
    2. في البريد الإلكتروني لدعم المستخدمين، اختَر عنوان بريد إلكتروني للدعم يمكن للمستخدمين التواصل معك من خلاله إذا كانت لديهم أسئلة حول موافقتهم.
    3. انقر على التالي.
    4. ضمن الجمهور، اختَر داخلي.
    5. انقر على التالي.
    6. ضمن معلومات الاتصال، أدخِل عنوان بريد إلكتروني يمكنك تلقّي إشعارات فيه بشأن أي تغييرات تطرأ على مشروعك.
    7. انقر على التالي.
    8. ضمن إنهاء، راجِع سياسة بيانات المستخدمين في خدمات Google API، وإذا كنت توافق عليها، ضَع علامة في المربّع بجانب أوافق على سياسة بيانات المستخدمين في خدمات Google API.
    9. انقر على متابعة.
    10. انقر على إنشاء.
  3. يمكنك حاليًا تخطّي إضافة النطاقات. في المستقبل، عند إنشاء تطبيق لاستخدامه خارج مؤسسة Google Workspace، عليك تغيير نوع المستخدم إلى خارجي. بعد ذلك، أضِف نطاقات التفويض التي يتطلّبها تطبيقك. لمزيد من المعلومات، يُرجى الاطّلاع على الدليل الكامل حول ضبط موافقة OAuth.

إنشاء مشروعك في "برمجة تطبيقات Google" وإعداده

لإنشاء مشروع Apps Script وإعداده للإضافة، يُرجى اتّباع الخطوات التالية:

  1. انقر على الزر التالي لفتح مشروع تحليل المشاعر في Gmail باستخدام Gemini وVertex AI في "برمجة التطبيقات".
    افتح مشروع "برمجة تطبيقات Google"

  2. انقر على نظرة عامة .

  3. في صفحة النظرة العامة، انقر على "إنشاء نسخة" رمز إنشاء نسخة.

  4. احصل على رقم مشروعك على السحابة الإلكترونية:

    1. في Google Cloud Console، انتقِل إلى "القائمة" > المشرف وإدارة الهوية وإمكانية الوصول > الإعدادات.

      الانتقال إلى إعدادات "إدارة الهوية وإمكانية الوصول" والمشرف

    2. في حقل رقم المشروع، انسخ القيمة.
  5. ربط مشروعك على السحابة الإلكترونية بمشروعك على Apps Script:

    1. في مشروع "برمجة تطبيقات Google" الذي نسخته، انقر على إعدادات المشروع رمز إعدادات المشروع.
    2. ضمن مشروع Google Cloud Platform (GCP)، انقر على تغيير المشروع.
    3. في رقم مشروع Google Cloud، الصِق رقم مشروع Cloud.
    4. انقر على تحديد المشروع.

اختبار الإضافة

لتجربة الإضافة، ثبِّت إصدارًا تجريبيًا ثم افتح الإضافة في Gmail:

  1. إنشاء عملية نشر تجريبية لبرمجة Apps Script وتثبيتها:
    1. في مشروع "برمجة تطبيقات Google" الذي نسخته، انقر على المحرّر .
    2. افتح ملف Code.gs وانقر على تشغيل. امنح الإذن للنصّ البرمجي عند مطالبتك بذلك.
    3. انقر على نشر > اختبار عمليات النشر.
    4. انقر على تثبيت > تم.
  2. افتح Gmail.

    الانتقال إلى Gmail

  3. في الشريط الجانبي الأيسر، افتح إضافة تحليل المشاعر.

  4. امنح الإذن للإضافة إذا طُلب منك ذلك.

  5. اختياري: لإنشاء رسائل إلكترونية تجريبية لاستخدامها مع الإضافة، انقر على إنشاء رسائل إلكترونية نموذجية. تظهر ثلاث رسائل في بريدك الوارد. إذا لم تظهر لك، أعِد تحميل الصفحة.

  6. لإضافة تصنيفات، انقر على تحليل الرسائل الإلكترونية.

يراجع التطبيق الإضافي آخر 10 رسائل في بريدك الوارد، ثم يطبّق أحد التصنيفات التالية استنادًا إلى محتوى الرسالة:

  • أسلوب سعيد 😊
  • نبرة محايدة 😐
  • أسلوب منزعج 😡

مراجعة الرمز البرمجي

راجِع رمز Apps Script البرمجي لهذا الحلّ:

عرض رمز المصدر

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"
}

تَنظيم

لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد المستخدَمة في هذا البرنامج التعليمي، ننصحك بحذف مشروع Cloud.

  1. في Google Cloud Console، انتقِل إلى صفحة إدارة الموارد. انقر على القائمة > إدارة الهوية وإمكانية الوصول والمشرف > إدارة الموارد.

    الانتقال إلى "إدارة الموارد"

  2. في قائمة المشاريع، اختَر المشروع الذي تريد حذفه، ثم انقر على حذف .
  3. في مربّع الحوار، اكتب رقم تعريف المشروع، ثم انقر على إيقاف لحذف المشروع.

الخطوات التالية