Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py	(revision 12552)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py	(revision 12553)
@@ -110,4 +110,8 @@
 
     @property
+    def title(self):
+        return self.display_fullname
+
+    @property
     def fullname(self):
         firstname = getattr(self, 'firstname', None)
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12552)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12553)
@@ -78,4 +78,5 @@
     fullname = Attribute('All name parts separated by hyphens')
     display_fullname = Attribute('The fullname of an applicant')
+    title = Attribute('A title used for email notifications only')
 
     suspended = schema.Bool(
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12552)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12553)
@@ -21,4 +21,5 @@
 import shutil
 import tempfile
+import logging
 import pytz
 import base64
@@ -301,4 +302,28 @@
     # Tests for Customer class views and pages
 
+
+    def setup_logging(self):
+        # setup a log-handler that catches all fake mailer output
+        self.stream = StringIO()
+        handler = logging.StreamHandler(self.stream)
+        logger = logging.getLogger('test.smtp')
+        logger.addHandler(handler)
+        logger.setLevel(logging.INFO)
+        return
+
+    def get_fake_smtp_output(self):
+        # get output generated by fake mailer
+        self.stream.flush()
+        self.stream.seek(0)
+        return self.stream.read()
+
+    def teardown_logging(self):
+        # remove the log handler for fake mailer output
+        logger = logging.getLogger('test.smtp')
+        handlers = [x for x in logger.handlers]
+        for handler in handlers:
+            logger.removeHandler(handler)
+        return
+
     def test_basic_auth(self):
         self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
@@ -386,6 +411,9 @@
 
 
-    def test_manage_workflow(self):
+    def test_manage_workflow_send_transition_information(self):
         # Managers can pass through the whole workflow
+        config = grok.getSite()['configuration']
+        config.email_notification = True
+        self.setup_logging()
         self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
         customer = self.app['customers'][self.customer_id]
@@ -399,4 +427,32 @@
         self.browser.getControl(name="transition").value = ['reject']
         self.browser.getControl("Apply").click()
+        # The customer is being notified by email after rejection
+        expected = [
+            u'Sending email from no-reply@waeup.org to aa@aa.ng:',
+            u'Message:', u'msg: MIME-Version: 1.0',
+            u'msg: Content-Type: text/plain; charset="us-ascii"',
+            u'msg: Content-Transfer-Encoding: 7bit',
+            u'msg: From: Administrator <no-reply@waeup.org>',
+            u'msg: To: Anna Tester <aa@aa.ng>',
+            u'msg: Reply-To: Administrator <contact@waeup.org>',
+            u'msg: Subject: Ikoba status change information',
+            u'msg: ',
+            u'msg: Dear Anna Tester,',
+            u'msg: ',
+            u'msg: The status of the following object has been changed:',
+            u'msg: ', u'msg: Object Id: K1000000',
+            u'msg: Title: Anna Tester',
+            u'msg: Transition: customer registration rejected',
+            u'msg: New state: started',
+            u'msg: ',
+            u'msg: Regards,',
+            u'msg: ',
+            u'msg: Manager',
+            u'msg: ',
+            u'msg: --',
+            u'msg: Sample Company',
+            u'msg: ',
+            u'']
+        self.assertEqual(expected, self.get_fake_smtp_output().split('\n'))
         self.browser.open(self.trigtrans_path)
         self.browser.getControl(name="transition").value = ['request']
@@ -411,4 +467,5 @@
         self.browser.getControl(name="transition").value = ['reset1']
         self.browser.getControl("Apply").click()
+        self.teardown_logging()
         return
 
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py	(revision 12552)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py	(revision 12553)
@@ -21,9 +21,10 @@
 from datetime import datetime
 from zope.component import getUtility
+from zope.i18n import translate
 from hurry.workflow.workflow import Transition, WorkflowState, NullCondition
 from hurry.workflow.interfaces import (
     IWorkflowState, IWorkflowTransitionEvent, InvalidTransitionError)
 from waeup.ikoba.interfaces import (
-    IObjectHistory, IIkobaWorkflowInfo, IIkobaUtils,
+    IObjectHistory, IIkobaWorkflowInfo, IIkobaUtils, IUserAccount,
     STARTED, CREATED, REQUESTED, PROVISIONALLY, APPROVED,
     SUBMITTED, VERIFIED, REJECTED, EXPIRED)
