From 97a685fae36578912e02b08c941b4eac9f21bd39 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 30 Apr 2013 11:20:54 +1000 Subject: [PATCH] Add mail support to mail reports. --- source-builder/defaults.mc | 4 ++ source-builder/sb/git.py | 21 ++++++ source-builder/sb/mailer.py | 109 ++++++++++++++++++++++++++++++++ source-builder/sb/setbuilder.py | 51 +++++++++------ 4 files changed, 164 insertions(+), 21 deletions(-) create mode 100644 source-builder/sb/mailer.py diff --git a/source-builder/defaults.mc b/source-builder/defaults.mc index f4098fb..efce0a2 100644 --- a/source-builder/defaults.mc +++ b/source-builder/defaults.mc @@ -247,3 +247,7 @@ FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ; # Default package settings _forced_static: none, none, '-Xlinker -Bstatic ${LIBS_STATIC} -Xlinker -Bdynamic' __xz: exe, required, '/usr/bin/xz' + +# Mail Support +_mail_smtp_host: none, none, 'localhost' +_mail_tools_to: none, none, 'rtems-tooltestresults@rtems.org' diff --git a/source-builder/sb/git.py b/source-builder/sb/git.py index e503beb..621c048 100644 --- a/source-builder/sb/git.py +++ b/source-builder/sb/git.py @@ -148,6 +148,26 @@ class repo: _remotes[r_name][r_type] = '='.join(ls[1:]) return _remotes + def email(self): + _email = None + _name = None + ec, output = self._run(['config', '--list']) + if ec == 0: + for l in output.split('\n'): + if l.startswith('user.email'): + ls = l.split('=') + if len(ls) >= 2: + _email = ls[1] + elif l.startswith('user.name'): + ls = l.split('=') + if len(ls) >= 2: + _name = ls[1] + if _email is not None: + if _name is not None: + _email = '%s <%s>' % (_name, _email) + return _email + return None + def head(self): hash = '' ec, output = self._run(['log', '-n', '1']) @@ -166,4 +186,5 @@ if __name__ == '__main__': print g.status() print g.clean() print g.remotes() + print g.email() print g.head() diff --git a/source-builder/sb/mailer.py b/source-builder/sb/mailer.py new file mode 100644 index 0000000..b6f686c --- /dev/null +++ b/source-builder/sb/mailer.py @@ -0,0 +1,109 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# +# Manage emailing results or reports. +# + +import os +import smtplib +import socket + +import error +import options +import path + +def append_options(opts): + opts['--mail'] = 'Send email report or results.' + opts['--smtp-host'] = 'SMTP host to send via.' + opts['--mail-to'] = 'Email address to send the email too.' + opts['--mail-from'] = 'Email address the report is from.' + +class mail: + def __init__(self, opts): + self.opts = opts + + def from_address(self): + + def _clean(l): + if '#' in l: + l = l[:l.index('#')] + if '\r' in l: + l = l[:l.index('r')] + if '\n' in l: + l = l[:l.index('\n')] + return l.strip() + + addr = self.opts.get_arg('--mail-from') + if addr is not None: + return addr[1] + mailrc = None + if 'MAILRC' in os.environ: + mailrc = os.environ['MAILRC'] + if mailrc is None and 'HOME' in os.environ: + mailrc = path.join(os.environ['HOME'], '.mailrc') + if mailrc is not None and path.exists(mailrc): + # set from="Joe Blow " + try: + mrc = open(mailrc, 'r') + lines = mrc.readlines() + mrc.close() + except IOError, err: + raise error.general('error reading: %s' % (mailrc)) + for l in lines: + l = _clean(l) + if 'from' in l: + fa = l[l.index('from') + len('from'):] + if '=' in fa: + addr = fa[fa.index('=') + 1:].replace('"', ' ').strip() + if addr is not None: + return addr + addr = self.opts.defaults.get_value('%{_sbgit_mail}') + return addr + + def smtp_host(self): + host = self.opts.get_arg('--smtp-host') + if host is not None: + return host[1] + host = self.opts.defaults.get_value('%{_mail_smtp_host}') + if host is not None: + return host + return 'localhost' + + def send(self, to_addr, subject, body): + from_addr = self.from_address() + msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % \ + (from_addr, to_addr, subject) + body + try: + s = smtplib.SMTP(self.smtp_host()) + s.sendmail(from_addr, [to_addr], msg) + except smtplib.SMTPException, se: + raise error.general('sending mail: %s' % (str(se))) + except socket.error, se: + raise error.general('sending mail: %s' % (str(se))) + +if __name__ == '__main__': + import sys + optargs = {} + append_options(optargs) + opts = options.load(sys.argv, optargs = optargs, defaults = 'defaults.mc') + m = mail(opts) + print 'From: %s' % (m.from_address()) + print 'SMTP Host: %s' % (m.smtp_host()) + m.send(m.from_address(), 'Test mailer.py', 'This is a test') diff --git a/source-builder/sb/setbuilder.py b/source-builder/sb/setbuilder.py index 80dc2cd..ced45ca 100644 --- a/source-builder/sb/setbuilder.py +++ b/source-builder/sb/setbuilder.py @@ -35,6 +35,7 @@ try: import check import error import log + import mailer import options import path import reports @@ -59,15 +60,15 @@ class buildset: self.macros = copy.copy(macros) self.bset = bset self.bset_pkg = '%s-%s-set' % (self.macros.expand('%{_target}'), self.bset) - self.email_report = '' + self.mail_report = '' - def write_email_report(self, text, prepend = False): + def write_mail_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 + self.mail_report = text + self.mail_report else: - self.email_report += text + self.mail_report += text def copy(self, src, dst): if not os.path.isdir(path.host(src)): @@ -84,7 +85,7 @@ class buildset: raise error.general('copying tree: %s' % (str(err))) def report(self, _config, _build): - if not _build.opts.get_arg('--no-report') and not _build.opts.get_arg('--no-email'): + if not _build.opts.get_arg('--no-report') and _build.opts.get_arg('--mail'): format = _build.opts.get_arg('--report-format') if format is None: format = 'html' @@ -118,12 +119,12 @@ class buildset: _build.mkdir(outpath) r.write(outname) del r - if not _build.opts.get_arg('--no-email'): + if _build.opts.get_arg('--mail'): 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 + self.mail_report += r.out del r def root_copy(self, src, dst): @@ -275,9 +276,11 @@ class buildset: 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()) + if self.opts.get_arg('--mail'): + mail_report_subject = \ + 'Build Set: %s %s (%s)' % (self.bset, + self.macros.expand('%{_host}'), + datetime.datetime.now().ctime()) configs = self.load() @@ -317,7 +320,7 @@ class buildset: else: raise error.general('invalid config type: %s' % (configs[s])) except error.general, gerr: - self.write_email_report(str(gerr)) + self.write_mail_report(str(gerr)) if self.opts.keep_going(): print gerr if self.opts.always_clean(): @@ -344,12 +347,21 @@ class buildset: os.environ['PATH'] = current_path - log.notice('Build Set: Time %s' % (str(end - start))) + build_time = 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) + if self.opts.get_arg('--mail'): + to_addr = self.opts.get_arg('--mail-to') + if to_addr is not None: + to_addr = to_addr[1] + else: + to_addr = self.macros.expand('%{_mail_tools_to}') + log.notice('Mailing report: %s' % (to_addr)) + self.write_mail_report('Build Time %s' % (build_time), True) + m = mailer.mail(self.opts) + if not self.opts.dry_run(): + m.send(to_addr, mail_report_subject, self.mail_report) + + log.notice('Build Set: Time %s' % (build_time)) def list_bset_cfg_files(opts, configs): if opts.get_arg('--list-configs') or opts.get_arg('--list-bsets'): @@ -374,11 +386,8 @@ def run(): '--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).', - '--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.' } + '--report-format': 'The report format (text, html, asciidoc).' } + mailer.append_options(optargs) opts = options.load(sys.argv, optargs) log.notice('RTEMS Source Builder - Set Builder, v%s' % (version.str())) if not check.host_setup(opts):