TUTORIAL Google Contacts to Asterisk Phonebook

Al Grant

Member
Joined
Jun 4, 2014
Messages
30
Reaction score
0
Yes but given that astdb is not mysql it will need significant editing beyond what I could do.

If the people who wrote the phone book script think asterisk. Users is a good place to read contacts from why is it a bad idea to store them there?
 

Al Grant

Member
Joined
Jun 4, 2014
Messages
30
Reaction score
0
Thanks for the link.

I will read it in detail when I'm not on my phone.

Still just asking however, could I use the Cisco phone script modified to read a different table with the asteridex script in this thread modified to write to the same table?
 

james

Guru
Joined
Oct 18, 2007
Messages
375
Reaction score
38
Location
Mesa, AZ
If the people who wrote the phone book script think asterisk. Users is a good place to read contacts from why is it a bad idea to store them there?
Just because you can write a script or hack one together doesn't mean you know what youre doing.
 

james

Guru
Joined
Oct 18, 2007
Messages
375
Reaction score
38
Location
Mesa, AZ
The author (Sanjay Willie, for whom I have some respect in these matters) reads the users table only to build a list of local extensions. The users table stores internal FreePBX config, and most certainly is not an appropriate place to store contacts.

Your solution is to sync the contacts to an actual contact database then modify your phone script to read from there.
I wasn't trying to insult this Dev. I didn't even look at the script. I was just answering why devs do things that aren't smart.

On topic. If you are ultimately generating an XML file and using an XML library why do you need a database at all. Just use the XML file as your data store
 
  • Like
Reactions: lgaetz

Al Grant

Member
Joined
Jun 4, 2014
Messages
30
Reaction score
0
I got it to run nicely with accountingnerds version.

But on the phone all the numbers have a leading "9" appended.

I have set country code to "64" since I am in NZ.

Where did the "9" come from?

Cheers

-Al
 

Rrrr

Tink
Joined
May 28, 2009
Messages
332
Reaction score
25
Hi

Looking to set up MySQLdb in Incredible PBX with ubuntu 14.4 (RentPBX)
I am now setting up the python script which has following error:

File "./googlepbxcontacts0.95step1.py", line 358, in main
import MySQLdb
ImportError: No module named MySQLdb
[email protected]:~/Google/gdata-2.0.18# dpkg --get-selections | grep mysql
libdbd-mysql-perl install
libmysqlclient-dev install
libmysqlclient18:i386 install
mysql-client install
mysql-client-5.5 install
mysql-client-core-5.5 install
mysql-common install
mysql-server install
mysql-server-5.5 install
mysql-server-core-5.5 install
php5-mysql install
The information provided here is for Raspberry (debian) and BBB (ubuntu 13.4), so I am just verifying, not wanting to disturb a clean start.

How to install the MySQLdb python connector module, can I do same for ubuntu 14.4 as for the BBB with ubuntu 13.4? I remembered a wise lesson from Ward once, but again am unwilling to just run some old install on good luck.
http://direct.installion.co.uk/ubuntu/trusty/universe/p/python-mysql.connector/en/install/index.html
http://stackoverflow.com/questions/3047848/why-cant-easy-install-find-mysqldb/3047938#3047938
http://stackoverflow.com/questions/10062002/mysqldb-for-python-2-7-ubuntu


update
SOLVED: I tried these commands successfully:

Code:
sudo apt-get install python-mysqldb
sudo apt-get install python-mysql.connector


Thanks
 

vikeq

New Member
Joined
Dec 12, 2011
Messages
3
Reaction score
0
Hi I'm using this script of Jay schulmann (post #15), but have issue:

Sortie de la commande python /usr/lib/python2.4/googlecontacts_origin_test.py ..

11 database entries removed.
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Updated database successfully
Traceback (most recent call last):
File "/usr/lib/python2.4/googlecontacts_origin_test.py", line 70, in ?
main()
File "/usr/lib/python2.4/googlecontacts_origin_test.py", line 66, in main
os.system("asterisk -rx \'database put cidname %s%s \"%s\"\'" % (country_code,phone.text,entry.title.text))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 48: ordinal not in range(128)

