Tuesday, February 22, 2011

Google contacts with sup email client.

Introduction


Recently I found about sup [1] and gave it a try to replace mutt. One of my requirements is access to my Gmail contacts from within the client so I can auto-complete the To, CC and BCC fields with my already registered contacts.

Fortunately I already had a ruby script to integrate Gmail contacts with mutt [2] and since sup can be extended via ruby scripts it was extremely easy to get my script working with sup.

SUP email client with Gmail contacts


Sup hooks system [3] is very powerful and allows us to add all kinds of functionality to sup using simple ruby scripts. One such hooks is called "extra-contact-addresses.rb" and from the hooks documentation we can read:



What this means is that we must create an script inside our $HOME/.sup/hooks directory called extra-contact-addresses.rb that returns an array of email addresses in plain format (e.g. myemail@gmail.com) or full format (e.g. User Name <username@gmail.com>).

Here is the script I implemented for this purpose:



Simply copy this script to "~/.sup/hooks/extra-contact-addresses.rb" and your are ready to go. When composing or replying and email you can press Tab to autocomplete email addresses.

Resources

[1] http://sup.rubyforge.org/
[2] http://piao-tech.blogspot.com/2010/01/google-contacts-in-mutt.html
[3] http://sup.rubyforge.org/wiki/wiki.pl?Hooks

Wednesday, December 29, 2010

Get KDE 4 .4.2 working with xrdp

Problem Statement

KDE4 [1] looks horrible when accessed remotely via vnc [2] and since xrdp [3] is simply a proxy that depends on vnc we get the same horrble look when accessing KDE using Windows RDP client.

The usual response from KDE developers is that vnc is bad and you should change your vnc server or use another remote desktop technology so I tested all vnc server implementations I found and I can tell that x11vnc is the only one that is simple and works correctly with KDE4 so the solution to my problem was simple: get xrdp to work with x11vnc.

Configure KDE4 with x11vnc server

This cannot be more easy. In Ubuntu simply install the package:

then in a terminal (konsole) run this command:

The first time you run this command it will ask you to input a password. Choose any one you like and remember it because you will need it to connect remotely to x11vnc. The -noxdamage option is only needed if you have desktop effects enabled in plasma. If you have these plasma effects enabled and you do not use the -noxdamage option you will see some XDamage errors in the x11vnc output. You can also ask x11vnc to turn off the monitor when a remote client connects using the -clientdpms option and to lock the screen when the client disconnects using the -gone option. Be warned that the -clientdpms and -gone options were not working very well last time I tried. For example is difficult to recover the session from the desktop unless the remote client
disconnects.

Configure KDE4 with xrdp server

Install the xrdp packages:

Edit the /etc/xrdp/xrdp.ini file and add an entry like:

Finally restart xrdp service:


Accessing remotely you KDE session via Windows RDP client

In a windows machine open the remote desktop client (usually found in accessories) and input your KDE machine IP address. After the connection is established you will get a popup with some options including the one we created above (MyHOME) so select it, input the password you set to x11vnc and enjoy.

Troubleshooting

If you use Gnome instead of KDE you be encounter a bug that messes up the keyboard [6]. To fix it you must disable the keyboard plugin of the gnome-settings-daemon using hte gconf-editor. To do this open the gconf-editor and navigate all the way to the folder:

and set the active option to False.

Enabling the Kana Henkan key (Japanese Keyboards)

To get the japanese kana key (top left in japanese keyboards) to work you need to apply a patch
[7] and install the patched deb:


Resources

[1] www.kde.org
[2] http://en.wikipedia.org/wiki/Virtual_Network_Computing
[3] http://xrdp.sourceforge.net
[4] http://forum.xbmc.org/showthread.php?t=74791
[5] http://adrianpopagh.blogspot.com/2010/06/connecting-with-remote-desktop-rdp-to.html
[6] https://bugs.launchpad.net/ubuntu/+source/xrdp/+bug/320393
[7] http://blogs.sun.com/thaniwa/entry/ja_xrdp

