Index: source-builder/sb/reports.py
===================================================================
--- source-builder/sb/reports.py	(revision 8837860347fd87db5a5b17224439d403e28a3a35)
+++ source-builder/sb/reports.py	(revision adf09460a298bf241d7e61bfe620a5e5dd73416d)
@@ -155,5 +155,5 @@
             self.output('')
 
-    def introduction(self, name, intro_text):
+    def introduction(self, name, intro_text = None):
         if self.is_asciidoc():
             h = 'RTEMS Source Builder Report'
@@ -246,7 +246,6 @@
                 self.output('--------------------------------------------')
 
-    def config(self, configname, opts, macros):
-
-        _config = config.file(configname, opts, macros)
+    def config(self, _config, opts, macros):
+
         packages = _config.packages()
         package = packages['main']
@@ -255,10 +254,10 @@
         if self.is_asciidoc():
             self.output('*Package*: _%s_ +' % (name))
-            self.output('*Config*: %s' % (configname))
+            self.output('*Config*: %s' % (_config.file_name()))
             self.output('')
         else:
             self.output('-' * self.line_len)
             self.output('Package: %s' % (name))
-            self.output(' Config: %s' % (configname))
+            self.output(' Config: %s' % (_config.file_name()))
         self.output_info('Summary', package.get_info('summary'), True)
         self.output_info('URL', package.get_info('url'))
@@ -303,23 +302,5 @@
         self.config_end(name)
 
-    def buildset(self, name, opts = None, macros = None):
-        self.bset_nesting += 1
-        self.buildset_start(name)
-        if opts is None:
-            opts = self.opts
-        if macros is None:
-            macros = self.macros
-        bset = setbuilder.buildset(name, self.configs, opts, macros)
-        for c in bset.load():
-            if c.endswith('.bset'):
-                self.buildset(c, bset.opts, bset.macros)
-            elif c.endswith('.cfg'):
-                self.config(c, bset.opts, bset.macros)
-            else:
-                raise error.general('invalid config type: %s' % (c))
-        self.buildset_end(name)
-        self.bset_nesting -= 1
-
-    def generate(self, name):
+    def write(self, name):
         if self.format == 'html':
             if self.asciidoc is None:
@@ -341,17 +322,28 @@
                 raise error.general('writing output file: %s: %s' % (name, err))
 
-    def make(self, inname, outname = None, intro_text = None):
+    def generate(self, name, opts = None, macros = None):
+        self.bset_nesting += 1
+        self.buildset_start(name)
+        if opts is None:
+            opts = self.opts
+        if macros is None:
+            macros = self.macros
+        bset = setbuilder.buildset(name, self.configs, opts, macros)
+        for c in bset.load():
+            if c.endswith('.bset'):
+                self.buildset(c, bset.opts, bset.macros)
+            elif c.endswith('.cfg'):
+                self.config(config.file(c, bset.opts, bset.macros),
+                            bset.opts, bset.macros)
+            else:
+                raise error.general('invalid config type: %s' % (c))
+        self.buildset_end(name)
+        self.bset_nesting -= 1
+
+    def create(self, inname, outname = None, intro_text = None):
         self.setup()
         self.introduction(inname, intro_text)
-        config = build.find_config(inname, self.configs)
-        if config is None:
-            raise error.general('config file not found: %s' % (inname))
-        if config.endswith('.bset'):
-            self.buildset(config)
-        elif config.endswith('.cfg'):
-            self.config(config, self.opts, self.macros)
-        else:
-            raise error.general('invalid config type: %s' % (config))
-        self.generate(outname)
+        self.generate(inname)
+        self.write(outname)
 
 def run(args):
@@ -395,6 +387,11 @@
                 else:
                     outname = output
-                r.make(_config, outname)
+                config = build.find_config(_config, configs)
+                if config is None:
+                    raise error.general('config file not found: %s' % (inname))
+                r.create(config, outname)
             del r
+        else:
+            raise error.general('invalid config type: %s' % (config))
     except error.general, gerr:
         print gerr
Index: source-builder/sb/setbuilder.py
===================================================================
--- source-builder/sb/setbuilder.py	(revision 8837860347fd87db5a5b17224439d403e28a3a35)
+++ source-builder/sb/setbuilder.py	(revision adf09460a298bf241d7e61bfe620a5e5dd73416d)
@@ -60,4 +60,13 @@
         self.bset = bset
         self.bset_pkg = '%s-%s-set' % (self.macros.expand('%{_target}'), self.bset)
+        self.email_report = ''
+
+    def write_email_report(self, text, prepend = False):
+        if len(text) == 0 or text[-1] != '\n' or text[-1] != '\r':
+            text += os.linesep
+        if prepend:
+            self.email_report = text + self.email_report
+        else:
+            self.email_report += text
 
     def copy(self, src, dst):
@@ -76,5 +85,5 @@
 
     def report(self, _config, _build):
