source: rtems-tools/rtemstoolkit/mailer.py @ 7e5cdea

Last change on this file since 7e5cdea was 7e5cdea, checked in by Chris Johns <chrisj@…>, on Nov 23, 2018 at 4:02:52 AM

rtemstoolkit: Add unit testing for the python modules

  • Add support to run the unit tests for the rtemstoolkit python modules from waf. Enter './waf test' for the tests to be run on python2 and python3.
  • Update the importing of rtemstoolkit modules to the standard method which works on python2 and python3.
  • Update the README.
  • Property mode set to 100644
File size: 5.9 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2013-2016 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# Manage emailing results or reports.
33#
34
35from __future__ import print_function
36
37import os
38import smtplib
39import socket
40
41from rtemstoolkit import error
42from rtemstoolkit import options
43from rtemstoolkit import path
44
45_options = {
46    '--mail'     : 'Send email report or results.',
47    '--smtp-host': 'SMTP host to send via.',
48    '--mail-to'  : 'Email address to send the email too.',
49    '--mail-from': 'Email address the report is from.'
50}
51
52def append_options(opts):
53    for o in _options:
54        opts[o] = _options[o]
55
56def add_arguments(argsp):
57    argsp.add_argument('--mail', help = _options['--mail'], action = 'store_true')
58    for o in ['--smtp-host', '--mail-to', '--mail-from']:
59        argsp.add_argument(o, help = _options[o], type = str)
60
61class mail:
62    def __init__(self, opts):
63        self.opts = opts
64
65    def _args_are_macros(self):
66        return type(self.opts) is 'command_line'
67
68    def _get_arg(self, arg):
69        if self._args_are_macros():
70            value = self.opts.find_arg(arg)[1]
71        else:
72            if arg.startswith('--'):
73                arg = arg[2:]
74            arg = arg.replace('-', '_')
75            if arg in vars(self.opts):
76                value = vars(self.opts)[arg]
77            else:
78                value = None
79        return value
80
81    def from_address(self):
82
83        def _clean(l):
84            if '#' in l:
85                l = l[:l.index('#')]
86            if '\r' in l:
87                l = l[:l.index('r')]
88            if '\n' in l:
89                l = l[:l.index('\n')]
90            return l.strip()
91
92        addr = self._get_arg('--mail-from')
93        if addr is not None:
94            return addr
95        mailrc = None
96        if 'MAILRC' in os.environ:
97            mailrc = os.environ['MAILRC']
98        if mailrc is None and 'HOME' in os.environ:
99            mailrc = path.join(os.environ['HOME'], '.mailrc')
100        if mailrc is not None and path.exists(mailrc):
101            # set from="Joe Blow <joe@blow.org>"
102            try:
103                with open(mailrc, 'r') as mrc:
104                    lines = mrc.readlines()
105            except IOError as err:
106                raise error.general('error reading: %s' % (mailrc))
107            for l in lines:
108                l = _clean(l)
109                if 'from' in l:
110                    fa = l[l.index('from') + len('from'):]
111                    if '=' in fa:
112                        addr = fa[fa.index('=') + 1:].replace('"', ' ').strip()
113            if addr is not None:
114                return addr
115        if self._args_are_macros():
116            addr = self.opts.defaults.get_value('%{_sbgit_mail}')
117        else:
118            raise error.general('no valid from address for mail')
119        return addr
120
121    def smtp_host(self):
122        host = self._get_arg('--smtp-host')
123        if host is not None:
124            return host[1]
125        if self._args_are_macros():
126            host = self.opts.defaults.get_value('%{_mail_smtp_host}')
127        if host is not None:
128            return host
129        return 'localhost'
130
131    def send(self, to_addr, subject, body):
132        from_addr = self.from_address()
133        msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % \
134            (from_addr, to_addr, subject) + body
135        try:
136            s = smtplib.SMTP(self.smtp_host())
137            s.sendmail(from_addr, [to_addr], msg)
138        except smtplib.SMTPException as se:
139            raise error.general('sending mail: %s' % (str(se)))
140        except socket.error as se:
141            raise error.general('sending mail: %s' % (str(se)))
142
143    def send_file_as_body(self, to_addr, subject, name, intro = None):
144        try:
145            with open(name, 'r') as f:
146                body = f.readlines()
147        except IOError as err:
148            raise error.general('error reading mail body: %s' % (name))
149        if intro is not None:
150            body = intro + body
151        self.send(to_addr, from_addr, body)
152
153if __name__ == '__main__':
154    import sys
155    from rtemstoolkit import macros
156    optargs = {}
157    rtdir = 'rtemstoolkit'
158    defaults = '%s/defaults.mc' % (rtdir)
159    append_options(optargs)
160    opts = options.command_line(base_path = '.',
161                                argv = sys.argv,
162                                optargs = optargs,
163                                defaults = macros.macros(name = defaults, rtdir = rtdir),
164                                command_path = '.')
165    options.load(opts)
166    m = mail(opts)
167    print('From: %s' % (m.from_address()))
168    print('SMTP Host: %s' % (m.smtp_host()))
169    if '--mail' in sys.argv:
170        m.send(m.from_address(), 'Test mailer.py', 'This is a test')
Note: See TracBrowser for help on using the repository browser.