Saturday, November 06, 2010

2010 Vim Configuration

Monday, May 10, 2010

Japanese Input in Lucid Lynx (Kubuntu 10.04)

Introduction

Since Kubuntu 9.10 there is a movement to replace skim [1] with ibus [2] that seems to be a better alternative. Unfortunately after my latest upgrade to Kubuntu 10.04 this movement caused my Japanese input to stop working.

To get Japanese working again using ibus was actually very easy and here Iexplain the steps to do it.

Uninstall SCIM/SKIM packages

First we uninstall all SCIM and SKIM related packages to avoid any kinds of conflicts with the new iBus system.


Install iBus required packages


Second we install the iBus packages needed to support different language input methods.


Configure the system to auto-select the input method.

The im-switch utility is used to select input methods. For better results make sure you select auto.


Trouble Shooting


  • Japanese/Chinese/Korean/etc does not work in any applications.
  • Make sure you have all scim/skim related packages uninstalled and all required ibus packages installed. Also make sure you ran the im-switch command (with sudo) and set ibus in auto mode.
  • Japanese/Chinese/Korean/etc input work in KDE apps but no in GTK (Firefox, Chrome, Skype) apps!
  • This happens if you do not have the ibus-gtk module installed or do not set the im-switch to auto.
  • Japanese/Chinese/Korean/etc input work in GTK (Firefox, Chrome, Skype) apps but no in KDE apps!
  • This happens if you do not have the ibus-qt4 module installed or do not set the im-switch to auto.

Resources

[1] http://www.scim-im.org scim/skim
[2] http://code.google.com/p/ibus

Sunday, March 21, 2010

Get offlineimap working with non ASCII characters.

Introduction

I recently started using offlineimap [1] to manage my GMail accounts locally on my machine.

With offlineimap all my email is local so the navigation is very fast and also I am a little more relieved that I have a local copy of all my email.

The only problem is that offlineimap does not work well with non english characters. This makes it difficult to use for those with labels in Russian, Chinese, Japanese etc [2].

Fortunately offlineimap offers some nice options that allows us to modify it's behavior. Using the "pythonfile" and "nametrans" options I was able to get Japanese working flawlessly.

Problem Description


IMAP4 uses a modified UTF-7 coding for all folder names but offlineimap does not convert the folder names to UTF-8 or something readable before creating local repositories that results in very cryptic folder names like "&MMYwuTDI-".

Some research (googling) on the topic resulted in a very nice code to add IMAP4 UTF-7 encoding capabilities to Python [3]. So with a little time and some copy/paste skills I added this code to offlineimap and ban! I got Japanese working correctly in my folders.

Fixing unicode issues in offlineimap