here is my script googlecontacts_origin_test.py

Code:
#!/usr/bin/python
# googlecontacts.py v0.1apps
# Original By: John Baab
# Email: [email protected]
# Updated By: Jay Schulman
# Email: [email protected]
# Purpose: syncs contacts from google to asterisk server
# Updates: Updating for Google API v3 with support for Google Apps
# Requirements: python, gdata python client, asterisk
#
# License:
#
# This Package is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This package is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this package; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
# On Debian & Ubuntu systems, a complete copy of the GPL can be found under
# /usr/share/common-licenses/GPL-3, or (at your option) any later version
 
import atom,re,sys,os
import gdata.data
import gdata.auth
import gdata.contacts
import gdata.contacts.client
import gdata.contacts.data
 
email = '[email protected]'
password = 'xxx'
domain = 'mydomain.com'
 
def main():
    # Change this if you aren't in the US.  If you have more than one country code in your contacts,
    # then use an empty string and make sure that each number has a country code.
    country_code = ""
 
    gd_client = gdata.contacts.client.ContactsClient(domain=domain)
    gd_client.ClientLogin(email, password, 'google2asterisk')
    qry = gdata.contacts.client.ContactsQuery(max_results=2000)
    feed = gd_client.GetContacts(query=qry)
 
    # delete all of our contacts before we refetch them, this will allow deletions
    os.system("asterisk -rx \'database deltree cidname\'")
 
    # for each phone number in the contacts
    for i, entry in enumerate(feed.entry):
        for phone in entry.phone_number:
            # Strip out any non numeric characters
            phone.text = re.sub('\D', '', phone.text)
 
            # Remove leading digit if it exists, we will add this again later for all numbers
            # Only if a country code is defined.
            if country_code != "":
                phone.text = re.sub('^\+?%s' % country_code, '', phone.text)
 
            # Insert the number into the cidname database, reinsert the country code if defined.
            os.system("asterisk -rx \'database put cidname %s%s \"%s\"\'" % (country_code,phone.text,entry.title.text))
 
 
if __name__ == "__main__":
        main()
thank you for help

UPDATE: my problem is solved by change "entry.title.text" to "entry.title.text.encode('utf-8')"
because in FRANCE we use "ë" or "é" ...
 

ThommyB

New Member
Joined
Mar 25, 2015
Messages
1
Reaction score
0
I am a user on a private system that serves as a bridge between Google Voice and Asterisk for several users (friends and family type of setup). I would like it if when a call comes on my Google Voice number, it would look up the number in my Google contacts and then use the name for that contact as the caller ID name. The system administrator has said that he would not mind setting this up for me and he has looked at this thread but he's confused by all the different scripts available, and he says that as best he can tell they all seem to write the phone numbers from a person's Google contacts list into the common Asterisk phone book, or into some other database that referenced on all incoming calls intended for all users on the system, not just those intended for me. My contacts list is rather large (around 1,000 entries) and many of them have name entries that mean something only to me, such as the person's first name only.

He says there are two ways it could possibly be done. If there is a way to access a specific user's Google contacts in real time when an incoming call comes in, he says he can create custom dialplan so that this would happen for my calls only, but he hasn't found any way to do a query from within a script where you put in a phone number and get back a name, or even the entire record containing that number, in real time. This would be the method I'd prefer, so that any new contacts I add would be used immediately.

Alternately, he says that if there is a way to get the "good" data into name and number pairs and put them into a custom Asterisk database, similar to the one used for blacklisted numbers but with a different database name, he could write some custom code similar to that used to check the blacklist that would run only when a call comes in on my number, and if the calling number is found in the "my" custom database then it would be used as the caller ID name. Neither he nor I like that idea quite as much, but he says he could do that if he knew how to get the names and numbers from a Google contacts list and put them into a unique Asterisk database for each user using a script. He says his preference for scripts are bash or perl, but he would use a python or ruby script if it would do what we need.

