def __init__(self, 
            id, 
            title='',
            description='',
            topics='',
            mailFrom='',
            nameFrom='',
            disclaimer='',
            signature='',
            ):

        """ Initialize an instance of the class """		
        ## parents constructors 
        DefaultDublinCoreImpl.__init__(self, title, description = description)
        self.id = id
        self.topics = string.split(topics,'\n')
        self.disclaimer = disclaimer		
        self.mailer = Mailer(None, mailFrom, nameFrom, signature)
        self.spool = Spool()
        self.users = {}
class Newsletter(PortalFolder,
        PortalContent,
        DefaultDublinCoreImpl,
        ):
	
    """ Plone NewsLetter Class """

    meta_type = 'Newsletter'
    portal_type = 'PloneNewsLetter'

    security = ClassSecurityInfo()
    security.declareObjectPublic()

    manage_options = PortalContent.manage_options
    meta_type = factory_type_information['meta_type'] 

    __implements__ = ( PortalContent.__implements__
                     , DefaultDublinCoreImpl.__implements__
                     )


    ## subscribe and ubsubscribe expressions
    SUB = 'Subscription'
    UNSUB = 'Unsubscription'
    MOD = 'Modify'

    def __init__(self, 
            id, 
            title='',
            description='',
            topics='',
            mailFrom='',
            nameFrom='',
            disclaimer='',
            signature='',
            ):

        """ Initialize an instance of the class """		
        ## parents constructors 
        DefaultDublinCoreImpl.__init__(self, title, description = description)
        self.id = id
        self.topics = string.split(topics,'\n')
        self.disclaimer = disclaimer		
        self.mailer = Mailer(None, mailFrom, nameFrom, signature)
        self.spool = Spool()
        self.users = {}

    def edit(self,
        title,
        description='',
        topics='',
        mailFrom='',
        nameFrom='',
        disclaimer='',
        signature='',
        ):

        """ Edit Newsletter Properties """
        self.editMetadata(title = title, description = description)
        self.topics = string.split(topics,'\n')
        self.disclaimer = disclaimer
        self.mailer.edit(mailFrom, nameFrom, signature)
        ## edit mailhost aswe can't do it in  __init__()
        if self.mailer.mailhost is None:
            self.mailer.mailhost = self.getMailHost()

    security.declarePrivate('manage_afterAdd')
    def manage_afterAdd(self, item, container):
         """ Add self to the workflow and catalog. """
         PortalFolder.manage_afterAdd(self, item, container)
         PortalContent.manage_afterAdd(self, item, container)

    security.declarePrivate('manage_beforeDelete')
    def manage_beforeDelete(self, item, container):
        """ Remove self from the workflow and catalog. """
    	if aq_base(container) is not aq_base(self):
            self.unindexObject()
        PortalFolder.manage_beforeDelete(self, item, container)

#    security.declareProtected(CMFCorePermissions.View, 'view')
#    def view(self, REQUEST):
#        """ List the contents og the newsletter """
#        return self.newsletter_view(self, REQUEST)

    security.declareProtected(CMFCorePermissions.AddPortalContent, 'invokeFactory')
    def invokeFactory( self
            , type_name
            , id
            , RESPONSE=None
            , *args
            , **kw
            ):

        """ Invokes the portal_types tool. """		
        pt = getToolByName( self, 'portal_types' )
        apply( pt.constructContent
            , (type_name, self, id, RESPONSE) + args
            , kw
        )

    def mailerAttr(self, attribute=None) :        
        """ Returns an attribute of mailer, as can't call mailer.attr in ZPT """ 
        return eval('self.mailer.%s' %attribute)

######################################
## User subscription/unsubscription ##
######################################

    def subscribe(
        self,
        firstName='',
        lastName='',
        email='',
        format='',
        ):

        """ User subscription """        
        if email in self.users.keys():
            return 0
        else:
            user = User(firstName, lastName, email, format)
            id = self.spool.addSubscription(user)
            self.confirmSubscription(user, id)
            return 1
        
    def unsubscribe(
        self,
        email='',
        ):
        
        """ User unsubscription """ 
        if email not in self.users.keys():
            return 0
        else:
            user = self.users[email]
            id = self.spool.addUnsubscription(user)
            self.confirmUnsubscription(user, id)
            return 1

    def deluser(self, id):
        """ Delete a user by email """
        if self.users.has_key(id):
            del self.users[id]
            self._p_changed = 1

    def adduser(self, REQUEST):
        """ Add a user """
        user = User(REQUEST['firstName'], REQUEST['lastName'], REQUEST['email'], REQUEST['format'])
        self.users[REQUEST['email']] = user
        self._p_changed = 1

    def moduserformat(self, email, format):
        """ Modify the format for a user """
        if self.users.has_key(email) and format != self.users[email].format:
            self.users[email].format = format
            self._p_changed = 1
	
    def listusers(self):
    	""" List users """
    	result = []
    	for user in self.users.values():
    	    l = [user.name[0], user.name[1], user.email, user.format]
    	    result.append(l)
    	return result

    def getallusers(self):
        """ List self users plus portal users """
        res = {}
        users = self.users
        for member in users.keys():
           res[member] = users[member]
        for member in self.portal_membership.listMembers():
           if member.newsletter:
                user = User(member.fullname, '', member.email, member.newsletter)
                res[member.email] = user
        return res                

