# Path: src/schemas/messages.py
# class EmailRecipientModel(BaseModel):
#     first_name: str = None
#     last_name: str = None
#     user_link: str = None
#     address: str = ...
#     tags: List[str] = []
#     context: dict = {}
#     headers: dict = {}
#     pdf_attachments: List[PDFAttachmentModel] = []
#     attachments: List[AttachmentModel] = []
# 
#     class Config:
#         max_anystr_length = int(1e7)
# 
# Path: src/worker/email.py
# STYLES_SASS = (THIS_DIR / 'extra' / 'default-styles.scss').read_text()
# def utcnow():
#     def __init__(self, ctx: dict, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
#     async def run(self):
#     async def _send_mandrill(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _send_test_email(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _render_email(self, context, headers) -> Optional[EmailInfo]:
#     async def _generate_base64_pdf(self, pdf_attachments):
#     async def _generate_base64(self, attachments: List[AttachmentModel]):
#     async def _store_email(self, external_id, send_ts, email_info: EmailInfo):
#     async def _store_email_failed(self, status: MessageStatus, error_msg):
# async def send_email(ctx, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
# class SendEmail:
# 
# Path: src/worker/scheduler.py
# async def delete_old_emails(ctx):
#     if not glove.settings.delete_old_emails:
#         logger.info('settings.delete_old_emails False, not running')
#         return
#     async with glove.pg.acquire() as conn:
#         count = await conn.execute_b(
#             'delete from message_groups where id in (select id from message_groups where created_ts < :cutoff)',
#             cutoff=datetime.now() - timedelta(days=365),
#         )
#     logger.info('deleted %s old messages', count.replace('DELETE ', ''))


import base64
import hashlib
import hmac
import json
import pytest
import re
from arq import Retry
from buildpg import V
from datetime import datetime, timedelta, timezone
from foxglove.db.helpers import SyncDb
from pathlib import Path
from pytest_toolbox.comparison import AnyInt, RegexStr
from starlette.testclient import TestClient
from uuid import uuid4
from src.schemas.messages import EmailRecipientModel
from src.worker import delete_old_emails, email_retrying, send_email as worker_send_email
    message_id = send_email(
        recipients=[{'address': 'foobar@testing.com', 'pdf_attachments': [{'name': 'testing.pdf', 'html': ''}]}]
    )
    assert len(tmpdir.listdir()) == 1
    msg_file = tmpdir.join(f'{message_id}.txt').read()
    assert '\n  "attachments": []\n' in msg_file


def test_mandrill_send_client_error(sync_db: SyncDb, worker_ctx, call_send_emails, loop):
    group_id, c_id, m = call_send_emails(subject_template='__slow__')

    assert sync_db.fetchval('select count(*) from messages') == 0
    worker_ctx['job_try'] = 1

    with pytest.raises(Retry) as exc_info:
        loop.run_until_complete(
            worker_send_email(worker_ctx, group_id, c_id, EmailRecipientModel(address='testing@recipient.com'), m)
        )
    assert exc_info.value.defer_score == 5_000

    assert sync_db.fetchval('select count(*) from messages') == 0


def test_mandrill_send_many_errors(sync_db: SyncDb, worker_ctx, call_send_emails, loop):
    group_id, c_id, m = call_send_emails()

    assert sync_db.fetchval('select count(*) from messages') == 0
    worker_ctx['job_try'] = 10

    loop.run_until_complete(

# Path: src/schemas/messages.py
# class EmailRecipientModel(BaseModel):
#     first_name: str = None
#     last_name: str = None
#     user_link: str = None
#     address: str = ...
#     tags: List[str] = []
#     context: dict = {}
#     headers: dict = {}
#     pdf_attachments: List[PDFAttachmentModel] = []
#     attachments: List[AttachmentModel] = []
# 
#     class Config:
#         max_anystr_length = int(1e7)
# 
# Path: src/worker/email.py
# STYLES_SASS = (THIS_DIR / 'extra' / 'default-styles.scss').read_text()
# def utcnow():
#     def __init__(self, ctx: dict, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
#     async def run(self):
#     async def _send_mandrill(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _send_test_email(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _render_email(self, context, headers) -> Optional[EmailInfo]:
#     async def _generate_base64_pdf(self, pdf_attachments):
#     async def _generate_base64(self, attachments: List[AttachmentModel]):
#     async def _store_email(self, external_id, send_ts, email_info: EmailInfo):
#     async def _store_email_failed(self, status: MessageStatus, error_msg):
# async def send_email(ctx, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
# class SendEmail:
# 
# Path: src/worker/scheduler.py
# async def delete_old_emails(ctx):
#     if not glove.settings.delete_old_emails:
#         logger.info('settings.delete_old_emails False, not running')
#         return
#     async with glove.pg.acquire() as conn:
#         count = await conn.execute_b(
#             'delete from message_groups where id in (select id from message_groups where created_ts < :cutoff)',
#             cutoff=datetime.now() - timedelta(days=365),
#         )
#     logger.info('deleted %s old messages', count.replace('DELETE ', ''))


# Path: tests/test_email.py
import base64
import hashlib
import hmac
import json
import pytest
import re
from arq import Retry
from buildpg import V
from datetime import datetime, timedelta, timezone
from foxglove.db.helpers import SyncDb
from pathlib import Path
from pytest_toolbox.comparison import AnyInt, RegexStr
from starlette.testclient import TestClient
from uuid import uuid4
from src.schemas.messages import EmailRecipientModel
from src.worker import delete_old_emails, email_retrying, send_email as worker_send_email

    message_id = send_email(
        recipients=[{'address': 'foobar@testing.com', 'pdf_attachments': [{'name': 'testing.pdf', 'html': ''}]}]
    )
    assert len(tmpdir.listdir()) == 1
    msg_file = tmpdir.join(f'{message_id}.txt').read()
    assert '\n  "attachments": []\n' in msg_file


def test_mandrill_send_client_error(sync_db: SyncDb, worker_ctx, call_send_emails, loop):
    group_id, c_id, m = call_send_emails(subject_template='__slow__')

    assert sync_db.fetchval('select count(*) from messages') == 0
    worker_ctx['job_try'] = 1

    with pytest.raises(Retry) as exc_info:
        loop.run_until_complete(
            worker_send_email(worker_ctx, group_id, c_id, EmailRecipientModel(address='testing@recipient.com'), m)
        )
    assert exc_info.value.defer_score == 5_000

    assert sync_db.fetchval('select count(*) from messages') == 0


def test_mandrill_send_many_errors(sync_db: SyncDb, worker_ctx, call_send_emails, loop):
    group_id, c_id, m = call_send_emails()

    assert sync_db.fetchval('select count(*) from messages') == 0
    worker_ctx['job_try'] = 10

    loop.run_until_complete(

        worker_send_email(worker_ctx, group_id, c_id, EmailRecipientModel(address='testing@recipient.com'), m)