Either way, he says that each user on the system would then only be using their personal Google contacts as a lookup source for their personal calls. My question is, do any of these scripts work in either of those ways, or could they be easily adapted to do so?
 

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20
I have this running nightly on my PBX (you can do it more often than that - google 'cron'). The script that worked for me was googlepbxcontacts0.95.py. I'm using Google Apps, BTW.
The scripts could certainly be adapted. As I remember, though, there isn't a "lookup by phone number" function in the Google API- so you'd have to iterate through contacts.
Google has a limit to the number of queries you can make per month.
So it makes sense to iterate through the database every few hours or daily rather than every time a phone call comes in.
Secondarily, there's a speed issue (local db lookup is always going to be faster - especially as it is keyed on phone).

The db being used is Ward Mundy's "Asteridex". It's also a web app - so you can go to the app, find the contact you want to call, click the number and have a connection setup between your extension and an outgoing call to that number.

There's also an Asteridex module in CID Superfecta which lets you lookup numbers before you go on to making external queries - and, even if you use OpenCNAM or the like there won't be much info for wireless callers, so IMO better to look here first, save the .01 cents (or whatever) but also have better info.


preference for scripts are bash or perl
It's bash now. He'd need to figure out the Google API to some extent. If nothing else the script is a good "how it works" example, but it's not hard. You'll need to be able to login as each of your users.

Also, assuming you have users Joe and Fred, why is it bad that, if a friend of Fred's calls Joe, that Joe sees who it is, rather than, say "wireless caller"?

serves as a bridge between Google Voice and Asterisk
You mean GTalk/XMPP? Google keeps announcing that they're going to stop this service. They haven't yet. They may never. But who knows?
 

Rrrr

Tink
Joined
May 28, 2009
Messages
332
Reaction score
25
NEED HELP TO UPGRADE TO OAUTH 2.0

ThommyB
Hi I made googlepbxcontacts0.95.py out of a mix of previous posts. I am not a programmer, just a tweaker. :)

I have 6000 contacts and dont even run a cron daily, but just run the script once in a while.
In fact, I run the same script twice with different variable setting to do two things:

a) one run to read all contacts into a local asteridex db: this gives me callerid number and name on incoming calls.

b) another run to generate dial codes for a certain contact group. The dial codes are used when I want to dial out to someone and do not remember the phone number. For example: I dial 99927 (99WAR) to find the number for Ward Mundy. I have modified his TTS app CallWho to read to me all options: Ward Mundy (home), Ward Mundy (work), Warren Beatty (mobile) and then choose one (1-9).

I think it does what you want (under a), except for the user privacy issue, but it will be a nice challenge: we can (ab)use the contact email field (is now not used) as a contact owner identification for each contact in the database. We need to change the script to read contacts from multiple user accounts. Earlier in this thread there already is such script. And we need to change the lookup script to take all this into account.

But before you/we go on with this, I hope we can first update the program to comply with Google OAUTH 2.0 because otherwise the script will stop working next month. I have tried to read Google instructions, but I have not found/do not understand the right solution for a server app like this one. Part of it (consent) needs to be done online in a browser.

We need to modify this as it currently simply requires gmail username and password and thats not good anymore:
Code:
import atom,re,sys,os
import gdata.data
import gdata.auth
import gdata.contacts
import gdata.contacts.client
import gdata.contacts.data
import unicodedata
 
email = '[email protected]'          # Or use your google apps account
password = 'password'
domain = 'gmail.com'                  # Your domain in case of Google Apps
 
def main():
    import MySQLdb
...
    # Google Contacts API
    gd_client = gdata.contacts.client.ContactsClient(domain=domain)
    gd_client.ClientLogin(email, password, 'google2asteridex')
...
Can anybody provide some pointers here?
 

Rrrr

Tink
Joined
May 28, 2009
Messages
332
Reaction score
25
I really need some help on getting this to work from someone that actually understands this stuff.
Maybe this interests more people?

Here is my "research":