@@ -159,4 +160,6 @@
 def handle_customer_transition_event(obj, event):
     """Append message to customer history and log file when transition happened.
+
+    Notify customer by email.
     """
 
@@ -164,4 +167,7 @@
     history = IObjectHistory(obj)
     history.addMessage(msg)
+    if event.transition.transition_id not in ('create', 'start', 'request'):
+        ikoba_utils = getUtility(IIkobaUtils)
+        ikoba_utils.sendTransitionInfo(IUserAccount(obj), obj, msg)
     try:
         customers_container = grok.getSite()['customers']
@@ -280,4 +286,8 @@
     history = IObjectHistory(obj)
     history.addMessage(msg)
+    if event.transition.transition_id not in ('create', 'submit') \
+        and obj.customer:
+        ikoba_utils = getUtility(IIkobaUtils)
+        ikoba_utils.sendTransitionInfo(IUserAccount(obj.customer), obj, msg)
     try:
         customers_container = grok.getSite()['customers']
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py	(revision 12552)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py	(revision 12553)
@@ -611,4 +611,9 @@
         )
 
+    email_notification = schema.Bool(
+        title = _(u'Notify customers by email'),
+        default = False,
+        )
+
     captcha = schema.Choice(
         title = _(u'Captcha used for public registration pages'),
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/utils/utils.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/utils/utils.py	(revision 12552)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/utils/utils.py	(revision 12553)
@@ -27,5 +27,6 @@
 from waeup.ikoba.interfaces import MessageFactory as _
 from waeup.ikoba.smtp import send_mail as send_mail_internally
-from waeup.ikoba.utils.helpers import get_sorted_preferred
+from waeup.ikoba.utils.helpers import (
+    get_sorted_preferred, get_current_principal)
 from waeup.ikoba.payments.currencies import ISO_4217_CURRENCIES
 
@@ -241,10 +242,66 @@
             subject, body, config)
 
-    def getPaymentItem(self, payment):
-        """Return payment item.
-
-        This method can be used to customize the display_item property method.
-        """
-        return payment.p_item
+    def sendTransitionInfo(self, customer, obj, msg=None):
+        """Send transition information as email.
+
+        Input is the customer for which credentials are sent and the object
+        which was transitioned.
+
+        Returns True or False to indicate successful operation.
+        """
+        config = grok.getSite()['configuration']
+        if not config.email_notification:
+            return
+        subject = 'Ikoba status change information'
+        text = _(u"""Dear ${a},
+
+The status of the following object has been changed:
+
+Object Id: ${c}
+Title: ${d}
+Transition: ${e}
+New state: ${f}
+
+Regards,
+
+${b}
+
+--
+${g}
+""")
+        from_name = config.name_admin
+        from_addr = config.email_admin
+        rcpt_name = customer.title
+        rcpt_addr = customer.email
+
+        user = get_current_principal()
+        if user is None:
+            usertitle = 'system'
+        elif user.id == 'zope.anybody':
+            usertitle = 'Anonymous'
+        else:
+            usertitle = getattr(user, 'public_name', None)
+            if not usertitle:
+                usertitle = user.title
+
+        msg = translate(msg,'waeup.ikoba', target_language=self.PORTAL_LANGUAGE)
+        new_state = translate(obj.translated_state,'waeup.ikoba',
+            target_language=self.PORTAL_LANGUAGE)
+
+        text = _(text, mapping={
+            'a': rcpt_name,
+            'b': usertitle,
+            'c': obj.__name__,
+            'd': obj.title,
+            'e': msg.lower(),
+            'f': new_state,
+            'g': config.name})
+
+        body = translate(text, 'waeup.ikoba',
+            target_language=self.PORTAL_LANGUAGE)
+
+        return send_mail(
+            from_name, from_addr, rcpt_name, rcpt_addr,
+            subject, body, config)
 
     def expensive_actions_allowed(self, type=None, request=None):
