# Path: amivapi/utils.py
# def mail(to, subject, text):
#     """Send a mail to a list of recipients.
# 
#     The mail is sent from the address specified by `API_MAIL` in the config,
#     and the subject formatted according to `API_MAIL_SUBJECT`.
# 
# 
#     Args:
#         to(list of strings): List of recipient addresses
#         subject(string): Subject string
#         text(string): Mail content
#     """
#     sender = app.config['API_MAIL']
#     subject = app.config['API_MAIL_SUBJECT'].format(subject=subject)
# 
#     if app.config.get('TESTING', False):
#         app.test_mails.append({
#             'subject': subject,
#             'from': sender,
#             'receivers': to,
#             'text': text
#         })
#     elif config.SMTP_SERVER and config.SMTP_PORT:
#         msg = MIMEText(text)
#         msg['Subject'] = subject
#         msg['From'] = sender
#         msg['To'] = ';'.join([to] if isinstance(to, str) else to)
# 
#         try:
#             with smtplib.SMTP(config.SMTP_SERVER,
#                               port=config.SMTP_PORT,
#                               timeout=config.SMTP_TIMEOUT) as smtp:
#                 status_code, _ = smtp.starttls()
#                 if status_code != 220:
#                     app.logger.error("Failed to create secure "
#                                      "SMTP connection!")
#                     return
# 
#                 if config.SMTP_USERNAME and config.SMTP_PASSWORD:
#                     smtp.login(config.SMTP_USERNAME, config.SMTP_PASSWORD)
#                 else:
#                     smtp.ehlo()
# 
#                 try:
#                     smtp.sendmail(msg['From'], to, msg.as_string())
#                 except smtplib.SMTPRecipientsRefused:
#                     error = ("Failed to send mail:\n"
#                              "From: %s\nTo: %s\n"
#                              "Subject: %s\n\n%s")
#                     app.logger.error(error % (sender, str(to), subject, text))
#         except smtplib.SMTPException as e:
#             app.logger.error("SMTP error trying to send mails: %s" % e)
# 
# Path: amivapi/cron.py
# def schedulable(func):
#     """ Registers a function to be in the table of schedulable functions.
#     This is necessary, as we can not save references to python functions in the
#     database.
#     """
#     schedulable_functions[func_str(func)] = func
#     return func
# 
# def schedule_task(time, func, *args):
#     """ Schedule a task at some point in the future. """
#     func_s = func_str(func)
# 
#     if func_s not in schedulable_functions:
#         raise NotSchedulable("%s is not schedulable. Did you forget the "
#                              "@schedulable decorator?" % func.__name__)
# 
#     current_app.data.driver.db['scheduled_tasks'].insert_one({
#         'time': time,
#         'function': func_s,
#         'args': pickle.dumps(args)
#     })


from flask import current_app
from amivapi.utils import mail
from datetime import datetime
from amivapi.cron import schedulable, schedule_task

        mail(email, 'You have been blacklisted!', template.format(**fields))

        # If the end time is already known, schedule removal mail
        if item['end_time'] and item['end_time'] > datetime.utcnow():
            schedule_task(item['end_time'], send_removed_mail, item)


def notify_patch_blacklist(new, old):
    """Send an email to a user if one of his entries was updated."""
    # Checks if the particular update resolved the blacklist entry or just
    # fixes an error, for example changed the reason or price. An entry is
    # resolved when the end_time is before now. The end_time might also
    # have been removed, in which case we don't schedule an email either.
    if 'end_time' not in new or new['end_time'] is None:
        return

    # Either send mail immediately, or schedule for the future
    item = {**old, **new}
    if new['end_time'] <= datetime.utcnow():
        send_removed_mail(item)
    elif new['end_time'] != old['end_time']:
        schedule_task(new['end_time'], send_removed_mail, item)


def notify_delete_blacklist(item):
    """Send an email to a user if one of his entries was deleted."""
    email = _get_email(item)
    fields = {'reason': item['reason']}