First we must add the code to convert from IMAP4 UTF7 encoding support to offlineimap. Thanks to Dominic LoBue (offlineimap developer) I learned that we can add our own python code to offlineimap. To do this we created a simple python script (e.g. ~/.utf7.py) that contains the following code (copy/paste from [3]:



Then in our offlineimap configuration file, in the "[general]" section we add a line to load this python script like:



Finally in our remote repository configuration add a nametrans option to convert all foldernames from "imap4-utf-7" encoding to your encoding of preference. My Ubuntu installation is all UTF-8 so I convert all folder names to this encoding:



The "imap4-utf-7" encoding is added by our "utf7.py" script. With this configuration I can now see the correct Japanese names for all the folders (labels) in my GMail accounts inside Mutt [4].

Resources


[1] http://software.complete.org/software/wiki/offlineimap
[2] http://software.complete.org/software/issues/show/102
[3] IMAP4 UTF-7 Encoding/Decoding
[4] Best email client

Tuesday, January 26, 2010

Google Contacts in Mutt

Introduction



For some time now I have managing all my contact information (a.k.a address book) in GMail because this allows me for easy synchronization of contacts with my cell phone that is a Google Phone HTC Hero.

What I was missing was the ability to query the GMail contacts from within my favorite email client: Mutt and the solutions I found in Google were not working for me.

The first solution I found [1] was to export all my GMail contacts to vcards and then import these to abook [2] that is an address book compatible with Mutt. Not really a solution should I say.

The second solution [3] I found is actually pretty good. Is a small python script that can be used within mutt using the "query_command" [4] and actually queries GMail contacts web service API. Also supports caching so you do not need to connect every time to GMail service speeding up the query time.

Unfortunately this solution did not work very well for me. Some contacts would not be auto completed when composing an email and some other would not even appear. For example contacts with non ASCII characters (e.g. Japanese Kanji) would never get autocompleted, even thought they appeared when listing all contacts.

So after some time I implemented my own solution, in Ruby, that works perfectly for me and also has some additional features for groups and mailing lists.

Query GMail Contacts within Mutt



Using the gdata gem [5] and some knowledge of the Google contacts web API [6] it was relatively easy to implement a Ruby script that could be used with Mutt to query my contacts directly from GMail:


#!/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="user"
PASSWORD="secret"

# 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


Simply copy the above script somewhere in your machine (e.g. ~/.mutt/contactos.rb) and change the USERNAME and PASSWORD variables. Give the script execution property and some secure permissions:

chmod 700 ~/.mutt/contactos.rb

You may also change the MAXRESULTS, UPDATE_INTERVAL and CACHEFILE variables to fit your needs. Just make sure MAXRESULTS is larger than the total number of contacts you have and that you have write access to the CACHEFILE you set. If you set UPDATE_INTERVAL to zero then the scripts queries GMail directly every time that can be slow depending on you network connection.

Also make sure you have installed Ruby and the gdata gem. In Ubuntu/Kubuntu this can be accomplished with the following commands:


sudo aptitude install ruby1.8 rubygems-1.8 libopenssl-ruby1.8
sudo gem1.8 install gdata

Finally configure Mutt to use this script to query contacts when you are filling the To: and From: headers of emails. To do this add these commands in your muttrc file:

set query_command ="~/mutt/contactos.rb --mutt %s"
set query_format="%4c %t %-40.40a %-40.40n %?e?(%e)?"
bind editor complete-query
bind editor ^T complete

After this you can press to autocomplete contacts using you GMail contact list and all without leaving the comfort of Mutt.

Integrating GMail contact groups within Mutt


After finishing my contacts script I realized that I could make even more things thanks to the rich Google contacts API and the scripting power and simplicity of ruby.

To integrate Mutt with you Google contact groups simply add this to your muttrc file:
source '~/.mutt/contactos.rb --groups|'
This command generates a list of "group" commands that map all GMail contact groups with Mut groups. Once this command is inserted in your muttrc file you may search, tag, delete and create hooks based on your GMail groups and manage the groups within GMail itself.

Managing Mutt mailing lists within GMail


One anoying thing about Mutt mailing lists is that you have to add a subscribe command for each mailing list you read in order to get all the features Mutt offers to handle mailing lists.

With my script you can create a special group for mailing lists (e.g. Mailing Lists) and add all the addresses of all mailing lists you are subscribed into that group. Then you can add this command to your muttrc file:

source './~mutt/contactos.rb --subscribes|'

and magically you get all the subscribe commands automagically generated for you from you GMail contacts. If you prefer to use a different name for you mailing list group you have to change the MAILISTGROUP variable in the ruby script to match the name you have in you GMail contacts.

Resources


Sunday, January 03, 2010

Brother DCP-595CN Printer In Ubuntu/Kubuntu



This little machine is a printer, scanner and copy machine all in one. It has USB and ethernet ports but even better a wireless 802.11a/b/g port. This means I can have the printer anywhere in the house and print from my desktop or lapton freely. In Japan it costs around ¥15,000 (USD 150) that is pretty cheap for all the features packaged in.

And the most important thing for me is that is 100% compatible with linux (Kubuntu). Here I will show the steps to get this little beast working with my Kubuntu machine.

Prerequisites



I use the wireless interface to connect to the printer/scanner so before you follow these instructions make sure the printer has an IP configured. The wireless configuration is done using the printer control panel and is already covered in the printer manual so I will skip it.

You may ping the printer IP address to check that you can reach it from your computer. If you cannot ping it then it is not well configured or you have problems with your LAN network.

Installation



These instructions are based on the Brother solution page instructions.

First we need to download both the LPR driver and the CUPS wrapper driver by going to the following URLs. Inside you will find RPM and DEB packages for the different printer models.

If you have the same printer as me (DCP-595CN) then look for the DEB packages of this printer and click the link. You will be directed to a GPL license page where you must agree to the GPL terms (Left Button) after which the download will start.

Once the DEB packages are downloaded we install them using the following commands:

sudo mkdir /usr/share/cups/model
sudo mkdir /var/spool/lpd
sudo mkdir -p /usr/lib/cups/filter
sudo dpkg -i dcp595cnlpr-1.1.2-1.i386.deb
sudo dpkg -i dcp595cncupswrapper-1.1.2-2.i386.deb
note that there are only packages for i386 architectures but if you see the Q&A link they explain how to install on amd64 architectures. All you have to do is add the --force-arquitecture switch to the dpkg command like:
sudo dpkg --force-arquitecture -i dcp595cnlpr-1.1.2-1.i386.deb
sudo dpkg --force-arquitecture -i dcp595cncupswrapper-1.1.2-2.i386.deb

Now with the drivers installed we can use the CUPS administration page to add the printer. To do this we open our favorite Internet browser and access the following URL: http://localhost:631.

Enter the printer administration tab and add a new printer. If your printer is already configured with an IP address in your LAN it should appear in the list of detected printers (see screenshot below):



Select the printer and in the next window you will be asked to add some details about the printer like the place, description and name. You may add anything you like or leave the defaults and go to the next screen.

In the next screen (see screenshot below) we select the printer driver to use. If you installed the DEB packages correctly then the correct driver should be selected here by default:



Simply press the "add printer" button to finish. Now your printer should be ready for printing. Go ahead the print something.

Brother DCP-595CN Scanner In Ubuntu/Kubuntu



Getting the scanner working in Kubuntu is even easier. First we need to download the SANE driver from Brothers home page. Which driver to download depends on the scanner model you have. In my case (DCP-595CN) I need the brscan3 driver. There are 32 and 64bit versions and RPM and DEB packages. For my configuration I need the brscan3 32bit DEB pacakge. Download the package for your configuration and install it using this command:

sudo aptitude install xsane sane-utils brscan3-0.2.8-1.i386.deb

In the command above I am installing some SANE packages and the brscan3 driver. Next we need to configure the scanner with the following command:

sudo brsaneconfig3 -a name=DCP-595CN model=DCP-595CN ip=192.168.11.4

Depending on the driver you installed the configuration command changes. For brscan3 we use the "brsaneconfig3" command. The name can be anything you want as long as it has no white spaces but the model and the ip must be set to the correct values. The ip of course is the IP address the printer has configured and the model is the model name of the printer. If you are not sure about the model or IP you can use the following command to query the network:

sudo brsaneconfig3 -q

This command gives a list of supported models and at the end a list of detected scanners. In my configuration at the end I get:

Devices on network
0 DCP-595CN           "DCP-595CN"         I:192.168.11.4


If you do not see this list then your machine is not able to reach the scanner on the IP level so make sure it has the IP address configured and that you can ping it.

After you have configured the scanner with the brscanconfig3 tool you are ready to scan. To test it you can run xsane and the scanner should be listed like in the screenshot below:



Select the scanner and scan something. Now you have a fully functional printer, scanner and copy machine in you Kubuntu installation.