Code:
#!/usr/bin/python
 
 
import atom,re,sys,os
import gdata.data
import gdata.auth
import gdata.contacts
import gdata.contacts.client
import gdata.contacts.data
import unicodedata
 
 
# OAUTH 2.0
# http://www.jaco.it/blog/2013/05/31/google-api-oauth-2-dot-0-the-short-way
# http://stackoverflow.com/questions/18267749/importerror-no-module-named-apiclient-discovery
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import SignedJwtAssertionCredentials
import httplib2
import os.path
 
# Personal information!  You need to get your own from Google and give consent, somehow.
# in the OAUTH 2 Compute Engine and App Engine
clientid = 'SOMETHING.apps.googleusercontent.com'
service_account_name = 'SOMEEMAIL'
 
def main():
    import MySQLdb
 
 
    with open('/root/Google/gdata-2.0.18/OAUTHkey/client_secret_contacts.json', 'rb') as f:
        key = f.read()
   
    print "Key from file : %s " % key
 
    http = httplib2.Http()
    storage = Storage('credentialsfile.dat')
    credentials = storage.get()
    # https://developers.google.com/accounts/docs/OAuth2ForDevices#allowedscopes
    # https://www.googleapis.com/auth/contacts is read only
    # https://developers.google.com/api-client-library/python/guide/aaa_oauth#SignedJwtAssertionCredentials
    # The oauth2client.client.SignedJwtAssertionCredentials class is only used with OAuth 2.0 Service Accounts.
    # No end-user is involved for these server-to-server API calls, so you can create this object directly without using a Flow object.
 
    # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.client.SignedJwtAssertionCredentials-class.html
    # Credentials object used for OAuth 2.0 Signed JWT assertion grants.
    # This credential does not require a flow to instantiate because it represents
    # a two legged flow, and therefore has all of the required information to
    # generate and refresh its own access tokens.
    # SignedJwtAssertionCredentials requires either PyOpenSSL, or PyCrypto 2.6 or
    # later. For App Engine you may also consider using AppAssertionCredentials.
    if credentials is None or credentials.invalid:
        credentials = SignedJwtAssertionCredentials(
            service_account_name, key,
            scope='https://www.googleapis.com/auth/contacts')
        storage.put(credentials)
    else:
        credentials.refresh(http)
 
    http = credentials.authorize(http)
       
    # Google Contacts API
 
    # old gd_client = gdata.contacts.client.ContactsClient(domain=domain)
    # old gd_client.ClientLogin(email, password, 'google2asteridex')  
    # https://developers.google.com/google-apps/contacts/v3/?hl=fr--#authorizing_requests_with_oauth_20
    # gd_client = gdata.contacts.client.ContactsClient(source='<var>YOUR_APPLICATION_NAME</var>')
    gd_client = gdata.contacts.client.ContactsClient(source='google12asteridex')
    # how to link gd_client to service = build(serviceName='contacts', version='v3', http=http) ???
    gd_client = service.gdata.contacts.client.ContactsClient(source='google12asteridex')
 
    print "Google contact data for `%s`" % service_account_name
 
    # Get groups
    feedg = gd_client.GetGroups()
 
    # END OF Main
 
if __name__ == "__main__":
        main()
 

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20
You can use OAUTH 2.0 for server-to-server (which fits this application).
To use it, you need to create a service account, give that account permissions, then create one (or more) key pairs associated with that service account, and use that with the OAUTH library.
In order to give the service account permissions to a second account (or a full domain) this needs to be Google Apps. The advantage here is that you'd have access to all user's (and shared) contacts within your domain.
see https://developers.google.com/identity/protocols/OAuth2ServiceAccount

For thise not using GApps, we might need a different approach.
Google Script app to email contacts with phone numbers as CSV list to PBX
On the PBX, a script to receive the email, unpackage the CSV and update the Asteridex database.

I have the Gscript working (built it long ago)
The Linux part (not done):
- configure postfix/sendmail/dovecot to receive email from Gmail (or maybe just use fetchmail)?
- write code to trigger on incoming email with particular characteristics (procmail?)
- read email body as CSV, walk lines
- update AsteriDex db (tested code already in script but writing to a db is the least of my issues)