# Path: amivapi/utils.py
# def mail(to, subject, text):
#     """Send a mail to a list of recipients.
# 
#     The mail is sent from the address specified by `API_MAIL` in the config,
#     and the subject formatted according to `API_MAIL_SUBJECT`.
# 
# 
#     Args:
#         to(list of strings): List of recipient addresses
#         subject(string): Subject string
#         text(string): Mail content
#     """
#     sender = app.config['API_MAIL']
#     subject = app.config['API_MAIL_SUBJECT'].format(subject=subject)
# 
#     if app.config.get('TESTING', False):
#         app.test_mails.append({
#             'subject': subject,
#             'from': sender,
#             'receivers': to,
#             'text': text
#         })
#     elif config.SMTP_SERVER and config.SMTP_PORT:
#         msg = MIMEText(text)
#         msg['Subject'] = subject
#         msg['From'] = sender
#         msg['To'] = ';'.join([to] if isinstance(to, str) else to)
# 
#         try:
#             with smtplib.SMTP(config.SMTP_SERVER,
#                               port=config.SMTP_PORT,
#                               timeout=config.SMTP_TIMEOUT) as smtp:
#                 status_code, _ = smtp.starttls()
#                 if status_code != 220:
#                     app.logger.error("Failed to create secure "
#                                      "SMTP connection!")
#                     return
# 
#                 if config.SMTP_USERNAME and config.SMTP_PASSWORD:
#                     smtp.login(config.SMTP_USERNAME, config.SMTP_PASSWORD)
#                 else:
#                     smtp.ehlo()
# 
#                 try:
#                     smtp.sendmail(msg['From'], to, msg.as_string())
#                 except smtplib.SMTPRecipientsRefused:
#                     error = ("Failed to send mail:\n"
#                              "From: %s\nTo: %s\n"
#                              "Subject: %s\n\n%s")
#                     app.logger.error(error % (sender, str(to), subject, text))
#         except smtplib.SMTPException as e:
#             app.logger.error("SMTP error trying to send mails: %s" % e)
# 
# Path: amivapi/cron.py
# def schedulable(func):
#     """ Registers a function to be in the table of schedulable functions.
#     This is necessary, as we can not save references to python functions in the
#     database.
#     """
#     schedulable_functions[func_str(func)] = func
#     return func
# 
# def schedule_task(time, func, *args):
#     """ Schedule a task at some point in the future. """
#     func_s = func_str(func)
# 
#     if func_s not in schedulable_functions:
#         raise NotSchedulable("%s is not schedulable. Did you forget the "
#                              "@schedulable decorator?" % func.__name__)
# 
#     current_app.data.driver.db['scheduled_tasks'].insert_one({
#         'time': time,
#         'function': func_s,
#         'args': pickle.dumps(args)
#     })


# Path: amivapi/blacklist/emails.py
from flask import current_app
from amivapi.utils import mail
from datetime import datetime
from amivapi.cron import schedulable, schedule_task


        mail(email, 'You have been blacklisted!', template.format(**fields))

        # If the end time is already known, schedule removal mail
        if item['end_time'] and item['end_time'] > datetime.utcnow():
            schedule_task(item['end_time'], send_removed_mail, item)


def notify_patch_blacklist(new, old):
    """Send an email to a user if one of his entries was updated."""
    # Checks if the particular update resolved the blacklist entry or just
    # fixes an error, for example changed the reason or price. An entry is
    # resolved when the end_time is before now. The end_time might also
    # have been removed, in which case we don't schedule an email either.
    if 'end_time' not in new or new['end_time'] is None:
        return

    # Either send mail immediately, or schedule for the future
    item = {**old, **new}
    if new['end_time'] <= datetime.utcnow():
        send_removed_mail(item)
    elif new['end_time'] != old['end_time']:
        schedule_task(new['end_time'], send_removed_mail, item)


def notify_delete_blacklist(item):
    """Send an email to a user if one of his entries was deleted."""
    email = _get_email(item)
    fields = {'reason': item['reason']}


    mail(email, 'Your blacklist entry has been removed!',