1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 | from BeautifulSoup import BeautifulSoup
import urllib
import httplib
GDATA_URL = '/accounts/ClientLogin'
class GdataError(Exception):
pass
class Gdata:
"""
A class to retrieve a users contacts from their Google Account.
Dependencies:
-------------
* BeautifulSoup.
* That's it. :-)
Usage:
------
>>> g = Gdata('email@example.org', 'password')
>>> g.login()
(200, 'OK')
>>> g.get_contacts()
>>> g.contacts
[(u'Persons Name', 'name@person.com'), ...]
"""
def __init__(self, username='test@gmail.com', password='test', service='cp'):
self.username = username
self.password = password
self.account_type = 'HOSTED_OR_GOOGLE' # Allow both Google Domain and Gmail accounts
self.service = service # Defaults to cp (contacts)
self.source = 'google-data-import' # Our application name
self.code = '' # Empty by default, populated by self.login()
self.contacts = [] # Empty list by default, populated by self.get_contacts()
def login(self):
"""
Login to Google. No arguments.
"""
data = urllib.urlencode({
'accountType': self.account_type,
'Email': self.username,
'Passwd': self.password,
'service': self.service,
'source': self.source
})
headers = {
'Content-type': 'application/x-www-form-urlencoded',
'Accept': 'text/plain'
}
conn = httplib.HTTPSConnection('google.com')
conn.request('POST', GDATA_URL, data, headers)
response = conn.getresponse()
if not str(response.status) == '200':
raise GdataError("Couldn't log in. HTTP Code: %s, %s" % (response.status, response.reason))
d = response.read()
self.code = d.split("\n")[2].replace('Auth=', '')
return response.status, response.reason
def _request(self, max_results=200):
"""
Base function for requesting the contacts. We'll allow other methods eventually
"""
url = '/m8/feeds/contacts/%s/base/?max-results=%d' % (self.username, max_results)
headers = {'Authorization': 'GoogleLogin auth=%s' % self.code}
conn = httplib.HTTPConnection('www.google.com')
conn.request('GET', url, headers=headers)
response = conn.getresponse()
if not str(response.status) == '200':
raise GdataError("Couldn't log in. HTTP Code: %s, %s" % (response.status, response.reason))
return response.read()
def get_contacts(self, max_results=200):
""" Parses the contacts (using BeautifulSoup) from self._request, and then populates self.contacts
"""
soup = BeautifulSoup(self._request(max_results))
self.contacts = []
for entry in soup.findAll('title'):
if len(entry.parent.findAll(['gd:email', 'title'])) == 2:
s = entry.parent.findAll(['gd:email', 'title'])
self.contacts.append((s[0].string, s[1].get('address')))
return
|
Comments
The problem with this approach is that you have to ask the user for their Gmail username and password, which they shouldn't be giving you as you aren't Google. Have you considered using the Google Contacts API instead?
#
Yes, you're right, Simon, AuthSub is what most people should use. In my case, ClientLogin provided the most fluent experience for the user (which was what my client requested), so I went for it.
I could always throw up an example using AuthSub, for those interested.
#