Add GnuTLS and secure LDAP information.
[mutt-ldap.git] / mutt-ldap.py
1 #!/usr/bin/env python
2 #
3 # Copyright (C) 2008-2011  W. Trevor King
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 """LDAP address searches for Mutt.
19
20 Add :file:`mutt-ldap.py` to your ``PATH`` and add the following line
21 to your :file:`.muttrc`::
22
23   set query_command = "mutt-ldap.py '%s'"
24
25 Search for addresses with `^t`, optionally after typing part of the
26 name.  Configure your connection by creating :file:`~/.mutt-ldap.py`
27 contaning something like::
28
29   [connection]
30   server = myserver.example.net
31   basedn = ou=people,dc=example,dc=net
32
33 See the `CONFIG` options for other available settings.
34 """
35
36 import email.utils
37 import itertools
38 import os.path
39 import ConfigParser
40
41 import ldap
42
43
44 CONFIG = ConfigParser.SafeConfigParser()
45 CONFIG.add_section('connection')
46 CONFIG.set('connection', 'server', 'domaincontroller.yourdomain.com')
47 CONFIG.set('connection', 'port', '389')  # set to 636 for default over SSL
48 CONFIG.set('connection', 'ssl', 'no')
49 CONFIG.set('connection', 'user', '')
50 CONFIG.set('connection', 'password', '')
51 CONFIG.set('connection', 'basedn', 'ou=x co.,dc=example,dc=net')
52 CONFIG.read(os.path.expanduser('~/.mutt-ldap.rc'))
53
54 def connect():
55     protocol = 'ldap'
56     if CONFIG.getboolean('connection', 'ssl'):
57         protocol = 'ldaps'
58     url = '%s://%s:%s' % (
59         protocol,
60         CONFIG.get('connection', 'server'),
61         CONFIG.get('connection', 'port'))
62     connection = ldap.initialize(url)
63     connection.bind(
64         CONFIG.get('connection', 'user'),
65         CONFIG.get('connection', 'password'),
66         ldap.AUTH_SIMPLE)
67     return connection
68
69 def search(query, connection=None):
70     local_connection = False
71     try:
72         if not connection:
73             local_connection = True
74             connection = connect()
75         post = ''
76         if query:
77             post = '*'
78         filterstr = '(|%s)' % (
79             u' '.join([u'(%s=*%s%s)' % (field, query, post)
80                        for field in ['cn', 'rdn', 'uid', 'mail']]))
81         r = connection.search_s(
82             CONFIG.get('connection', 'basedn'),
83             ldap.SCOPE_SUBTREE,
84             filterstr.encode('utf-8'))
85     finally:
86         if local_connection and connection:
87             connection.unbind()
88     return r
89
90 def format_entry(entry):
91     cn,data = entry
92     if 'mail' in data:
93         for m in data['mail']:
94             yield email.utils.formataddr((data['cn'][-1], m))
95
96
97 if __name__ == '__main__':
98     import sys
99
100     query = unicode(' '.join(sys.argv[1:]), 'utf-8')
101     entries = search(query)
102     addresses = list(itertools.chain(
103             *[format_entry(e) for e in sorted(entries)]))
104     print '%d addresses found:' % len(addresses)
105     print '\n'.join(addresses)