<reponame>dreibh/planetlab-lxc-plcapi<gh_stars>0
import os
import sys
import pprint
from email.mime.text import MIMEText
from email.header import Header
from smtplib import SMTP

from PLC.Logger import logger
from PLC.Faults import *

def sendmail(api, To, Subject, Body, From = None, Cc = None, Bcc = None):
    """
    Uses sendmail (must be installed and running locally) to send a
    message to the specified recipients. If the API is running under
    mod_python, the apache user must be listed in e.g.,
    /etc/mail/trusted-users.

    To, Cc, and Bcc may be addresses or lists of addresses. Each
    address may be either a plain text address or a tuple of (name,
    address).
    """

    # Fix up defaults
    if not isinstance(To, list):
        To = [To]
    if Cc is not None and not isinstance(Cc, list):
        Cc = [Cc]
    if Bcc is not None and not isinstance(Bcc, list):
        Bcc = [Bcc]
    if From is None:
        From = ("%s Support" % api.config.PLC_NAME,
                api.config.PLC_MAIL_SUPPORT_ADDRESS)

    # Create a MIME-encoded UTF-8 message
    msg = MIMEText(Body)

    # Unicode subject headers are automatically encoded correctly
    msg['Subject'] = Subject

    def encode_addresses(addresses, header_name = None):
        """
        Unicode address headers are automatically encoded by
        email.Header, but not correctly. The correct way is to put the
        textual name inside quotes and the address inside brackets:

        To: "=?utf-8?b?encoded" <recipient@domain>

        Each address in addrs may be a tuple of (name, address) or
        just an address. Returns a tuple of (header, addrlist)
        representing the encoded header text and the list of plain
        text addresses.
        """

        header = []
        addrs = []

        for addr in addresses:
            if isinstance(addr, tuple):
                (name, addr) = addr
                h = Header(name, charset = api.encoding, header_name = header_name)
                header.append('"%s" <%s>' % (h, addr))
            else:
                header.append(addr)
            addrs.append(addr)

        return (", ".join(header), addrs)

    (msg['From'], from_addrs) = encode_addresses([From], 'From')
    (msg['To'], to_addrs) = encode_addresses(To, 'To')

    if Cc is not None:
        (msg['Cc'], cc_addrs) = encode_addresses(Cc, 'Cc')
        to_addrs += cc_addrs

    if Bcc is not None:
        (unused, bcc_addrs) = encode_addresses(Bcc, 'Bcc')
        to_addrs += bcc_addrs

    # Needed to pass some spam filters
    msg['Reply-To'] = msg['From']
    msg['X-Mailer'] = "Python/" + sys.version.split(" ")[0]

    if not api.config.PLC_MAIL_ENABLED:
        logger.info("PLC_MAIL_ENABLED not set")
        logger.info("From: %(From)s, To: %(To)s, Subject: %(Subject)s" % msg)
        return

    s = SMTP()
    s.connect()
    rejected = s.sendmail(from_addrs[0], to_addrs, msg.as_string(), rcpt_options = ["NOTIFY=NEVER"])
    s.close()

    if rejected:
        raise PLCAPIError("Error sending message to " + ", ".join(list(rejected.keys())))
