我正在尝试下载用户可以看到的Google日历列表。我已经设置了服务帐户,并且我有这个代码(适用于Analytics API的其他帐户):
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
import pprint
def prepare_credentials():
f = file(keyFilePath, 'rb')
key = f.read()
f.close()
credentials = SignedJwtAssertionCredentials(
service_account_email_address, key,
scope='https://www.googleapis.com/auth/calendar.readonly')
return credentials
http = httplib2.Http()
credentials = prepare_credentials()
http = credentials.authorize(http)
service = build('calendar', 'v3', http=http)
httpRequest = service.calendarList().list()
data = httpRequest.execute()
pprint.pprint(data)
结果是:
{u'etag': u'"YXs7dfDSFSFD9F0k/sofIhuT4dSLyxKaRH7vNpx5BOEU"',
u'items': [],
u'kind': u'calendar#calendarList',
u'nextSyncToken': u'00001405024697194000'}
问题是,我知道我可以访问日历,我甚至使用过“试一试!”本页的部分:https://developers.google.com/google-apps/calendar/v3/reference/calendarList/list,返回预期结果,大约10个日历。我尝试过不同版本的范围参数('https://www.googleapis.com/auth/calendar.readonly'和['https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/calendar.readonly']),我也尝试添加自己的电子邮件地址作为“prn”和“sub”参数,所有这些都给我“访问被拒绝”错误。我无法弄清楚为什么我可以通过我的服务帐户获得授权,但是当使用不同的身份验证方法清楚地查看这些结果时,我无法实际查看结果。
我做错了什么?
答案 0 :(得分:2)
只是想用我实际上最终解决的解决方案来更新这个问题。
如果您希望服务帐户能够拥有日历上的所有者权限,则表明执行此操作的唯一方法是使用API创建辅助日历同时通过身份验证为服务帐户(https://developers.google.com/google-apps/calendar/v3/reference/calendars/insert)。服务帐户没有任何主要日历,但它将是新辅助日历的所有者。
然后,您可以使用访问控制规则API端点(https://developers.google.com/google-apps/calendar/v3/reference/acl/insert)与您自己的Google帐户(或任何可以登录以在浏览器中查看日历的非服务帐户)共享此日历。新用户也可以设置为所有者。
编辑:以下解决方案不准确。
这不是问题,但我无法在任何地方找到它,我想人们可能想知道,所以我也会在这里回答:
如果您希望与会者在插入或更新活动时收到电子邮件通知,则将“sendNotifications”参数设置为True并不是您需要做的唯一事情。与该用户共享日历后,用户还需要进入服务帐户日历的“日历设置”,并在“提醒和通知”标签中激活电子邮件通知。
编辑:这是不准确的。任何更改其设置以在此日历上接收通知的人都会收到,无论他们是否被邀请参加此活动。我还没有找到通过API邀请人们参与活动的方法服务帐户,只有受邀者才能收到邀请电子邮件。我将在StackOverflow上提出另一个关于此的问题。
答案 1 :(得分:1)
使用此用户的凭据执行呼叫时,只能看到特定用户的日历列表。服务帐户将始终为您提供属于该服务帐户的日历列表。如果您想访问日历列表,我建议您为帐户使用Oauth2令牌。
答案 2 :(得分:0)
经过一番挖掘后,您可以允许访问您域外的用户(api服务帐户)访问Google日历。
检查以下设置:Google管理员,Google Apps,日历,共享设置 并选择以下其中一项:
( ) Only free/busy information (hide event details) Default
( ) Share all information, but outsiders cannot change calendars
(X) Share all information, and outsiders can change calendars
( ) Share all information, and allow managing of calendars
然后,您可以在Share with specific people
这对某人有何帮助。
答案 3 :(得分:0)
最初,我自己也在努力解决这个问题。但我认为我取得了足够的进展以获得一些帮助。
看起来每个服务帐户都分配了一个唯一的" client_email"。该值是可下载的JSON文件中包含的字段,来自API - >项目的凭据部分。格式类似于 xxxxx-yyyyy@developer.gserviceaccount.com 。在上面的代码中,您似乎通过" service_account_email_address"来引用此值。变量。
由于client_email地址与您的个人电子邮件不同,因此您引用的主日历和辅助日历不是一回事。默认情况下,我认为服务帐户电子邮件中没有与之关联的日历,这就是您在结果中看不到任何日历的原因。当您添加两个日历然后使用calendarList.list()方法时,这一点就变得很明显了。但在添加任何日历之前,必须将范围从只读更改为读/写。您可以通过将代码更改为:
来完成此操作## Original Scope needs to be changed...
#scope='https://www.googleapis.com/auth/calendar.readonly'
## Must allow the ability to write to calendars...
scope='https://www.googleapis.com/auth/calendar'
一旦允许读/写,您可以添加两个日历,然后通过执行以下操作列出它们:
def createCalendar(): ## Create the calendar...
calendar = {
'summary': 'Calendar used to communicate lease end dates.',
'timeZone': 'America/Los_Angeles'
}
created_calendar = service.calendars().insert(body=calendar).execute()
print "Created Calendar ID: ", created_calendar['id']
## In main block of code, call the createCalendar() twice...
createCalendar()
createCalendar()
## Show the current list of calendars (should have 2 listed)...
httpRequest = service.calendarList().list()
data = httpRequest.execute()
pprint.pprint(data)
创建日历后,请尝试再次运行您的代码,您应该会看到您的"数据"中列出的两个新日历。结果现在。但是,这两个日历仍仅与服务帐户相关联。因此,如果您登录到您的个人电子邮件(myEmail@gmail.com),这些日历将无法显示在您的个人资料中(http://calendar.google.com)。
要让它们显示在您的个人日历列表中,您必须授予您的个人电子邮件地址权限,以查看和/或修改日历。为此,您必须插入一个ACL,为您的个人电子邮件(myEmail@gmail.com)提供适当的权限。
但是,如果您尝试转向其他方向(允许服务帐户访问您的个人日历)。您必须登录您的个人电子邮件帐户(myEmail@gmail.com),与服务帐户client_email共享特定日历,并分配适当的权限级别(进行更改和管理共享等)。与服务帐户共享日历后,日历将列在calendarList()。list()结果中,您应该能够按预期查看事件。