So - is anyone using this script, needs the functionality, but is not using Google Apps?
 

lrosenman

Guru
Joined
Oct 17, 2014
Messages
222
Reaction score
30
Location
Austin, TX US
I'm not using Google Apps, but have a developers console -- I'll look at what I need to do, as I DO scrape my contacts with one of the Python scripts that's floating around.....
 

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20
I can get you as far as "contacts emailed to wherever" which deals with OAUTH 2 on the GScript side (just a matter of clicking some boxes when you first try to run).
  • go to https://script.google.com
  • click "create script for blank project"
  • paste the code below in - change [email protected]_domain.com to wherever you want things sent
  • file / save
  • click run, select function emailPhoneContacts
    • there'll be some dialog boxes asking you if you're sure you want this to run. click yes
  • click run again, select function emailPhoneContacts again - this time you should end up with an email wherever you specified
  • click the thing that looks like a stopwatch (round icon)
  • you'll get a dialog box that says "current project's triggers" with a link to create a new trigger - click that
  • it should be somewhat self explanatory - select function emailPhoneContacts (yeah, again), timer-driven (all there is) and how often you want it to run. IMO daily is fine, but that's me
Code:
function emailPhoneContacts() {
  var csvList = getPhoneContactsAsCSV();
  MailApp.sendEmail("[email protected]_domain.com",    // email to send to
                  "phone contacts",    // subject line of email
                  csvList);
}
 
function getPhoneContactsAsCSV() {
  var csvLines = new Array();
  var regex = new RegExp('^1|^[+]1|[^0-9+x]','g');
  // get all contacts
  var contacts = ContactsApp.getContacts();
  // walk through 'em; we only want the ones with at least one phone number
  for (var i=0; i<contacts.length; i++){
    var contact = contacts[i];
    var fullName = contact.getFullName();
   
    // walk though contact's phone(s)
    var phones = contact.getPhones();
    if(phones.length > 0) {
      var csvline = '';
      for (var p=0; p<phones.length; p++){
        var phoneNum = phones[p].getPhoneNumber().toString().replace(regex,'');
        var label = (phones[p].getLabel()).toString().toLowerCase().replace('_phone','').replace('_',' ');
        csvline = '"' + fullName + '","' + label + '","' + phoneNum + '"\r\n';
        csvLines.push(csvline);
      }
    }     
  }
  csvLines.sort();
  return(csvLines.join(''));
}
 
// APIs used:
// https://developers.google.com/apps-script/reference/mail/mail-app
// https://developers.google.com/apps-script/reference/contacts/
 

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20
Is it reasonable to expect Postfix? I can trigger a script upon a specified email with a postfix filter.
Otherwise, it's procmail or maybe inotifywait or... (any other likely suspects?) Does semdmail/dovecot/exim/whatever have the same capability?

Or maybe lrosenman has figured a non-GApps solution to OAUTH 2.0 (?)
 

lrosenman

Guru
Joined
Oct 17, 2014
Messages
222
Reaction score
30
Location
Austin, TX US
Exim/Dovecot can run scripts (Exim native or Sieve, and Dovecot also runs Sieve on Local delivery).

That said, I haven't had the time to investigate what it would take for a non-GApps OAUTH 2.0 solution yet.
 

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20
Given that there's no single expectable email server, and my current disinterest in learning/documenting how to trigger scripts in all, perhaps the most general solution is (as above) email GContacts via Gscript to some email box (and so deal with OAUTH 2.0) and then write a script in, say, Python, that reads email via either POP or IMAP. As I remember, there are a boatload of Python libraries for doing either kind of access.

Also: it would only increase the number of "moving parts" to two.
 

bobkoure

Member
Joined
May 22, 2013
Messages
176
Reaction score
20
So, here's the code to read the contact csv email sent by the gscript above.
No bells and whistles - but it works fine.

Googlepbxcontacts continues to work fine so long as you log in with username / password.
This gscript/python would be for the situation where you don't want a google account username/password exposed in a script - and you're not using GApps (where OAUTH should work fine). Note that you still expose a username/password, but it's for an email account you only use to receive contact updates - so it's not world shattering if someone gets it.

