def __call__(self):
        # TODO: make sure this works...

        regcancelhash = self.request.get('h')
        # if a match is found, then move it to the confirm state and
        # set a flag for the template to show a 'confirmed' message
        for reg in self.context.registrations:
            reghash = generateRegistrationHash(
                        'cancel',
                        self.context.registrations[reg])
            if reghash == regcancelhash:
                self.confirmed = True
                wf = getToolByName(self.context, 'portal_workflow')
                curstatus = wf.getStatusOf(
                              'collective.eventmanager.Registration_workflow',
                              self.context.registrations[reg])
                # only confirm a registration if it has been approved
                if curstatus is not None \
                        and curstatus['review_state'] != 'cancelled' \
                        and curstatus['review_state'] != 'denied':
                    wf.doActionFor(self.context.registrations[reg], 'cancel')

                break

        return super(CancelRegistrationView, self).__call__()
    def test_registrants_can_cancel(self):
        # setup event
        browserLogin(self.portal, self.browser)
        self.browser.open(self.portal_url + \
            '/++add++collective.eventmanager.EMEvent')
        self.browser.getControl('Event Name').value = 'Test Event'
        self.browser.getControl('Description/Notes').value = 'Event desc'
        self.browser.getControl(
                name='form.widgets.thankYouIncludeConfirmation:list'
            ).value = 'on'
        self.browser.getControl('Save').click()
        event = self.getLastEvent('test-event')

        # add registration
        self.registerNewUser(
                event,
                "Test Registration Cancel",
                "*****@*****.**")

        # send confirmation email
        self.browser.open("%s/%s/@@emailsenderform"
                                % (self.portal_url, event.getId()))
        self.browser.getControl(name='emailfromaddress').value = '*****@*****.**'
        self.browser.getControl(name='emailtoaddresses') \
                    .value = "*****@*****.**"
        self.browser.getControl(name='submit').click()

        # get cancellation link from email
        mailhost = self.portal.MailHost
        assert len(mailhost.messages) == 1
        msg = message_from_string(mailhost.messages[0])
        assert '*****@*****.**' in msg['To']
        cancelurl = "%s/%s/cancel-registration?h=%s" \
                        % (self.portal_url,
                           event.getId(),
                           generateRegistrationHash(
                                "cancel",
                                event.registrations['test-registration-cancel']
                                ))
        assert cancelurl in mailhost.messages[0]

        # go to cancellation link
        self.browser.open(cancelurl)
        assert "Registration Cancelled" in self.browser.contents

        # assert state of registration is cancelled
        wf = getToolByName(self.portal, "portal_workflow")
        regstatus = wf.getStatusOf(
            'collective.eventmanager.Registration_workflow',
            event.registrations['test-registration-cancel'])
        assert regstatus['review_state'] == 'cancelled'
