Gmal連絡先→LDAP

ちょこちょこいじってGmaiの連絡先メールアドレスをLDAPに取り込むPerlスクリプト完成\(^o^)/
なかったのでこんな感じでつくったのだ。

#!/usr/bin/perl

use strict;
use utf8;
use LWP::UserAgent;
use HTTP::Request::Common;
use URI::Escape;
use XML::Simple;
use Net::LDAP;
use Time::Piece;

#XML::Simpleのエラー回避
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';

#アプリケーション設定
my $uid_prefix = 'Gmail_';

#Googleアカウント情報
my $gdata_user = 'あなた@gmail.com';
my $gdata_pass = 'あなたのパスワード';

#UserAgent設定
my $ua = LWP::UserAgent->new();
my ( $req, $res, $url );

#LDAP設定
my $ldap_server = 'example.com';
my $base_dn = 'dc=example, dc=com';
my $root_cn = 'cn=Manager';
my $root_passwd ='LDAP管理者パスワード';
my $secure = 1; #LDAPSの場合:1

#LDAP接続
my ( $ldap_scheme, $ldap_port );
if( $secure ){
	$ldap_scheme = 'ldaps';
	$ldap_port = 636;
}
else{
	$ldap_scheme = 'ldap';
	$ldap_port = 389;
}
my $ldap = Net::LDAP->new( $ldap_server, port => $ldap_port, scheme => $ldap_scheme, );
unless( $ldap ){
	print &now, "LDAP server connect failed.\n";
	die "LDAP server connect failed.\n";
}
#LDAPログイン
my $ldap_msg = $ldap->bind( "$root_cn, $base_dn", password => $root_passwd );
if( $ldap_msg->code ){
	print &now, "LDAP account login failed.\n";
	die "LDAP account login failed.\n";
}
print &now, "LDAP server  logined.\n";

#登録中uidを検索→削除
{
	my $filter = "(uid=$uid_prefix*)";
	$ldap_msg = $ldap->search( base => $base_dn, filter => $filter );
	if( $ldap_msg->code ){
		print &now, "uid search failed.\n";
		die "uid search failed.\n";
	}
	foreach my $entry ( $ldap_msg->entries ){
		my $uid = $entry->get_value( 'uid' ),"\n";
		my $delete_dn = "uid=$uid, ou=People, " . $base_dn;
		$ldap_msg = $ldap->delete( $delete_dn );
			if( $ldap_msg->code ){
				print &now, "uid:$uid delete failed.\n";
				die "uid:$uid delete failed.\n";
			}
	}
	print &now, "All old entries deleted.\n";
}

#Googleアカウントにログイン
{
	$url = 'https://www.google.com/accounts/ClientLogin';
	my %post_data = (
		'Email' =>		$gdata_user,
		'Passwd' =>		$gdata_pass,
		'accountType' =>	'GOOGLE',
		'source' =>		'Google-Contact-Lister',
		'service' =>		'cp',
	);
	$req = POST( $url, [ %post_data ] );
	$res = $ua->request( $req );
}

#セッション・承認情報取得
my %session;
foreach my $line ( split( /\n/, $res->content ) ){
	my ( $key, $data ) = split( /=/, $line );
	$session{ $key } = $data;
}

#ログイン成功確認
unless( $session{ 'Auth' } ){
	print &now, "Google account login failed.\n";
	die "Google account login failed.\n";
}
print &now, "Google account logined.\n";

{
	#Google Acontact APIの検索設定
	my $index = 1;
	my $paging = 100;	# 2以上に設定すること
	my $total_results;

	my $add_count = 0;
	do {
		$url = 'https://www.google.com/m8/feeds/contacts/' .
				uri_escape( $gdata_user ) .
				"/full?start-index=$index&max-results=$paging";
		$req = GET( $url );
		$req->header( Authorization => "GoogleLogin auth=$session{ 'Auth' }" );
		$res = $ua->request( $req );

		my $xml_parser = XML::Simple->new();
		my $parsed_data = $xml_parser->XMLin( $res->content );

		$total_results = $parsed_data->{ 'openSearch:totalResults' };

		foreach my $key ( keys( %{ $parsed_data->{ 'entry' } } ) ){
			#Google Acontactのデータパース
			my $uid = $uid_prefix . ( split( /\//, $key ) )[-1];
			my $common_name = $parsed_data->{ 'entry' }{ $key }{ 'title' }{ 'content' };
			my ( $surname, $given_name ) = split( / /, $common_name );

			#email複数対応
			my @email_list;

			my $elem = $parsed_data->{ 'entry' }{ $key }{ 'gd:email' };
			#エントリーが1つだけの時
			if ( $elem =~ /^HASH/ ){
				push( @email_list, $elem->{ 'address' } );
			}
			#エントリーが複数の時
			elsif( $elem =~ /^ARRAY/ ){
				foreach my $temp ( @$elem ){
					push( @email_list, $temp->{ 'address' } );
				}
			}

			my $suffix = 1;
			foreach my $email ( @email_list ){
				#LDAP操作
				my $uid_s = $uid . "_$suffix";
				my $add_dn = "uid=$uid_s, ou=People, " . $base_dn;
				if( $email ne '' ){
					my %attrs = (
						'uid' =>			$uid_s,
						'cn' =>				$common_name,
						'sn' => 			$surname,
						'objectClass' =>	[ 'inetOrgPerson', 'top', ],
						'mail' =>			$email,
						'description' =>	"Gmail to LDAP uid: $uid_s",
					);
					if( $given_name ne '' ){
						$attrs{ 'givenName' } = $given_name;
					}
					$ldap_msg = $ldap->add( $add_dn, attrs => [ %attrs ] );
					if( $ldap_msg->code == 0 ){
						$add_count++;
					}
				}
				$suffix++;
			}
		}
		$index += $paging;

	} while( $index unbind;
print &now, "Operation completed.\n";

sub now{
	my $now = Time::Piece::localtime();
	return '[' . $now->strftime('%Y-%m-%d %H:%M:%S') . '] ';
}

機能的には電話番号とか住所も取り込んだり、双方向でデータのやりとりができるといいかな?