I'm posting this (working but missing features) in case the username/password login stops working and I'm busy when that happens. Enjoy! Or enjoy not needing it, I guess...

Code:
#!/usr/bin/env python
 
# Partial reimplementation of googlepbxcontacts, using GScript/IMAP to 'sidestep' OAUTH 2.0 (which interferes with direct scraping)
#
# This app looks in the mailbox EMAIL_ACCOUNT in the folder EMAIL_FOLDER for email from a GScript that sends contact information as a
# 3-column CSV (columns are name, label, number)
# Only email sent from SENT_FROM with a title containing SENT_TITLE** are accepted, lines without 3 columns are ignored.
 
# 05/04/2015 initial coding Bob Koure
#
 
 
import sys
import imaplib
import email
import datetime
import StringIO
import csv
import re
import MySQLdb
import unicodedata
 
 
EMAIL_ACCOUNT = "[email protected]" # account you are sending contacts updates TO
EMAIL_PASSWD = "passw0rd"
EMAIL_FOLDER = "INBOX"          # you can use a folder(tag) instead - e.g. "contacts", "pbx/contact updates" -- Use a GMail filter to move incoming folder updates there
SENT_FROM = '[email protected]'    # the account you are sending contacts FROM (the one you login to to run the emailphonecontacts google script (also useful if we ever support updates from multiple users)
SENT_TITLE = 'phone contacts'  # must be in the subject line - feel free to change, but also change in emailphonecontacts google script
 
IMAP_SERVER = 'imap.gmail.com'  # no need to ever change this
 
# mysql database connection settings
dbhost = "localhost";
dbpass = "passw0rd";                  # passw0rd for non raspberry PIAF
dbuser = "root";
dbname = "asteridex";
dbtable = "user1"                      # user1 for filling the original Asteridex table,
#dbtable = "pbxcontacts"              # or your own table name for example to create test tables.
 
# global variables, other variables are defined under main()
g_replacecontacts = 0                  # 0 = delete data in dbtable 1 = remove/re-insert contacts from CSV
g_printtraceinfo = 0                  # 1 to trace and print throughout the program, 2 to print more detail
 
 
 
def strip_accents(s):
  # remove accents from characters in a name (note: gscript mailapp uses iso8859.1 _in_the_US)
  return ''.join(c for c in unicodedata.normalize('NFD', s.decode('iso-8859-1'))
                  if unicodedata.category(c) != 'Mn')
               
 
 
def process_CSV(scsv):
    global g_replacecontacts
    icount = 0
 
    f = StringIO.StringIO(scsv)
    contacts = list(csv.reader(f, delimiter=','))  # sidestep renitializing CSV iterators
 
    print len(contacts), " contacts in CSV"
    if len(contacts) == 0: return
 
    try:
        # Open database connection and prepare a cursor object using cursor() method
        db = MySQLdb.connect(dbhost, dbuser, dbpass, dbname )
        cursor = db.cursor()
        # execute SQL query using execute() method.
        cursor.execute("SELECT VERSION()")
        # Fetch a single row using fetchone() method.
        data = cursor.fetchone()
        print "Main: Database version : %s " % data
    #except MySQLError:
    except:
        print "Error opening database ", dbname
        return
 
  # Clean up database table, unless user wants to replace contacts that are already in database
    if g_replacecontacts :
        print "Replacing existing contact group in the %s database." % (dbname)
    else:
        # delete all of our contacts before we refetch them, this will propagate deletions
        print "Deleting existing table %s in the %s database." % (dbtable, dbname)
        cursor.execute("DELETE FROM %s" % dbtable)
        cursor.close()
        # re-instantiate the cursor
        cursor = db.cursor()
 
    # for each contact
    for contact in contacts:
        if len(contact) >=3:
            name = strip_accents(contact[0])
            label = contact[1]
            number = contact[2]
            nameandlabel = name + ' ' + '('+ label + ')'
            print name, label, number
 
            if g_replacecontacts: # if replacing contacts, delete matching entry (TO DO replace with select where / update)
                    sql = "DELETE FROM `%s`" % dbtable
                    sql += "WHERE `name` REGEXP '^%s'" % nameandlabel  # name (label): ^ starts with name
                    try:
                        cursor.execute(sql)
                        db.commit()
                        if g_printtraceinfo > 0: print "Main: name `%s` DELETED from db" % normalised_name
                    except:
                        db.rollback()
                     
            # punting on formatting numbers
            contact_outnumber = number
            # punting on dialcode for now         
            contact_group = "*"
            contact_dialcode = ""
         
            contact_email = "not set"  # WHY is this column here? Easy enough to pass 'em in if there's aneed/use
         
            sql = "INSERT INTO `%s`" % dbtable
            sql += "(`name`, `in`, `out`, `dialcode`, `email`) VALUES ('%s', '%s', '%s', '%s', '%s' )" % \
                  (nameandlabel, contact_group, contact_outnumber, contact_dialcode, contact_email)
            try:
                cursor.execute(sql)
                db.commit()
                if g_printtraceinfo > 0: print "Main: name `%s` INSERTED into db" % contact_name
            except:
                db.rollback()
            icount += 1
         
    print "inserted",icount,"contacts of", len(contacts)
 
 
