# Path: pypi_portal/core/email.py
# def send_email(subject, body=None, html=None, recipients=None, throttle=None):
#     """Send an email. Optionally throttle the amount an identical email goes out.
# 
#     If the throttle argument is set, an md5 checksum derived from the subject, body, html, and recipients is stored in
#     Redis with a lock timeout. On the first email sent, the email goes out like normal. But when other emails with the
#     same subject, body, html, and recipients is supposed to go out, and the lock hasn't expired yet, the email will be
#     dropped and never sent.
# 
#     Positional arguments:
#     subject -- the subject line of the email.
# 
#     Keyword arguments.
#     body -- the body of the email (no HTML).
#     html -- the body of the email, can be HTML (overrides body).
#     recipients -- list or set (not string) of email addresses to send the email to. Defaults to the ADMINS list in the
#         Flask config.
#     throttle -- time in seconds or datetime.timedelta object between sending identical emails.
#     """
#     recipients = recipients or current_app.config['ADMINS']
#     if throttle is not None:
#         md5 = hashlib.md5('{}{}{}{}'.format(subject, body, html, recipients)).hexdigest()
#         seconds = throttle.total_seconds() if hasattr(throttle, 'total_seconds') else throttle
#         lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=int(seconds))
#         have_lock = lock.acquire(blocking=False)
#         if not have_lock:
#             LOG.debug('Suppressing email: {}'.format(subject))
#             return
#     msg = Message(subject=subject, recipients=recipients, body=body, html=html)
#     mail.send(msg)
# 
# def send_exception(subject):
#     """Send Python exception tracebacks via email to the ADMINS list.
# 
#     Use the same HTML styling as Flask tracebacks in debug web servers.
# 
#     This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info().
# 
#     Positional arguments:
#     subject -- subject line of the email (to be prepended by 'Application Error: ').
#     """
#     # Generate and modify html.
#     tb = tbtools.get_current_traceback()  # Get exception information.
#     with _override_html():
#         html = tb.render_full().encode('utf-8', 'replace')
#     html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">')
#     subject = 'Application Error: {}'.format(subject)
# 
#     # Apply throttle.
#     md5 = hashlib.md5('{}{}'.format(subject, html)).hexdigest()
#     seconds = int(current_app.config['MAIL_EXCEPTION_THROTTLE'])
#     lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=seconds)
#     have_lock = lock.acquire(blocking=False)
#     if not have_lock:
#         LOG.debug('Suppressing email: {}'.format(subject))
#         return
# 
#     # Send email.
#     msg = Message(subject=subject, recipients=current_app.config['ADMINS'], html=html)
#     mail.send(msg)
# 
# Path: pypi_portal/extensions.py
# LOG = getLogger(__name__)
# def _on_connect(dbapi_connection, **_):


from datetime import timedelta
from pypi_portal.core.email import send_email, send_exception
from pypi_portal.extensions import mail, redis
import time



def raise_and_send():
    with mail.record_messages() as outbox:
        try:
            raise ValueError('Fake error.')
        except ValueError:
            send_exception('Test Email10')
    return outbox


def test_send_email():
    with mail.record_messages() as outbox:
        send_email('Test Email', 'Message body.')
    assert 1 == len(outbox)
    assert 'Test Email' == outbox[0].subject

    with mail.record_messages() as outbox:
        send_email('Test Email2', 'Message body.', throttle=1)
        send_email('Test Email2', 'Message body.', throttle=timedelta(seconds=1))
        send_email('Test Email9', 'Message body.', throttle=1)
        time.sleep(1.1)

# Path: pypi_portal/core/email.py
# def send_email(subject, body=None, html=None, recipients=None, throttle=None):
#     """Send an email. Optionally throttle the amount an identical email goes out.
# 
#     If the throttle argument is set, an md5 checksum derived from the subject, body, html, and recipients is stored in
#     Redis with a lock timeout. On the first email sent, the email goes out like normal. But when other emails with the
#     same subject, body, html, and recipients is supposed to go out, and the lock hasn't expired yet, the email will be
#     dropped and never sent.
# 
#     Positional arguments:
#     subject -- the subject line of the email.
# 
#     Keyword arguments.
#     body -- the body of the email (no HTML).
#     html -- the body of the email, can be HTML (overrides body).
#     recipients -- list or set (not string) of email addresses to send the email to. Defaults to the ADMINS list in the
#         Flask config.
#     throttle -- time in seconds or datetime.timedelta object between sending identical emails.
#     """
#     recipients = recipients or current_app.config['ADMINS']
#     if throttle is not None:
#         md5 = hashlib.md5('{}{}{}{}'.format(subject, body, html, recipients)).hexdigest()
#         seconds = throttle.total_seconds() if hasattr(throttle, 'total_seconds') else throttle
#         lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=int(seconds))
#         have_lock = lock.acquire(blocking=False)
#         if not have_lock:
#             LOG.debug('Suppressing email: {}'.format(subject))
#             return
#     msg = Message(subject=subject, recipients=recipients, body=body, html=html)
#     mail.send(msg)
# 
# def send_exception(subject):
#     """Send Python exception tracebacks via email to the ADMINS list.
# 
#     Use the same HTML styling as Flask tracebacks in debug web servers.
# 
#     This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info().
# 
#     Positional arguments:
#     subject -- subject line of the email (to be prepended by 'Application Error: ').
#     """
#     # Generate and modify html.
#     tb = tbtools.get_current_traceback()  # Get exception information.
#     with _override_html():
#         html = tb.render_full().encode('utf-8', 'replace')
#     html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">')
#     subject = 'Application Error: {}'.format(subject)
# 
#     # Apply throttle.
#     md5 = hashlib.md5('{}{}'.format(subject, html)).hexdigest()
#     seconds = int(current_app.config['MAIL_EXCEPTION_THROTTLE'])
#     lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=seconds)
#     have_lock = lock.acquire(blocking=False)
#     if not have_lock:
#         LOG.debug('Suppressing email: {}'.format(subject))
#         return
# 
#     # Send email.
#     msg = Message(subject=subject, recipients=current_app.config['ADMINS'], html=html)
#     mail.send(msg)
# 
# Path: pypi_portal/extensions.py
# LOG = getLogger(__name__)
# def _on_connect(dbapi_connection, **_):


# Path: tests/core/test_email.py
from datetime import timedelta
from pypi_portal.core.email import send_email, send_exception
from pypi_portal.extensions import mail, redis
import time




def raise_and_send():
    with mail.record_messages() as outbox:
        try:
            raise ValueError('Fake error.')
        except ValueError:
            send_exception('Test Email10')
    return outbox


def test_send_email():
    with mail.record_messages() as outbox:
        send_email('Test Email', 'Message body.')
    assert 1 == len(outbox)
    assert 'Test Email' == outbox[0].subject

    with mail.record_messages() as outbox:
        send_email('Test Email2', 'Message body.', throttle=1)
        send_email('Test Email2', 'Message body.', throttle=timedelta(seconds=1))
        send_email('Test Email9', 'Message body.', throttle=1)
        time.sleep(1.1)

        send_email('Test Email2', 'Message body.', throttle=1)