-        if not _build.opts.get_arg('--no-report'):
+        if not _build.opts.get_arg('--no-report') and not _build.opts.get_arg('--no-email'):
             format = _build.opts.get_arg('--report-format')
             if format is None:
@@ -98,11 +107,22 @@
             prefix = _build.macros.expand('%{_prefix}')
             name = _build.main_package().name() + ext
-            outpath = path.host(path.join(buildroot, prefix, 'share', 'rtems-source-builder'))
-            outname = path.host(path.join(outpath, name))
             log.notice('reporting: %s -> %s' % (_config, name))
-            if not _build.opts.dry_run():
-                _build.mkdir(outpath)
+            if not _build.opts.get_arg('--no-report'):
+                outpath = path.host(path.join(buildroot, prefix, 'share', 'rtems-source-builder'))
+                outname = path.host(path.join(outpath, name))
                 r = reports.report(format, self.configs, _build.opts, _build.macros)
-                r.make(_config, outname)
+                r.setup()
+                r.introduction(_build.config.file_name())
+                r.config(_build.config, _build.opts, _build.macros)
+                if not _build.opts.dry_run():
+                    _build.mkdir(outpath)
+                    r.write(outname)
+                del r
+            if not _build.opts.get_arg('--no-email'):
+                r = reports.report('text', self.configs, _build.opts, _build.macros)
+                r.setup()
+                r.introduction(_build.config.file_name())
+                r.config(_build.config, _build.opts, _build.macros)
+                self.email_report += r.out
                 del r
 
@@ -234,16 +254,20 @@
     def load(self):
 
-        exbset = self.macros.expand(self.bset)
-
-        self.macros['_bset'] = exbset
-
-        root, ext = path.splitext(exbset)
-
-        if exbset.endswith('.bset'):
-            bset = exbset
+        #
+        # If the build set file ends with .cfg the user has passed to the
+        # buildset builder a configuration so we just return it.
+        #
+        if self.bset.endswith('.cfg'):
+            configs = [self.bset]
         else:
-            bset = '%s.bset' % (exbset)
-
-        return self.parse(bset)
+            exbset = self.macros.expand(self.bset)
+            self.macros['_bset'] = exbset
+            root, ext = path.splitext(exbset)
+            if exbset.endswith('.bset'):
+                bset = exbset
+            else:
+                bset = '%s.bset' % (exbset)
+            configs = self.parse(bset)
+        return configs
 
     def build(self, deps = None):
@@ -251,4 +275,8 @@
         log.trace('_bset: %s: make' % (self.bset))
         log.notice('Build Set: %s' % (self.bset))
+
+        if not self.opts.get_arg('--no-email'):
+            email_report_header = \
+                'Build Set: %s (%s)' % (self.bset, datetime.datetime.now().ctime())
 
         configs = self.load()
@@ -272,8 +300,10 @@
                     macros = copy.copy(self.macros)
                     if configs[s].endswith('.bset'):
+                        log.trace('_bset: %s' % ('=' * 80))
                         bs = buildset(configs[s], self.configs, opts, macros)
                         bs.build(deps)
                         del bs
                     elif configs[s].endswith('.cfg'):
+                        log.trace('_bset: %s' % ('-' * 80))
                         b = build.build(configs[s], self.opts.get_arg('--pkg-tar-files'),
                                         opts, macros)
@@ -288,4 +318,5 @@
                         raise error.general('invalid config type: %s' % (configs[s]))
                 except error.general, gerr:
+                    self.write_email_report(str(gerr))
                     if self.opts.keep_going():
                         print gerr
@@ -316,4 +347,9 @@
         log.notice('Build Set: Time %s' % (str(end - start)))
 
+        if not self.opts.get_arg('--no-email'):
+            self.write_email_report('', True)
+            self.write_email_report('  Build Time %s' % (str(end - start)), True)
+            self.write_email_report(email_report_header, True)
+
 def list_bset_cfg_files(opts, configs):
     if opts.get_arg('--list-configs') or opts.get_arg('--list-bsets'):
@@ -336,8 +372,12 @@
                     '--list-bsets':    'List available build sets',
                     '--list-deps':     'List the dependent files.',
+                    '--bset-tar-file': 'Create a build set tar file',
+                    '--pkg-tar-files': 'Create package tar files',
                     '--no-report':     'Do not create a package report.',
                     '--report-format': 'The report format (text, html, asciidoc).',
-                    '--bset-tar-file': 'Create a build set tar file',
-                    '--pkg-tar-files': 'Create package tar files' }
+                    '--no-email':      'Do not send an email report.',
+                    '--smtp-host':     'SMTP host to send via.',
+                    '--email-to':      'Email address to send the email too.',
+                    '--email-from':    'Email address the report is from.' }
         opts = options.load(sys.argv, optargs)
         log.notice('RTEMS Source Builder - Set Builder, v%s' % (version.str()))