#############################
## E-mail posting function ##
#############################

    def sendAll(self, publi, subject, message_txt, message_html):
        """ Send the newsletter to all subscribed members """
        self.mailer.sendAll(publi, self.getallusers(), self.addTitle(subject), message_txt, message_html)

    def sendValidate(self, subject, publication_url):
        """ Send email to reviewers when publication submited """
        roles = self.get_local_roles()
        to=[]
        for r in roles:
            if 'Owner' or 'Manager' or 'Reviewer' in r[1] :
                # Got error if user not defined on CMF acl_users (returns None object)
                try :
                    e = self.portal_membership.getMemberById(r[0]).getProperty('email')
                    to += [e]
                except: pass
        self.mailer.sendValidate(to, subject, publication_url)
              
##########################################
## E-mail (parsing + sending) functions ##
##########################################

    def parseMailSubject(self, mfrom, to, subject):
        """ Parse e-mail subject and eventually send to spool. """
        tokens = string.split(subject)
        ## case 1: mail to confirm unsubscription
        if self.UNSUB in tokens and 'id:' in tokens :
            email = self.spool.checkUnsubscription(subject)
            if email is not None:
                self.unsubscriptionDone(self.users[email])
        ## case 1b: mail to request an unsubscription
        elif self.UNSUB in tokens and 'mail:' in tokens :
            m = re.match(".*mail: ([^ ]*).*", subject)
            if m:
                email = m.group(1)
                self.unsubscribe(email)
            
        ## case 2: mail to confirm subscription 
        elif self.SUB in tokens and 'id:' in tokens :
            user = self.spool.checkSubscription(subject)
            if user is not None:
                self.subscriptionDone(user)
        ## case 3: mail format modification
        elif self.MOD in tokens and 'mail:' in tokens and 'format:' in tokens :
            m = re.match(".*mail: ([^ ]*).*format: ([0-9]).*", subject)
            if m:
                email = m.group(1)
                format = int(m.group(2))
		self.moduserformat(email, format)
		self.welcome(self.users[email])

    def confirmSubscription(self, user, id):
        """ Send e-mail to request user subscription confirmation """
        message = """
You have requested subscription to "%s".
Please confirm your subscription by replying to this mail (keep entire subject)

Thank you for your attention.
""" %self.title
        if hasattr(self, 'subscription_message'):
            message = self.subscription_message
        subject = self.formatConfirmSubject(self.SUB, user, id)
        self.mailer.mailSubscribe(user, subject, message)

    def confirmUnsubscription(self, user, id):
        """ Send e-mail to request user unsubscription confirmation """
        message = """
You have requested unsubscription from "%s".
Please confirm your unsubscription by replying to this mail (keep entire subject)

Thank you for your attention.
""" %self.title
        if hasattr(self, 'unsubscription_message'):
            message = self.unsubscription_message
        subject = self.formatConfirmSubject(self.UNSUB, user, id)
        self.mailer.mailUnsubscribe(user, subject, message)

    def welcome(self, user):
        """ send a welcome message to the newly subscribed user """
        if hasattr(self, 'welcome_release') and hasattr(self, self.welcome_release):
            release = self[self.welcome_release]
            [html, text] = release.getBodies()
            subject = self.addTitle(release.title_or_id())
            self.mailer.mailTo(user, subject, user.format and html or text)

    def subscriptionDone(self, user):
        """ Send e-mail to confirm user subscription """
        message = """
You have been added to "%s".

Thank you for your attention.
""" %self.title
        if hasattr(self, 'confirmation_message'):
            message = self.confirmation_message
        subject = self.formatDoneSubject(self.SUB, user)
        self.mailer.mailSubscribe(user, subject, message)
	self.users[user.email] = user
	self._p_changed = 1
        # Send the welcome release if set
        self.welcome(user)

    def unsubscriptionDone(self, user):
        """ Send e-mail to confirm user unsubscription """
        message = """
You have been removed from "%s".

Thank you for your attention.
""" %self.title
        if hasattr(self, 'rconfirmation_message'):
            message = self.rconfirmation_message
        subject = self.formatDoneSubject(self.UNSUB, user)
        self.mailer.mailUnsubscribe(user, subject, message)
	del self.users[user.email]
	self._p_changed = 1

    def formatConfirmSubject(self, type, user, id):
        """ Returns formated subject to confirm (un)subscription """
        return self.addTitle("""Confirm %s - user: %s - id: %s""" %(type, user.email, id))

    def formatDoneSubject(self, type, user):
        """ Returns formated subject when (un)subscription done """
        return self.addTitle("""%s Done - user: %s""" %(type, user.email))


######################
## Internal Methods ##
######################

    def addTitle(self, subject):
        """ add newsletter title to subject """
        return """[%s] %s""" %(self.title, subject)
        
    def getMailHost(self):
        """ returns mailhost instance """
        root = getToolByName(self, 'portal_url').getPortalObject()
        return getattr(root, 'MailHost')