def sendEMail(emevent, emailtype, mto=[], reg=None, defattachments=[],
              deffrom=None, defsubject=None, defmsg=None):

    mtemplate = ''
    mfrom = deffrom
    msubject = defsubject
    mbody = defmsg
    additional_html_body = None
    additional_plain_body = None
    mattachments = defattachments

    mh = getToolByName(emevent, 'MailHost')
    registry = getUtility(IRegistry)

    # get data configured for this specific event
    if emailtype == 'thank you':
        mtemplate = 'thankyou'
        mfrom = emevent.thankYouEMailFrom
        msubject = emevent.thankYouEMailSubject
        mbody = emevent.thankYouEMailBody

    elif emailtype == 'on waiting list':
        mtemplate = 'onwaitinglist'
        mfrom = emevent.waitingListEMailFrom
        msubject = emevent.waitingListEMailSubject
        mbody = emevent.waitingListEMailBody

    elif emailtype == 'registration full':
        mtemplate = 'registrationfull'
        mfrom = emevent.registrationFullEMailFrom
        msubject = emevent.registrationFullEMailSubject
        mbody = emevent.registrationFullEMailBody

    elif emailtype == 'confirmation':
        mtemplate = 'confirmation'
        if emevent.thankYouIncludeConfirmation and reg is not None:
            # only include a confirmation link where a registration has
            #   been approved.
            confirmtext = ''
            confirmhtml = ''
            portal = getSite()
            wf = getToolByName(portal, 'portal_workflow')
            regstatus = wf.getStatusOf(
                'collective.eventmanager.Registration_workflow',
                reg)
            if regstatus is not None \
                    and regstatus['review_state'] == 'approved':
                confirmreghash = generateRegistrationHash('confirmation', reg)
                confirmtext = """
Please visit the following URL in order to confirm your registration:

%s/confirm-registration?h=%s


""" % (emevent.absolute_url(), confirmreghash)
                confirmhtml = '<br />Please ' \
                '<a href="%s/confirm-registration?h=%s">confirm your ' \
                'registration</a>.</div><br /><br />' \
                % (emevent.absolute_url(), confirmreghash)

            # put together the final messages
            cancelreghash = generateRegistrationHash('cancel', reg)
            additional_plain_body = """
=======================%s
If you'd like to cancel your registration, please visit the following URL:

%s/cancel-registration?h=%s""" % (confirmtext,
                                  emevent.absolute_url(), cancelreghash)
            additional_html_body = \
                '<div>=======================%s<div>' \
                'You may <a href="%s/cancel-registration?h=%s">cancel your ' \
                'registration</a> at any time.</div>' \
                % (confirmhtml,
                   emevent.absolute_url(), cancelreghash)

    elif emailtype == 'announcement':
        mtemplate = 'announcement'

    elif emailtype == 'other':
        mtemplate = 'other'

    if mfrom == None or mfrom == '':
        return False

    # get the keys for each of the registry entries that define the
    # email templates
    registrykey = "collective.eventmanager.emailtemplates" \
                  ".IEMailTemplateSettings.%s_%s"
    tsubkey = registrykey % (mtemplate, 'subject')
    thtmlkey = registrykey % (mtemplate, 'htmlbody')
    tplainkey = registrykey % (mtemplate, 'textbody')

    # get the site wide templates
    tsub = registry.records[tsubkey].value
    thtml = registry.records[thtmlkey].value
    tplain = registry.records[tplainkey].value

    subtemplate = Template(tsub)
    htmltemplate = Template(thtml)
    plaintemplate = Template(tplain)

    messagetemplate = Template(mbody)

    # apply results of event template render to site wide templates
    messageresult = messagetemplate.render(emevent=emevent).decode('utf-8')
    messagehtml = htmltemplate.render(
        emevent=emevent,
        event_content=messageresult)
    messageplain = plaintemplate.render(
        emevent=emevent,
        event_content=messageresult)

    if additional_html_body is not None:
        messagehtml += additional_html_body
    if additional_plain_body is not None:
        messageplain += additional_plain_body

    subject = subtemplate.render(emevent=emevent, event_content=msubject)

    # create a multipart message to hold both a text and html version
    msg = MIMEMultipart('alternative')
    msg['Subject'] = subject.decode('utf-8')
    msg['From'] = mfrom.encode('ascii')
    msgpart1 = MIMEText(messageplain, 'plain', 'utf-8')
    msgpart2 = MIMEText(messagehtml, 'html', 'utf-8')
    msg.attach(msgpart1)
    msg.attach(msgpart2)

    # if there were any attachments, then add them to the message
    if mattachments != None and len(mattachments) > 0:
        for attachment in mattachments:
            apart = MIMEBase('application', 'octet-stream')
            apart.set_payload(attachment['data'])
            encoders.encode_base64(apart)
            apart.add_header('Content-Disposition', 'attachment',
                            filename=attachment['name'])
            msg.attach(apart)

    # send a separate message to each address
    for address in mto:
        msg['To'] = address.encode('ascii')
        mh.send(msg.as_string(), address, mfrom, subject)
        #mh.send(msg)

    #mh.send('message', '*****@*****.**', '*****@*****.**', 'subject')

    return True