RT @龍神: http://piao-tech.blogspot.com/2010/01/google-contacts-in-mutt.html
#!/usr/bin/env ruby1.8
##
# File: contactos.rb
# Author: Horacio Sanson (hsanson at gmail)
# Date: 2010/01/22
#
# Descr:
# Small script to facilitate use of GMail contacts within mutt email client.
#
# Features:
# - Generates a list of group and subscribe commands generated from your
# GMail contacts groups that can be sourced from your muttrc file.
# - Can be used to search for contacts within mutt using the query_command
# option in the same way abook or ldbd are used.
# - Results are cached for a period of time (configurable) to speed up
# queries.
#
# Installation:
# To use this script you need ruby and rubygems 1.8 and the gdata gem. To
# install these in Ubuntu/Kubuntu use the following commands.
#
# sudo aptitude install ruby1.8 rubygems-1.8 libopenssl-ruby1.8
# sudo gem1.8 install gdata
#
# Make sure to read the comments below to learn how to configure this script
# to work with your GMail account.
#
# Then in your muttrc file add these lines:
#
# source '/PATH_TO_SCRIPT/contactos.rb --groups|'
# source '/PATH_TO_SCRIPT/contactos.rb --subscribes|'
# set query_command ="/PATH_TO_SCRIPT/contactos.rb --mutt %s"
# set query_format="%4c %t %-40.40a %-40.40n %?e?(%e)?"
# bind editor <Tab> complete-query
# bind editor ^T complete
#
# with this configuration you will be able to use your GMail groups in all
# regexp's and create hooks for them. Pressing <tab> when filling a To: or
# From: header will give you a list of options to choose or auto complete the
# address if only one matches.
#
# Resources:
# - http://antonyjepson.wordpress.com/2009/06/27/using-your-gmail-contacts-in-mutt/
# - http://www.chizang.net/alex/blog/code/mutt-query-gmail/
# - http://castrojo.wordpress.com/2009/01/28/gmail-contacts-with-mutt/
# - http://wiki.mutt.org/?QueryCommand
# - http://code.google.com/apis/contacts/docs/3.0/reference.html#Feeds
# - http://code.google.com/apis/gdata/articles/gdata_on_rails.html#GettingStarted
#
# TODO:
# - Mutt only sources the group list once on startup. If we add new groups or
# add contacts to a group these won't be reflected in mutt until we restart
# it. Not really a problem because mutt has the fastest start up time.
# - Create a script to add contacts from within mutt.
# - Find if create-alias can accept a script as parameter.
require "rubygems"
require "gdata"
require "fileutils"
require "pp"
## Set up here your GMail account username and password
USERNAME="YOUR-USERNAME"
PASSWORD="YOUR-PASSWORD"
# You may create a group in you GMail contacts and add all the mailing lists
# you are subscribed into that group. This script will generate a bunch of
# subscribe commands for all addresses in that group.
MAILISTGROUP="Mailing Lists"
# Make sure this value is larger than the total number of contacts you have.
MAXRESULTS=999
# How much time before the local cache expires in seconds.
UPDATE_INTERVAL=3600
# Where to store the local cache for faster query times.
CACHEFILE="~/.mutt/cache/gcontacts"
###############################################################################
## DON'T CHANGE ANYTHING BELOW THIS POINT
## unless you know what your are doing
###############################################################################
class Contact
attr_accessor :emails, :groups
attr_reader :name, :id
def initialize(id, name="")
@id = id
@name = name
@emails = []
@groups = []
end
def mutt_match(pattern)
return mutt_fmt if @name and @name =~ Regexp.new(pattern,Regexp::IGNORECASE)
str = ""
@emails.each { |email|
str << "#{email}\t#{@name||email}\t#{@groups.first}\n" if email =~ Regexp.new(pattern,Regexp::IGNORECASE)
}
str
end
def mutt_fmt
str = ""
@emails.each { |email|
str << "#{email}\t#{@name||email}\t#{@groups.first}\n"
}
str
end
end
# This method updates the local cache if the cache file is not present or if the
# UPDATE_INTERVAL has expired.
def update_cache
user_hash = nil
if ! File.exists?(File.expand_path(CACHEFILE)) or Time.now - File.stat(File.expand_path(CACHEFILE)).mtime > UPDATE_INTERVAL
#STDERR << "Updating from gmail\n"
user_hash = {}
client = GData::Client::Contacts.new
begin
client.clientlogin("#{USERNAME}@gmail.com", PASSWORD)
rescue GData::Client::AuthorizationError
STDERR << "Failed to authenticate\n"
return nil
rescue => e
STDERR << "Failed to log into Gmail: #{e}\n"
end
# Create a hash list of all groups
group_hash = {}
groups = client.get("http://www.google.com/m8/feeds/groups/#{USERNAME}%40gmail.com/full?max-results=#{MAXRESULTS}").to_xml
groups.elements.each('entry') { |entry|
name = entry.elements['title'].text.gsub("System Group: ","")
id = entry.elements['id'].text
group_hash[id] = name
}
# Create a hash list of all users
feeds = client.get("http://www.google.com/m8/feeds/contacts/#{USERNAME}%40gmail.com/full?max-results=#{MAXRESULTS}").to_xml
feeds.elements.each('entry') { |entry|
name = entry.elements['title'].text
id = entry.elements['id'].text
new_contact = Contact.new(id, name)
entry.elements.each('gd:email') { |email|
new_contact.emails << email.attribute('address').value
}
entry.elements.each('gContact:groupMembershipInfo') { |group|
new_contact.groups << group_hash[group.attribute('href').to_s]
}
user_hash[id] = new_contact
}
File.open(File.expand_path(CACHEFILE),"wb") { |fd|
fd << Marshal.dump(user_hash)
}
end
end
def load_cache
#STDERR << "Updating from local cache\n"
user_hash = {}
if File.exists?(File.expand_path(CACHEFILE))
File.open(File.expand_path(CACHEFILE),"rb") { |fd|
user_hash = Marshal.load(fd.read)
}
end
return user_hash
end
def print_help
puts "usage: "
puts " contactos.rb --mutt [pattern]"
puts " contactos.rb --groups"
puts " contactos.rb --subscribes"
puts " contactos.rb --aliases"
end
if ARGV.empty?
print_help
else
update_cache
contacts = load_cache
case ARGV[0]
when "--mutt"
puts "" # Mutt ignores the first line
if ARGV[1]
contacts.each { |k, contact|
STDOUT << contact.mutt_match(ARGV[1])
}
else
contacts.each { |k, contact|
STDOUT << contact.mutt_fmt
}
end
when "--groups"
contacts.each { |k,contact|
contact.groups.each { |g|
puts "group -group \"#{g}\" -addr #{contact.emails.join(', ')}" if ! contact.emails.empty?
}
}
when "--subscribes"
contacts.each { |k,contact|
contact.groups.each { |g|
if g == MAILISTGROUP and contact.emails.size > 0
puts "subscribe #{contact.emails.join(' ')}"
end
}
}
when "--aliases"
contacts.each { |k,contact|
contact.emails.each { |e|
if contact.name
puts "alias \"#{contact.name}\" #{contact.name} <#{e}>"
else
puts "alias \"#{e}\" #{e}"
end
}
}
when "-v"
when "--version"
puts "Contactos.rb version 0.2.0, Copyright 2010 Horacio Sanson"
when "-h"
when "--help"
print_help
else
print_help
end
end
安装、配置方法在代码开头已经说的很详细了。
打开 Mutt 写一封邮件,在编辑 To: 发件人栏(或 CC/BCC)的时候,和过去一样按 <Tab>
,几乎察觉不到延时,就能看到 GMail 里面的联系人了,还包括了分组信息,很不错。