0Pricing
AI Agents · درس

الاتصال بـ Gmail عبر API

مكتبة عميل Google API، وموافقة OAuth2، واختيار نطاقات Gmail

الاتصال بـ Gmail عبر API درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.

لماذا نستخدم Gmail API بدلًا من SMTP؟

تستخدم أتمتة البريد الإلكتروني التقليدية SMTP/IMAP، لكن Gmail API يوفّر إمكانات أكثر بكثير: قراءة سلاسل الرسائل، والبحث باستخدام الاستعلامات، وإدارة التصنيفات، والإرسال باستخدام مصادقة كاملة. كما يدعم OAuth 2.0، لذلك لا يخزّن وكيلك كلمة مرور، بل رمز وصول محدود النطاق فقط.

يُعد Gmail API جزءًا من Google Workspace APIs، ويمكن الوصول إليه عبر مكتبة google-api-python-client.

# Install required libraries:
# pip install google-api-python-client google-auth google-auth-oauthlib

# The Gmail API lets agents:
# - List and search messages (labels, queries)
# - Read full message content and attachments
# - Send messages via OAuth (no password needed)
# - Manage labels and threads
# - Watch for new messages via push notifications

print('Gmail API is part of Google Workspace APIs')

المصادقة: حساب الخدمة مقابل مصادقة المستخدم

توجد طريقتان للمصادقة باستخدام Gmail API:

  • حساب الخدمة: الخيار الأفضل للاستخدام في مساحات العمل أو المؤسسات مع التفويض على مستوى النطاق؛ ولا يتطلب تفاعلًا من المستخدم
  • User OAuth (OAuth2 مع شاشة الموافقة): مطلوب لحسابات Gmail الشخصية؛ يمنح المستخدم صلاحية الوصول مرة واحدة، ثم يستخدم الوكيل رمز التحديث

بالنسبة إلى معظم أتمتة الوكلاء، تُفضّل حسابات الخدمة لاعتماديتها.

# Service Account approach:
# 1. Go to Google Cloud Console -> APIs & Services -> Credentials
# 2. Create a Service Account
# 3. Download the JSON key file
# 4. In Google Workspace Admin: enable domain-wide delegation
# 5. Grant required scopes to the service account

# User OAuth approach:
# 1. Create OAuth 2.0 Client ID (Desktop or Web App type)
# 2. Download credentials.json
# 3. First run: user sees consent screen and grants access
# 4. Agent stores token.json with refresh token for subsequent runs

print('Choose service account for org automation, OAuth for personal Gmail')

بنية JSON لبيانات اعتماد OAuth2

توفّر Google بيانات الاعتماد في ملف JSON يحمّله وكيلك للمصادقة. بالنسبة إلى User OAuth، يكون هذا الملف credentials.json الذي يتم تنزيله من Google Cloud Console. يحتوي الملف على معرّف العميل والسر وURI لإعادة التوجيه، لذا لا ترفقه أبدًا في نظام التحكم بالإصدارات.

# credentials.json structure (User OAuth — Desktop app type):
# {
#   "installed": {
#     "client_id": "123456789.apps.googleusercontent.com",
#     "client_secret": "GOCSPX-abc123xyz",
#     "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"],
#     "auth_uri": "https://accounts.google.com/o/oauth2/auth",
#     "token_uri": "https://oauth2.googleapis.com/token"
#   }
# }

# service-account.json structure:
# {
#   "type": "service_account",
#   "project_id": "my-project",
#   "private_key_id": "abc123",
#   "private_key": "-----BEGIN PRIVATE KEY-----\n...",
#   "client_email": "agent@my-project.iam.gserviceaccount.com",
#   "client_id": "..."
# }

print('Store credential files outside your git repository')

نطاقات Gmail API

تحدد النطاقات في OAuth ما يمكن لوكيلك الوصول إليه بالضبط. اطلب النطاقات التي تحتاج إليها فقط، فهذا هو مبدأ أقل قدر من الصلاحيات. تتراوح نطاقات Gmail بين الوصول للقراءة فقط والوصول الكامل.

  • gmail.readonly — قراءة كل البريد
  • gmail.send — الإرسال فقط، دون القراءة
  • gmail.modify — القراءة والإرسال وتعديل التصنيفات
  • gmail.compose — إنشاء المسودات فقط
# Gmail API scope constants
SCOPE_READONLY = 'https://www.googleapis.com/auth/gmail.readonly'
SCOPE_SEND = 'https://www.googleapis.com/auth/gmail.send'
SCOPE_MODIFY = 'https://www.googleapis.com/auth/gmail.modify'
SCOPE_COMPOSE = 'https://www.googleapis.com/auth/gmail.compose'

# Calendar scopes (often used alongside Gmail)
SCOPE_CALENDAR_READ = 'https://www.googleapis.com/auth/calendar.readonly'
SCOPE_CALENDAR_EVENTS = 'https://www.googleapis.com/auth/calendar.events'