def process_mailbox(M):
    rv, data = M.search(None, "ALL")    # search gets a list of message sequence numbers
    if rv != 'OK':
        print "No messages found"
        return
 
    for num in data[0].split():
   
        rv, data = M.fetch(num, "(BODY[HEADER.FIELDS (FROM)])")
        if rv != 'OK': continue
        #print "From: ", data[0][1].strip('\r\n')
        if not SENT_FROM in data[0][1]: continue
           
        rv, data = M.fetch(num, "(BODY[HEADER.FIELDS (SUBJECT)])")
        if rv != 'OK': continue
        #print "Subject: ", data[0][1].strip('\r\n')
        if not SENT_TITLE in data[0][1]: continue
 
        # sender and subject indicate a contacts update, get the entire email
        rv, data = M.fetch(num, '(RFC822)')
        if rv != 'OK': continue
     
        msg = email.message_from_string(data[0][1])
     
        date_tuple = email.utils.parsedate_tz(msg['Date'])
        if date_tuple:
          local_date = datetime.datetime.fromtimestamp(
              email.utils.mktime_tz(date_tuple))
          print "Local Date:", \
              local_date.strftime("%a, %d %b %Y %H:%M:%S")
 
       
        if msg.is_multipart(): continue # sent from GScript MailApp as single part email
 
        type = msg.get_content_type()
        print type
        if type != 'text/plain': continue
     
        csv = msg.get_payload(None, True)
        process_CSV(csv)
     
        # done with this email, delete* it
        M.store(num, '+FLAGS', '\\Deleted')
        M.expunge()
 
   
 
 
def main():
    M = imaplib.IMAP4_SSL(IMAP_SERVER)
    M.login(EMAIL_ACCOUNT, EMAIL_PASSWD)
    rv, data = M.select(EMAIL_FOLDER)
    if rv == 'OK':
        print "Processing mailbox: ", EMAIL_FOLDER
        process_mailbox(M)
        M.close()
    else:
        print "ERROR: Unable to open mailbox ", rv
    M.logout()
 
if __name__ == "__main__":
    main()
 

Zento

New Member
Joined
May 27, 2015
Messages
4
Reaction score
0
Hi. I was using this script until Google finally deprecated its login method.

I've been looking for a replacement, and seems that the best way is using OAuth 2.0 for Devices. It has scope available for read-only access to contacts.

Unfortunately, I have not much time available for testing, but this blog post has code in Python that could be a good starting point for someone experienced in this language: http://blog.warehouseman.com/2014/09/gspreadHelloOAuthWorld.html.
 

Members online

PIAF 5 - Powered by 3CX

Forum statistics

Threads
22,522
Messages
138,571
Members
14,648
Latest member
KellyOnley