##############################################################################
# Copyright (c) 2005 The Open Planning Project and Rob Miller
# All Rights Reserved.
#
# This software is subject to the provisions of the GNU General Public
# License, Version 2.0 (GPL).  A copy of the GPL should accompany this
# distribution.  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
# AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
##############################################################################


from types import StringType
from email.Utils import getaddresses
import re

EMAIL_RE = re.compile(r"^(\w&.%#$&'\*+-/=?^_`{}|~]+!)*[\w&.%#$&'\*+-/=?^_`{}|~]+@(([0-9a-z]([0-9a-z-]*[0-9a-z])?\.)+[a-z]{2,6}|([0-9]{1,3}\.){3}[0-9]{1,3})$", re.IGNORECASE)
# used to find double new line (in any variant)
EMAIL_CUTOFF_RE = re.compile(r".*[\n\r][\n\r]")

from Products.CMFPlone.PloneTool import PloneTool

def sendto(self, send_to_address, send_from_address, comment,
           subject='Plone', template='sendto_template', **kwargs):
    """Sends a link of a page to someone."""
    host = self.getMailHost()
    template = getattr(self, template)
    encoding = self.getSiteEncoding()
    if 'envelope_from' in kwargs:
        envelope_from = kwargs['envelope_from']
    else:
        envelope_from = send_from_address
    # Cook from template
    message = template(self, send_to_address=send_to_address,
                       send_from_address=send_from_address,
                       comment=comment, subject=subject, **kwargs)
    if getattr(host.aq_base, 'secureSend', None) is None:
        # not using SecureMailHost
        host.send(message, send_to_address, send_from_address,
                  subject=subject, encode='quoted-printable')
    else:
        # using SecureMailHost
        result = host.secureSend(message, send_to_address,
                                 envelope_from, subject=subject,
                                 subtype='plain', charset=encoding,
                                 debug=False, From=send_from_address)


################################################################
#
# The following email validation methods have copied the code
# from SecureMailHost (which PloneTool normally delegates to)
# into PloneTool itself, so that Plone will work w/ alternate
# MailHost implementations.  This is a hacky workaround until
# Plone fixes up its MailHost dependency issue
# (see http://dev.plone.org/plone/ticket/5584)

def validateSingleNormalizedEmailAddress(self, address):
    if type(address) is not StringType:
        return False

    sub = EMAIL_CUTOFF_RE.match(address);
    if sub != None:
        # Address contains two newlines (possible spammer relay attack)
        return False

    # sub is an empty string if the address is valid
    sub = EMAIL_RE.sub('', address)
    if sub == '':
        return True
    return False

def validateSingleEmailAddress(self, address):
    if type(address) is not StringType:
        return False

    sub = EMAIL_CUTOFF_RE.match(address);
    if sub != None:
        # Address contains two newlines (spammer attack using
        # "address\n\nSpam message")
        return False

    if len(getaddresses([address])) != 1:
        # none or more than one address
        return False

    # Validate the address
    for name,addr in getaddresses([address]):
        if not self.validateSingleNormalizedEmailAddress(addr):
            return False
    return True

def validateEmailAddresses(self, addresses):
    if type(addresses) is not StringType:
        return False

    sub = EMAIL_CUTOFF_RE.match(addresses);
    if sub != None:
        # Addresses contains two newlines (spammer attack using
        # "To: list\n\nSpam message")
        return False

    # Validate each address
    for name,addr in getaddresses([addresses]):
        if not self.validateSingleNormalizedEmailAddress(addr):
            return False
    return True

#
# End of email validation code
#
################################################################

PloneTool.sendto = sendto
PloneTool.validateSingleNormalizedEmailAddress = \
    validateSingleNormalizedEmailAddress
PloneTool.validateSingleEmailAddress = validateSingleEmailAddress
PloneTool.validateEmailAddresses = validateEmailAddresses
