"""
Sends a post-release email
"""
from __future__ import print_function
from rez.release_hook import ReleaseHook
from rez.system import system
from email.mime.text import MIMEText
from rez.utils.logging_ import print_warning, print_error
from rez.utils.yaml import load_yaml
from rez.utils.scope import scoped_formatter
from rez.vendor.schema.schema import Or
from rez.vendor.six import six
import os.path
import smtplib
basestring = six.string_types[0]
[docs]class EmailReleaseHook(ReleaseHook):
    schema_dict = {
        "subject": basestring,
        "body": basestring,
        "smtp_host": basestring,
        "smtp_port": int,
        "sender": basestring,
        "recipients": Or(basestring, [basestring])
    }
[docs]    @classmethod
    def name(cls):
        return "emailer" 
    def __init__(self, source_path):
        super(EmailReleaseHook, self).__init__(source_path)
[docs]    def post_release(self, user, install_path, variants, release_message=None,
                     changelog=None, previous_version=None, **kwargs):
        if not variants:
            return  # nothing was released
        # construct email body
        release_dict = dict(path=install_path,
                            previous_version=previous_version or "None.",
                            message=release_message or "No release message.",
                            changelog=changelog or "No changelog.")
        paths_str = '\n'.join(x.root for x in variants)
        variants_dict = dict(count=len(variants),
                             paths=paths_str)
        formatter = scoped_formatter(release=release_dict,
                                     variants=variants_dict,
                                     system=system,
                                     package=self.package)
        body = formatter.format(self.settings.body)
        body = body.strip()
        body = body.replace("\n\n\n", "\n\n")
        # construct subject line, send email
        subject = formatter.format(self.settings.subject)
        self.send_email(subject, body) 
[docs]    def send_email(self, subject, body):
        if not self.settings.recipients:
            return  # nothing to do, sending email to nobody
        if not self.settings.smtp_host:
            print_warning("did not send release email: "
                          "SMTP host is not specified")
            return
        recipients = self.get_recipients()
        if not recipients:
            return
        print("Sending release email to:")
        print('\n'.join("- %s" % x for x in recipients))
        msg = MIMEText(body)
        msg["Subject"] = subject
        msg["From"] = self.settings.sender
        msg["To"] = str(',').join(recipients)
        try:
            s = smtplib.SMTP(self.settings.smtp_host, self.settings.smtp_port)
            s.sendmail(from_addr=self.settings.sender,
                       to_addrs=recipients,
                       msg=msg.as_string())
            print('Email(s) sent.')
        except Exception as e:
            print_error("release email delivery failed: %s" % str(e)) 
[docs]    def get_recipients(self):
        value = self.settings.recipients
        if isinstance(value, list):
            return value
        if os.path.exists(value):
            filepath = value
            try:
                return self.load_recipients(filepath)
            except Exception as e:
                print_error("failed to load recipients config: %s. Emails "
                            "not sent" % str(e))
        elif '@' in value:
            return [value]  # assume it's an email address
        else:
            print_error("email recipient file does not exist: %s. Emails not "
                        "sent" % value)
        return [] 
[docs]    def load_recipients(self, filepath):
        def test(value, type_):
            if not isinstance(value, type_):
                raise TypeError("Expected %s, not %s" % type_, value)
            return value
        conf = load_yaml(filepath)
        recipients = set()
        for rule in test(conf.get("rules", []), list):
            filters = rule.get("filters")
            match = True
            if filters:
                for attr, test_value in test(filters, dict).items():
                    missing = object()
                    value = getattr(self.package, attr, missing)
                    if value is missing:
                        match = False
                    elif test_value is None:
                        match = True
                    elif isinstance(test_value, list):
                        match = (value in test_value)
                    else:
                        match = (value == test_value)
                    if not match:
                        break
            if match:
                rule_recipients = rule.get("recipients")
                recipients.update(test(rule_recipients, list))
        return sorted(recipients)  
[docs]def register_plugin():
    return EmailReleaseHook 
# Copyright 2013-2016 Allan Johns.
#
# This library is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library.  If not, see <http://www.gnu.org/licenses/>.