# Combine scopes your agent actually needs
AGENT_SCOPES = [
    SCOPE_READONLY,
    SCOPE_SEND,
    SCOPE_CALENDAR_EVENTS
]
print(f'Using {len(AGENT_SCOPES)} scopes')

OAuth للمستخدم: تدفق المصادقة لأول مرة

في المرة الأولى التي يشغّل فيها المستخدم الوكيل، يفتح الوكيل متصفحًا ليمنح المستخدم الإذن. ويخزّن الوكيل الرمز الناتج في token.json. في عمليات التشغيل اللاحقة، يحمّل الرمز المخزّن ويحدّثه تلقائيًا، دون الحاجة إلى تفاعل مع المتصفح.

from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
import os

SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']

def get_credentials(token_file='token.json', creds_file='credentials.json'):
    creds = None

    # Load existing token if available
    if os.path.exists(token_file):
        creds = Credentials.from_authorized_user_file(token_file, SCOPES)

    # Refresh or re-authenticate if needed
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())  # auto-refresh
        else:
            # Opens browser for user consent (first time only)
            flow = InstalledAppFlow.from_client_secrets_file(
                creds_file, SCOPES
            )
            creds = flow.run_local_server(port=0)
        # Save token for next run
        with open(token_file, 'w') as f:
            f.write(creds.to_json())

    return creds

مصادقة حساب الخدمة

تُعد حسابات الخدمة مثالية للوكلاء المؤتمتين الذين يعملون دون تفاعل من المستخدم. يصادق الوكيل باستخدام مفتاح خاص، ثم ينتحل هوية مستخدم في Google Workspace عبر التفويض على مستوى النطاق. لا توجد شاشة موافقة ولا متصفح، بل ملف مفتاح JSON فقط.

from google.oauth2 import service_account
import os

SCOPES = [
    'https://www.googleapis.com/auth/gmail.readonly',
    'https://www.googleapis.com/auth/gmail.send'
]

def get_service_account_credentials(impersonate_user):
    service_account_file = os.environ.get(
        'GOOGLE_SERVICE_ACCOUNT_JSON',
        'service-account.json'
    )

    credentials = service_account.Credentials.from_service_account_file(
        service_account_file,
        scopes=SCOPES
    )

    # Impersonate a real user (requires domain-wide delegation in Admin)
    delegated = credentials.with_subject(impersonate_user)
    return delegated

creds = get_service_account_credentials('agent@yourcompany.com')
print('Service account credentials ready')

إنشاء كائن خدمة Gmail

بعد حصولك على بيانات الاعتماد، استخدم googleapiclient.discovery.build() لإنشاء كائن خدمة Gmail. هذه هي الواجهة الرئيسية لجميع استدعاءات Gmail API. مرّر اسم الخدمة 'gmail' والإصدار 'v1'.

from googleapiclient.discovery import build

def build_gmail_service(credentials):
    service = build(
        'gmail',
        'v1',
        credentials=credentials,
        cache_discovery=False  # avoid file warnings in some environments
    )
    return service

# Full setup: credentials -> service
creds = get_credentials()          # or get_service_account_credentials()
gmail = build_gmail_service(creds)

# Test: get user profile
profile = gmail.users().getProfile(userId='me').execute()
print('Email:', profile['emailAddress'])
print('Total messages:', profile['messagesTotal'])

إنشاء كائن خدمة Calendar

يعمل إعداد بيانات الاعتماد نفسه مع Google Calendar. ما عليك سوى الإنشاء باستخدام 'calendar' و'v3'. وإذا احتجت إلى Gmail وCalendar معًا في وكيل واحد، فأنشئ الخدمتين باستخدام كائن بيانات الاعتماد نفسه.

from googleapiclient.discovery import build

def build_google_services(credentials):
    gmail = build(
        'gmail', 'v1',
        credentials=credentials,
        cache_discovery=False
    )
    calendar = build(
        'calendar', 'v3',
        credentials=credentials,
        cache_discovery=False
    )
    return gmail, calendar

# Use both in one agent
creds = get_credentials()
gmail_service, calendar_service = build_google_services(creds)

# Test calendar access
cal_list = calendar_service.calendarList().list().execute()
for cal in cal_list.get('items', []):
    print(f'Calendar: {cal["summary"]}')

معالجة أخطاء Google API

تُرفع أخطاء Google API على شكل googleapiclient.errors.HttpError. ويحتوي الخطأ على رمز حالة HTTP ونص JSON يتضمن تفاصيل الخطأ. احرص دائمًا على التقاط هذا الخطأ وتسجيل الحالة والرسالة لأغراض تصحيح الأخطاء.

from googleapiclient.errors import HttpError
import json

