يجب السماح بالطلبات المرسَلة إلى Gmail API باستخدام OAuth 2.0. بيانات الاعتماد. يجب استخدام التدفق من جهة الخادم عندما يكون تطبيقك الوصول إلى واجهات Google APIs نيابةً عن المستخدم، على سبيل المثال عندما يكون المستخدم بلا اتصال بالإنترنت. تتطلب هذه الطريقة تمرير رمز تفويض يُستخدم لمرة واحدة من العميل إلى خادمك؛ يُستخدم هذا الرمز للحصول على رمز الدخول الرموز المميزة لتحديث خادمك.
لمزيد من المعلومات حول تنفيذ Google OAuth 2.0 من جهة الخادم، يُرجى الاطّلاع على استخدام OAuth 2.0 مع تطبيقات خادم الويب
المحتويات
إنشاء معرِّف عميل وسر عميل
لبدء استخدام Gmail API، عليك أولاً استخدام أداة الإعداد، التي ترشدك خلال إنشاء مشروع في وحدة التحكم في واجهة Google API، وتفعيل واجهة برمجة التطبيقات، وإنشاء بيانات الاعتماد.
- من صفحة بيانات الاعتماد، انقر على إنشاء بيانات اعتماد > عميل OAuth رقم التعريف لإنشاء بيانات اعتماد OAuth 2.0 أو إنشاء بيانات الاعتماد > الخدمة مفتاح الحساب لإنشاء حساب خدمة.
- إذا أنشأت معرِّف عميل OAuth، اختَر نوع تطبيقك.
- املأ النموذج وانقر على إنشاء.
يتم الآن إدراج معرِّفات العملاء ومفاتيح حساب الخدمة لتطبيقك على صفحة بيانات الاعتماد. للاطّلاع على التفاصيل، انقر على معرِّف عميل. تختلف المعلمات حسب نوع المعرّف، ولكن قد تتضمن عنوان البريد الإلكتروني أو سر العميل أصول JavaScript أو عناوين URL لإعادة التوجيه.
دوِّن Client-ID، إذ ستحتاج إلى إضافته إلى الرمز البرمجي لاحقًا.
التعامل مع طلبات التفويض
عندما يُحمِّل المستخدم تطبيقك للمرة الأولى، يتم عرض مربّع حوار لمنح تطبيقك الإذن بالوصول إلى حساباتهم على Gmail الذي يتضمن نطاقات الأذونات المطلوبة. بعد هذه المدة فلن يظهر للمستخدم مربع حوار الأذونات إلا إذا كان تغيير معرِّف العميل للتطبيق أو تغيير النطاقات المطلوبة.
مصادقة المستخدم
تعرض عملية تسجيل الدخول الأولية هذه كائن نتيجة تفويض يحتوي على رمز التفويض في حال نجاحه.
استبدال رمز التفويض برمز دخول
رمز التفويض هو رمز يُستخدم لمرة واحدة ويمكن للخادم استبداله رمز دخول. يتم تمرير رمز الدخول هذا إلى واجهة برمجة تطبيقات Gmail لمنح وصول تطبيقاتك إلى بيانات المستخدمين لفترة محدودة
إذا كان تطبيقك يتطلّب الوصول إلى "offline
"، ستكون المرة الأولى التي يتبادل فيها تطبيقك
رمز التفويض، فإنه يتلقى أيضًا رمزًا مميزًا لإعادة التحميل يستخدمه
الحصول على رمز دخول جديد بعد انتهاء صلاحية رمز مميز سابق. تطبيقك
بتخزين هذا الرمز المميز للتحديث (عادةً في قاعدة بيانات على الخادم)
لاستخدامه في وقت لاحق.
توضح نماذج التعليمات البرمجية التالية تبادل رمز التفويض
رمز دخول لديه إذن وصول offline
وتخزين الرمز المميّز لإعادة التحميل.
Python
استبدِل القيمة CLIENTSECRETS_LOCATION
بموقع
ملف client_secrets.json
.
import logging
from oauth2client.client import flow_from_clientsecrets
from oauth2client.client import FlowExchangeError
from apiclient.discovery import build
# ...
# Path to client_secrets.json which should contain a JSON document such as:
# {
# "web": {
# "client_id": "[[YOUR_CLIENT_ID]]",
# "client_secret": "[[YOUR_CLIENT_SECRET]]",
# "redirect_uris": [],
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://accounts.google.com/o/oauth2/token"
# }
# }
CLIENTSECRETS_LOCATION = '<PATH/TO/CLIENT_SECRETS.JSON>'
REDIRECT_URI = '<YOUR_REGISTERED_REDIRECT_URI>'
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
# Add other requested scopes.
]
class GetCredentialsException(Exception):
"""Error raised when an error occurred while retrieving credentials.
Attributes:
authorization_url: Authorization URL to redirect the user to in order to
request offline access.
"""
def __init__(self, authorization_url):
"""Construct a GetCredentialsException."""
self.authorization_url = authorization_url
class CodeExchangeException(GetCredentialsException):
"""Error raised when a code exchange has failed."""
class NoRefreshTokenException(GetCredentialsException):
"""Error raised when no refresh token has been found."""
class NoUserIdException(Exception):
"""Error raised when no user ID could be retrieved."""
def get_stored_credentials(user_id):
"""Retrieved stored credentials for the provided user ID.
Args:
user_id: User's ID.
Returns:
Stored oauth2client.client.OAuth2Credentials if found, None otherwise.
Raises:
NotImplemented: This function has not been implemented.
"""
# TODO: Implement this function to work with your database.
# To instantiate an OAuth2Credentials instance from a Json
# representation, use the oauth2client.client.Credentials.new_from_json
# class method.
raise NotImplementedError()
def store_credentials(user_id, credentials):
"""Store OAuth 2.0 credentials in the application's database.
This function stores the provided OAuth 2.0 credentials using the user ID as
key.
Args:
user_id: User's ID.
credentials: OAuth 2.0 credentials to store.
Raises:
NotImplemented: This function has not been implemented.
"""
# TODO: Implement this function to work with your database.
# To retrieve a Json representation of the credentials instance, call the
# credentials.to_json() method.
raise NotImplementedError()
def exchange_code(authorization_code):
"""Exchange an authorization code for OAuth 2.0 credentials.
Args:
authorization_code: Authorization code to exchange for OAuth 2.0
credentials.
Returns:
oauth2client.client.OAuth2Credentials instance.
Raises:
CodeExchangeException: an error occurred.
"""
flow = flow_from_clientsecrets(CLIENTSECRETS_LOCATION, ' '.join(SCOPES))
flow.redirect_uri = REDIRECT_URI
try:
credentials = flow.step2_exchange(authorization_code)
return credentials
except FlowExchangeError, error:
logging.error('An error occurred: %s', error)
raise CodeExchangeException(None)
def get_user_info(credentials):
"""Send a request to the UserInfo API to retrieve the user's information.
Args:
credentials: oauth2client.client.OAuth2Credentials instance to authorize the
request.
Returns:
User information as a dict.
"""
user_info_service = build(
serviceName='oauth2', version='v2',
http=credentials.authorize(httplib2.Http()))
user_info = None
try:
user_info = user_info_service.userinfo().get().execute()
except errors.HttpError, e:
logging.error('An error occurred: %s', e)
if user_info and user_info.get('id'):
return user_info
else:
raise NoUserIdException()
def get_authorization_url(email_address, state):
"""Retrieve the authorization URL.
Args:
email_address: User's e-mail address.
state: State for the authorization URL.
Returns:
Authorization URL to redirect the user to.
"""
flow = flow_from_clientsecrets(CLIENTSECRETS_LOCATION, ' '.join(SCOPES))
flow.params['access_type'] = 'offline'
flow.params['approval_prompt'] = 'force'
flow.params['user_id'] = email_address
flow.params['state'] = state
return flow.step1_get_authorize_url(REDIRECT_URI)
def get_credentials(authorization_code, state):
"""Retrieve credentials using the provided authorization code.
This function exchanges the authorization code for an access token and queries
the UserInfo API to retrieve the user's e-mail address.
If a refresh token has been retrieved along with an access token, it is stored
in the application database using the user's e-mail address as key.
If no refresh token has been retrieved, the function checks in the application
database for one and returns it if found or raises a NoRefreshTokenException
with the authorization URL to redirect the user to.
Args:
authorization_code: Authorization code to use to retrieve an access token.
state: State to set to the authorization URL in case of error.
Returns:
oauth2client.client.OAuth2Credentials instance containing an access and
refresh token.
Raises:
CodeExchangeError: Could not exchange the authorization code.
NoRefreshTokenException: No refresh token could be retrieved from the
available sources.
"""
email_address = ''
try:
credentials = exchange_code(authorization_code)
user_info = get_user_info(credentials)
email_address = user_info.get('email')
user_id = user_info.get('id')
if credentials.refresh_token is not None:
store_credentials(user_id, credentials)
return credentials
else:
credentials = get_stored_credentials(user_id)
if credentials and credentials.refresh_token is not None:
return credentials
except CodeExchangeException, error:
logging.error('An error occurred during code exchange.')
# Drive apps should try to retrieve the user and credentials for the current
# session.
# If none is available, redirect the user to the authorization URL.
error.authorization_url = get_authorization_url(email_address, state)
raise error
except NoUserIdException:
logging.error('No user ID could be retrieved.')
# No refresh token has been retrieved.
authorization_url = get_authorization_url(email_address, state)
raise NoRefreshTokenException(authorization_url)
التفويض باستخدام بيانات الاعتماد المخزنة
عندما يزور المستخدمون تطبيقك بعد الحصول على تفويض للمرة الأولى بنجاح فإن تطبيقك يمكن أن يستخدم رمز تحديث مخزنًا للسماح بالطلبات دون مطالبة المستخدم مرة أخرى.
إذا كنت قد صادقت المستخدم من قبل، يمكن لتطبيقك استرداد الرمز المميز للتحديث من قاعدة بياناته وتخزين الرمز المميز في جلسة المراجعة. في حال إبطال الرمز المميّز للتحديث أو كان غير صالح بأي شكل آخر، عليك يتعين علينا اكتشاف ذلك واتخاذ الإجراء المناسب.
استخدام بيانات اعتماد OAuth 2.0
بعد استرداد بيانات اعتماد OAuth 2.0 كما هو موضَّح في في القسم السابق، يمكن استخدامها لمصادقة عنصر خدمة Gmail وإرسال الطلبات إلى واجهة برمجة التطبيقات.
إنشاء مثيل لعنصر خدمة
يعرض نموذج الرمز هذا كيفية إنشاء مثيل لعنصر خدمة ثم تفويضه. لتقديم طلبات واجهة برمجة التطبيقات.
Python
from apiclient.discovery import build
# ...
def build_service(credentials):
"""Build a Gmail service object.
Args:
credentials: OAuth 2.0 credentials.
Returns:
Gmail service object.
"""
http = httplib2.Http()
http = credentials.authorize(http)
return build('gmail', 'v1', http=http)
إرسال الطلبات المصرّح بها والتحقّق من بيانات الاعتماد التي تم إبطالها
يستخدم مقتطف الرمز التالي مثيل خدمة Gmail المسموح به من أجل استرداد قائمة بالرسائل.
وفي حال حدوث خطأ، يتحقق الرمز من توفُّر رمز حالة HTTP 401
،
والتي يجب معالجتها من خلال إعادة توجيه المستخدم إلى صفحة الترخيص
عنوان URL.
يتم توثيق المزيد من عمليات واجهة برمجة تطبيقات Gmail في مرجع واجهة برمجة التطبيقات.
Python
from apiclient import errors
# ...
def ListMessages(service, user, query=''):
"""Gets a list of messages.
Args:
service: Authorized Gmail API service instance.
user: The email address of the account.
query: String used to filter messages returned.
Eg.- 'label:UNREAD' for unread Messages only.
Returns:
List of messages that match the criteria of the query. Note that the
returned list contains Message IDs, you must use get with the
appropriate id to get the details of a Message.
"""
try:
response = service.users().messages().list(userId=user, q=query).execute()
messages = response['messages']
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = service.users().messages().list(userId=user, q=query,
pageToken=page_token).execute()
messages.extend(response['messages'])
return messages
except errors.HttpError, error:
print 'An error occurred: %s' % error
if error.resp.status == 401:
# Credentials have been revoked.
# TODO: Redirect the user to the authorization URL.
raise NotImplementedError()
الخطوات التالية
عندما تشعر بالارتياح لتفويض طلبات واجهة برمجة تطبيقات Gmail، فأنت على استعداد في التعامل مع الرسائل وسلاسل المحادثات والتصنيفات، كما هو موضح في أقسام "أدلة المطوِّرين"
يمكنك الاطّلاع على مزيد من المعلومات حول طرق واجهة برمجة التطبيقات المتاحة في مرجع واجهة برمجة التطبيقات.