# -*- coding: utf-8 -*- import os from postman import config from postman.models import Member, MailingList from postman.storage import JsonStorage as Storage class Postman(): def __init__(self, configfile=None): if not configfile: # FIXME: This is not used right now, we are getting the stuff # from postman.config, but we will move configurations to a # external ini-style config file soon configfile = os.path.join(os.path.dirname(__file__), '../conf/postman.conf') self.configfile = configfile # lists were the currently managed mailing lists information is going # to be saved self.mailings = {} self.mailings_addresses = [] # the files were internal information (like active mailing lists, # members, etc) is saved self.dbs = {'mailings': Storage(os.path.join(config.storage_path, 'mailings.json')), 'members': Storage(os.path.join(config.storage_path, 'members.json'))} def save(self): """ Save all the current managed data to disk """ if self.mailings: # Save the config file from where we can reload information about the # mailing lists managed by this postman instance self.dbs['mailings'].write(self.mailings_addresses) # Save each mailing list data into its separated persistence file for m in self.mailings.keys(): self.mailings[m].save() return True return False def load(self): """ Load all data from the storage files """ if self.dbs['mailings'].exists(): # load the list of managed mailing lists # FIXME: This is quite naive, we do not perform any check here after # loading the data from the json file, which can be modified by # untrustred users. self.mailings_addresses = self.dbs['mailings'].read() # now load all the mailing objects: for address in self.mailings_addresses: mailing = MailingList(address, address) mailing.load() self.mailings[address] = mailing return True return False def clear(self): """ Delete all stored data from disk (useful for testing). DANGER: Calling this method will remove all data from disk, leaving the postman instance with no persistence data, if the postman process die, before another .save() call is made, all data will be lost. """ if self.dbs['mailings'].exists(): # We do not delete each mailing list file, but only the file # containing the list of existing mailing lists self.dbs['mailings'].delete() return True return False def add_mailing_list(self, info={}): """ Add a new mailing list to this postman instance. expects one parameter, info, which is a dictionary that should contain, at least, the following keys: - name: (string) the name we will give to the list - address: (string) the email address of the list - members: (list) a list of email adddress of the list members """ if not isinstance(info, dict): raise TypeError(info, ' is not a valid dictionary') if 'name' not in info.keys() or \ 'address' not in info.keys() or \ 'members' not in info.keys() or \ 'config' not in info.keys(): raise ValueError(info, ' does not seem to be a valid configuration') if info['address'] in self.mailings_addresses: raise IndexError(info['address'], ' has been already added to postman') mailing = MailingList(info['name'], info['address'], info['members'], info['config']) self.mailings[mailing.address] = mailing self.mailings_addresses.append(mailing.address) # After adding new mailings, save them to disk self.save() return True def add_mailing_member(self, member_addr=None, list_addr=None): """ Add a new member for the mailing list represented by list_addr (a string containing the email address of any mailing list managed by this postman instance). member_addr is a string representing the email address of the new member """ if not member_addr: raise ValueError(member_addr, 'missing member address') if not list_addr: raise ValueError(list_addr, 'missing list address') if list_addr not in self.mailings_addresses: # FIXME: Perhaps we should add it, perhaps not (mispelled address?) raise IndexError(list_addr, ' is not a valid mailing list') added = self.mailings[list_addr].add_member_by_address(member_addr) if added: self.save() return added