# -*- coding: utf-8 -*- import json from httplib import HTTPConnection, HTTPException from urllib import urlencode class MailmanRESTClientError(Exception): """An exception thrown by the Mailman REST API client.""" pass class MailmanRESTClient(object): """A thin client wrapper for the Mailman REST API.""" def __init__(self, host): self.host = host if self.host[-1] == '/': self.host = self.host[:-1] # general header information self.headers = { "User-Agent": "MailmanRESTClient", "Accept": "text/plain", } try: self.c = HTTPConnection(self.host) except: raise MailmanRESTClientError('Could not connect to server') def __repr__(self): return '<MailmanRESTClient: %s>' % self.host def _get_url(self, path): try: self.c.request('GET', path, None, self.headers) except: raise MailmanRESTClientError('Error sending request') try: r = self.c.getresponse() raw_data = r.read() if len(raw_data) == 0: raise None data = json.loads(raw_data) except: raise MailmanRESTClientError('Error sending request') finally: self.c.close() return data def _post_url(self, path, data): self.headers['Content-type'] = "application/x-www-form-urlencoded" try: self.c.request('POST', path, urlencode(data), self.headers) except: raise MailmanRESTClientError('Could not send request') try: r = self.c.getresponse() if r.status == 201: return True else: return r.status finally: self.c.close() def _delete_url(self, path): try: self.c.request('DELETE', path, None, self.headers) except: raise MailmanRESTClientError('Could not send request') def _put_url(self, path): pass def get_lists(self): """Get a list of mail lists. returns a list of dicts """ try: r = self._get_url('/3.0/lists') except: raise MailmanRESTClientError('Could not send request') if 'entries' not in r: raise MailmanRESTClientError('No mailing lists found') return r['entries'] def read_list(self, list_name): """Get information about list. :param list_name: name of the list to get information about :type list_name: string :rtype: dict """ try: r = self._get_url('/3.0/lists/' + list_name) except: raise MailmanRESTClientError('Unable to get info about list') return r def create_list(self, fqdn_listname, **kwargs): """Create a new list. :param fqdn_listname: the name of the list including the @ and the domain name. eg. test@example.com :type fqdn_listname: string :rtype: None """ data = { 'fqdn_listname': fqdn_listname } data.update(**kwargs) try: return self._post_url('/3.0/lists', data) except MailmanRESTClientError, e: raise MailmanRESTClientError(e) def subscribe_list(self, fqdn_listname, address, real_name, **kwargs): """Add an address to a list. :param fqdn_listname: the name of the list . :type fqdn_listname: string :param address: email address to add to the list. :type address: string :param real_name: the "real" name for the address to be addded :type real_name: string """ data = { 'fqdn_listname': fqdn_listname, 'address': address, 'real_name': real_name } data.update(**kwargs) try: r = self._post_url('/3.0/members', data) except: raise MailmanRESTClientError('unable to join list') return r def leave_list(self, fqdn_listname, address): """Remove an address from a list. :param fqdn_listname: the name of the list. :type fqdn_listname: string :param address: email address that is leaving the list :type address: string :rtype: None """ try: r = self._delete_url('/3.0/lists/' + fqdn_listname + '/member/' + address ) except: raise MailmanRESTClientError('unable to leave list') return True def get_members(self, fqdn_listname = None): """Get a list of all members for all lists. :rtype: list of dicts :type fqdn_listname: string """ if fqdn_listname != None: url = '/3.0/lists/' + fqdn_listname + '/members' else: url = '/3.0/members' try: r = self._get_url(url) except: raise MailmanRESTClientError('Could not complete request') if 'entries' not in r: raise MailmanRESTClientError('Could not find any members') return r['entries'] def get_domains(self): """Get a list of domains. :rtype: list of dicts """ try: r = self._get_url('/3.0/domains') except: raise MailmanRESTClientError('Could not complete request') if 'entries' not in r: raise MailmanRESTClientError('Could not find any domains') return r['entries'] def read_domain(self, domain_name): """Get information about a specific domain. :param domain_name: the name of the domain. :rtype: dict """ try: r = self._get_url('/3.0/domains/' + domain_name) except: raise MailmanRESTClientError('Unable to read domain') return r def create_domain(self, email_host, **kwargs): """Create a new domain name. :param email_host: domain name to create :type email_host: string :rtype: None """ data = { 'email_host': email_host, } data.update(**kwargs) try: r = self._post_url('/3.0/domains', data) except: raise MailmanRESTClientError('Unable to create domain') return r