def safe_gmail_call(service, user_id='me'):
    try:
        profile = service.users().getProfile(userId=user_id).execute()
        return profile
    except HttpError as e:
        status = e.resp.status
        try:
            error_body = json.loads(e.content.decode())
            message = error_body.get('error', {}).get('message', str(e))
        except Exception:
            message = str(e)

        if status == 401:
            print('AUTH ERROR: Credentials invalid or expired')
        elif status == 403:
            print(f'PERMISSION ERROR: {message}')
            print('Check scopes and domain-wide delegation settings')
        elif status == 429:
            print('QUOTA EXCEEDED: Gmail API rate limit hit')
        else:
            print(f'Gmail API error {status}: {message}')
        return None

حصص Google API وحدود معدل الطلبات

يفرض Gmail API حصص استخدام: مليار وحدة حصة يوميًا افتراضيًا، مع تكلفة تتراوح بين وحدة واحدة و100 وحدة لكل استدعاء، بحسب العملية. وتكلفة قراءة الرسائل أعلى من تكلفة عرض قائمتها. استخدم طلبات الدفعات والتراجع الأسي عند ظهور أخطاء 429/503 للبقاء ضمن الحدود.

import time
from googleapiclient.errors import HttpError

def gmail_call_with_retry(func, max_retries=5):
    for attempt in range(max_retries):
        try:
            return func()
        except HttpError as e:
            if e.resp.status in (429, 500, 503):
                wait = (2 ** attempt) + 1
                print(f'Quota/server error. Waiting {wait}s (attempt {attempt+1})')
                time.sleep(wait)
            elif e.resp.status == 403:
                # Check if it's a quota exceeded vs permission error
                import json
                body = json.loads(e.content.decode())
                reason = body.get('error', {}).get('errors', [{}])[0].get('reason', '')
                if reason == 'rateLimitExceeded':
                    time.sleep(2 ** attempt)
                else:
                    raise  # real permission error, don't retry
            else:
                raise
    raise Exception(f'Gmail API call failed after {max_retries} attempts')

تخزين بيانات الاعتماد بأمان

لا ترفق token.json أو credentials.json أو service-account.json أبدًا في نظام التحكم بالإصدارات. أضفها إلى .gitignore. في بيئة الإنتاج، خزّن JSON الخاص بحساب الخدمة في متغير بيئة أو مدير أسرار، وحمّله أثناء التشغيل.

import json
import os
from google.oauth2 import service_account

SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']

def get_credentials_from_env():
    # Load service account JSON from environment variable
    sa_json = os.environ.get('GOOGLE_SERVICE_ACCOUNT_JSON')
    if not sa_json:
        raise EnvironmentError(
            'GOOGLE_SERVICE_ACCOUNT_JSON env var not set. '
            'Set it to the contents of your service-account.json'
        )

    sa_info = json.loads(sa_json)
    credentials = service_account.Credentials.from_service_account_info(
        sa_info,
        scopes=SCOPES
    )
    return credentials

# In production: export GOOGLE_SERVICE_ACCOUNT_JSON=$(cat service-account.json)
creds = get_credentials_from_env()
print('Service account loaded from env var')

تحقق سريع: حساب الخدمة مقابل OAuth للمستخدم

اختبر مدى فهمك لطرق المصادقة في Gmail API.

مراجعة الاتصال بـ Gmail API

أصبح بإمكانك الآن توصيل وكيل بـ Gmail:

  • User OAuth: استخدم InstalledAppFlow وخزّن token.json؛ وسيُحدّث تلقائيًا في عمليات التشغيل اللاحقة
  • حساب الخدمة: حمّل مفتاح JSON، واستدعِ .with_subject(user_email) للتفويض
  • النطاقات: اطلب الحد الأدنى اللازم (gmail.readonly وgmail.send وcalendar.events)
  • أنشئ الخدمة باستخدام build('gmail', 'v1', credentials=creds)
  • التقط HttpError لأخطاء API، وأعد المحاولة عند ظهور 429/503
  • لا ترفق ملفات بيانات الاعتماد أبدًا؛ استخدم متغيرات البيئة في بيئة الإنتاج

الأسئلة الشائعة

هل درس «الاتصال بـ Gmail عبر API» مجاني؟

نعم — نص درس «الاتصال بـ Gmail عبر API» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.

ماذا ستتعلم في «الاتصال بـ Gmail عبر API»؟

مكتبة عميل Google API، وموافقة OAuth2، واختيار نطاقات Gmail تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟

لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «الاتصال بـ Gmail عبر API»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟

نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الاتصال بـ Gmail عبر API
  2. قراءة رسائل البريد وإرسالها برمجيًا
  3. إنشاء أحداث التقويم والاستعلام عنها
  4. بناء وكيل مساعد بسيط للبريد الإلكتروني
← العودة إلى AI Agents