From 713730420cb54fcd5290710d3b9e1da820182c16 Mon Sep 17 00:00:00 2001 From: berkay Date: Mon, 24 Mar 2025 12:48:31 +0300 Subject: [PATCH] email services updated --- .../RoutineEmailService/.python-version | 1 + BankServices/RoutineEmailService/Dockerfile | 40 ++++++++++++ BankServices/RoutineEmailService/README.md | 0 BankServices/RoutineEmailService/app.py | 57 +++++++++++++++++ .../RoutineEmailService/pyproject.toml | 15 +++++ .../RoutineEmailService/templates/a.txt | 0 BankServices/SenderService/Dockerfile | 8 +++ BankServices/SenderService/app.py | 10 +++ BankServices/SenderService/pyproject.toml | 5 ++ BankServices/SenderService/templates/a.txt | 0 .../ServiceDepends/template_accounts.html | 50 +++++++++++++++ BankServices/WriterService/Dockerfile | 2 + BankServices/WriterService/app.py | 3 +- Services/EmailService/config.py | 9 +++ Services/EmailService/provider.py | 41 ++++++++++++ docker-compose.yml | 54 +++++++++------- pyproject.toml | 2 +- uv.lock | 62 ++++++++++++------- 18 files changed, 310 insertions(+), 49 deletions(-) create mode 100644 BankServices/RoutineEmailService/.python-version create mode 100644 BankServices/RoutineEmailService/Dockerfile create mode 100644 BankServices/RoutineEmailService/README.md create mode 100644 BankServices/RoutineEmailService/app.py create mode 100644 BankServices/RoutineEmailService/pyproject.toml create mode 100644 BankServices/RoutineEmailService/templates/a.txt create mode 100644 BankServices/SenderService/templates/a.txt create mode 100644 BankServices/ServiceDepends/template_accounts.html create mode 100644 Services/EmailService/config.py create mode 100644 Services/EmailService/provider.py diff --git a/BankServices/RoutineEmailService/.python-version b/BankServices/RoutineEmailService/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/BankServices/RoutineEmailService/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/BankServices/RoutineEmailService/Dockerfile b/BankServices/RoutineEmailService/Dockerfile new file mode 100644 index 0000000..590d35e --- /dev/null +++ b/BankServices/RoutineEmailService/Dockerfile @@ -0,0 +1,40 @@ +FROM python:3.12-slim + +WORKDIR / + +# Install system dependencies and Poetry +RUN apt-get update && apt-get install -y --no-install-recommends gcc \ + && rm -rf /var/lib/apt/lists/* && pip install --no-cache-dir poetry + +# Copy Poetry configuration +COPY /BankServices/RoutineEmailService/pyproject.toml ./pyproject.toml + +# Configure Poetry and install dependencies with optimizations +RUN poetry config virtualenvs.create false && poetry install --no-interaction --no-ansi --no-root --only main \ + && pip cache purge && rm -rf ~/.cache/pypoetry + +# Install cron for scheduling tasks +RUN apt-get update && apt-get install -y cron + +# 11:00 Istanbul Time (UTC+3) system time is 08:00 UTC +RUN echo "0 8 * * * /usr/local/bin/python /app.py >> /var/log/cron.log 2>&1" > /tmp/crontab_list && crontab /tmp/crontab_list + +# Copy application code +ADD /BankServices/RoutineEmailService / + +ADD /Configs /Configs +ADD /Schemas /Schemas +ADD /Commons /Commons + +ADD /Services/MongoService /Services/MongoService +ADD /Services/PostgresService /Services/PostgresService +ADD /Services/EmailService /Services/EmailService + +# Set Python path to include app directory +ENV PYTHONPATH=/ PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1 + +# Create log file to grab cron logs +RUN touch /var/log/cron.log + +# Run cron setup and tail the log file for user to monitor logs +CMD cron && tail -f /var/log/cron.log diff --git a/BankServices/RoutineEmailService/README.md b/BankServices/RoutineEmailService/README.md new file mode 100644 index 0000000..e69de29 diff --git a/BankServices/RoutineEmailService/app.py b/BankServices/RoutineEmailService/app.py new file mode 100644 index 0000000..8b25418 --- /dev/null +++ b/BankServices/RoutineEmailService/app.py @@ -0,0 +1,57 @@ +import os +import arrow + +from Schemas import AccountRecords +from jinja2 import Environment, FileSystemLoader +from Services.EmailService.provider import send_email + + +def render_email_template(headers: list, rows: list): + template_dir = os.path.join(os.path.dirname(__file__), "templates") + env = Environment(loader=FileSystemLoader(template_dir)) # Load templates from the directory + template = env.get_template("template_accounts.html") # Load the specific template file + return template.render(headers=headers, rows=rows) # Render template with variables + + +def send_email_to_given_address(send_to: str, html_template: str): + today = arrow.now() + subject = f"{str(today.date())} Gunes Apt. Cari Durum Bilgilendirme Raporu" + try: + send_email(subject=subject, receivers=[send_to], html=html_template) + print(f"Email is sent to : {send_to}. BB") + return + except Exception as e: + print(f"Error: {e}") + print("Email is not sent") + return + + +def set_account_records_to_send_email(): + account_records = ( + AccountRecords.query.filter() + .order_by( + AccountRecords.bank_date.desc(), AccountRecords.bank_reference_code.desc() + ) + .limit(3) + .all() + ) + + first_record, second_record, balance_error = account_records[0], account_records[1], False + second_balance = first_record.bank_balance - first_record.currency_value + if second_balance != second_record.bank_balance: + balance_error = True + + rows = [{ + "date": record.bank_date, "comment": record.bank_comment, "currency": record.currency_value, + } for record in account_records] + + send_to = "karatay@mehmetkaratay.com.tr" + html_template = render_email_template( + headers=["Ulaştığı Tarih", "Banka Transaksiyonu Ek Bilgi", "Aktarım Değeri"], + rows=rows, + ) + exit() + + +if __name__ == "__main__": + set_account_records_to_send_email() diff --git a/BankServices/RoutineEmailService/pyproject.toml b/BankServices/RoutineEmailService/pyproject.toml new file mode 100644 index 0000000..d494dc5 --- /dev/null +++ b/BankServices/RoutineEmailService/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "routineemailservice" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "arrow>=1.3.0", + "fastapi>=0.115.11", + "jinja2>=3.1.6", + "psycopg2-binary>=2.9.10", + "redbox>=0.2.1", + "redmail>=0.6.0", + "sqlalchemy-mixins>=2.0.5", +] diff --git a/BankServices/RoutineEmailService/templates/a.txt b/BankServices/RoutineEmailService/templates/a.txt new file mode 100644 index 0000000..e69de29 diff --git a/BankServices/SenderService/Dockerfile b/BankServices/SenderService/Dockerfile index 77091cd..1f96d28 100644 --- a/BankServices/SenderService/Dockerfile +++ b/BankServices/SenderService/Dockerfile @@ -16,6 +16,14 @@ RUN poetry config virtualenvs.create false && poetry install --no-interaction -- # Copy application code ADD /BankServices/SenderService / +ADD /Configs /Configs +ADD /Schemas /Schemas +ADD /Commons /Commons + +ADD /Services/MongoService /Services/MongoService +ADD /Services/PostgresService /Services/PostgresService +ADD /Services/EmailService /Services/EmailService + # Set Python path to include app directory ENV PYTHONPATH=/ PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1 diff --git a/BankServices/SenderService/app.py b/BankServices/SenderService/app.py index c89fe15..d07132d 100644 --- a/BankServices/SenderService/app.py +++ b/BankServices/SenderService/app.py @@ -1,11 +1,21 @@ import time +from jinja2 import Template +# todo Check if postgres is_email_send === False then send email +# todo Trigger @mongo email_send = False then send email def app(): print("Hello from sender service!") +def check_any_written_stage_in_mongo_database(mongo_provider) -> bool: + return mongo_provider.find_one(filter_query={"stage": "written", "send": None}) + + + + if __name__ == "__main__": + while True: app() time.sleep(5) diff --git a/BankServices/SenderService/pyproject.toml b/BankServices/SenderService/pyproject.toml index 8a5c4e8..f8c20db 100644 --- a/BankServices/SenderService/pyproject.toml +++ b/BankServices/SenderService/pyproject.toml @@ -5,7 +5,12 @@ description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [ + "arrow>=1.3.0", + "fastapi>=0.115.11", + "jinja2>=3.1.6", "psycopg2-binary>=2.9.10", "pymongo>=4.11.3", "redbox>=0.2.1", + "redmail>=0.6.0", + "sqlalchemy-mixins>=2.0.5", ] diff --git a/BankServices/SenderService/templates/a.txt b/BankServices/SenderService/templates/a.txt new file mode 100644 index 0000000..e69de29 diff --git a/BankServices/ServiceDepends/template_accounts.html b/BankServices/ServiceDepends/template_accounts.html new file mode 100644 index 0000000..9a67df5 --- /dev/null +++ b/BankServices/ServiceDepends/template_accounts.html @@ -0,0 +1,50 @@ + + + + + + Gelen Banka Kayıtları + + + +

Günaydın, Admin

+
+ + + + {% for header in headers %} + + {% endfor %} + + + + {% for row in rows %} + + {% for cell in row %} + + {% endfor %} + + {% endfor %} + +
{{ header }}
{{ cell }}
+ + \ No newline at end of file diff --git a/BankServices/WriterService/Dockerfile b/BankServices/WriterService/Dockerfile index f20e585..fe41f7f 100644 --- a/BankServices/WriterService/Dockerfile +++ b/BankServices/WriterService/Dockerfile @@ -13,6 +13,8 @@ COPY /BankServices/WriterService/pyproject.toml ./pyproject.toml RUN poetry config virtualenvs.create false && poetry install --no-interaction --no-ansi --no-root --only main \ && pip cache purge && rm -rf ~/.cache/pypoetry + + # Copy application code ADD /BankServices/WriterService / ADD /Configs /Configs diff --git a/BankServices/WriterService/app.py b/BankServices/WriterService/app.py index 95ab704..874842b 100644 --- a/BankServices/WriterService/app.py +++ b/BankServices/WriterService/app.py @@ -48,8 +48,7 @@ def write_parsed_data_to_account_records( new_account_record.is_confirmed = True new_account_record.save(db=db_session) mongo_provider.update_one( - filter_query={"filename": file}, - update_data={"$set": {"stage": "written"}}, + filter_query={"filename": file}, update_data={"$set": {"stage": "written"}}, ) diff --git a/Services/EmailService/config.py b/Services/EmailService/config.py new file mode 100644 index 0000000..4cb919e --- /dev/null +++ b/Services/EmailService/config.py @@ -0,0 +1,9 @@ + + +class EmailConfig: + EMAIL_HOST: str = "10.10.2.34" + EMAIL_USERNAME: str = "karatay@mehmetkaratay.com.tr" + EMAIL_PASSWORD: str = "system" + EMAIL_PORT: int = 587 + + diff --git a/Services/EmailService/provider.py b/Services/EmailService/provider.py new file mode 100644 index 0000000..17e7ba2 --- /dev/null +++ b/Services/EmailService/provider.py @@ -0,0 +1,41 @@ +from redmail import EmailSender +from Services.EmailService.config import EmailConfig + + +email_sender = EmailSender( + host=EmailConfig.EMAIL_HOST, + port=int(EmailConfig.EMAIL_PORT), + username=EmailConfig.EMAIL_USERNAME, + password=EmailConfig.EMAIL_PASSWORD, +) + + +def send_email( + subject: str, + receivers: list, + text: str = "", + html: str = "", + cc: list = None, + bcc: list = None, + headers: dict = None, + attachments: dict = None, +) -> bool: + try: + email_sender.connect() + receivers = ["karatay@mehmetkaratay.com.tr"] + email_sender.send( + subject=subject, + receivers=receivers, + text=text + f" : Gonderilen [{str(receivers)}]", + html=html, + cc=cc, + bcc=bcc, + headers=headers or {}, + attachments=attachments or {}, + ) + return True + except Exception as e: + print(f"Error raised at email send :{e}") + finally: + email_sender.close() + return False diff --git a/docker-compose.yml b/docker-compose.yml index 7cfb2a5..e18be1f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -51,30 +51,38 @@ services: # volumes: # - wag_postgres_commercial_data:/bitnami/postgresql - email_service: - container_name: email_service - build: - context: . - dockerfile: BankServices/EmailService/Dockerfile - networks: - - network_store_services - - parser_service: - container_name: parser_service - build: - context: . - dockerfile: BankServices/ParserService/Dockerfile - networks: - - network_store_services - - writer_service: - container_name: writer_service - build: - context: . - dockerfile: BankServices/WriterService/Dockerfile - networks: - - network_store_services +# email_service: +# container_name: email_service +# build: +# context: . +# dockerfile: BankServices/EmailService/Dockerfile +# networks: +# - network_store_services # +# parser_service: +# container_name: parser_service +# build: +# context: . +# dockerfile: BankServices/ParserService/Dockerfile +# networks: +# - network_store_services +# +# writer_service: +# container_name: writer_service +# build: +# context: . +# dockerfile: BankServices/WriterService/Dockerfile +# networks: +# - network_store_services + + routine_email_service: + container_name: routine_email_service + build: + context: . + dockerfile: BankServices/RoutineEmailService/Dockerfile + networks: + - network_store_services + # sender_service: # container_name: sender_service # build: diff --git a/pyproject.toml b/pyproject.toml index 912bbb8..196e707 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,4 +23,4 @@ dependencies = [ ] [tool.uv.workspace] -members = ["BankServices/EmailService", "BankServices/ParserService", "BankServices/ReaderService", "BankServices/SenderService"] +members = ["BankServices/EmailService", "BankServices/ParserService", "BankServices/ReaderService", "BankServices/SenderService", "BankServices/RoutineEmailService"] diff --git a/uv.lock b/uv.lock index 7a78e65..e476eb2 100644 --- a/uv.lock +++ b/uv.lock @@ -5,7 +5,7 @@ requires-python = ">=3.12" members = [ "emailservice", "parserservice", - "readerservice", + "routineemailservice", "senderservice", "wag-services-and-backend-latest", ] @@ -603,25 +603,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/38/ac33370d784287baa1c3d538978b5e2ea064d4c1b93ffbd12826c190dd10/pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", size = 507930 }, ] -[[package]] -name = "readerservice" -version = "0.1.0" -source = { virtual = "BankServices/ReaderService" } -dependencies = [ - { name = "arrow" }, - { name = "psycopg2-binary" }, - { name = "pymongo" }, - { name = "redbox" }, -] - -[package.metadata] -requires-dist = [ - { name = "arrow", specifier = ">=1.3.0" }, - { name = "psycopg2-binary", specifier = ">=2.9.10" }, - { name = "pymongo", specifier = ">=4.11.3" }, - { name = "redbox", specifier = ">=0.2.1" }, -] - [[package]] name = "redbox" version = "0.2.1" @@ -671,20 +652,55 @@ wheels = [ ] [[package]] -name = "senderservice" +name = "routineemailservice" version = "0.1.0" -source = { virtual = "BankServices/SenderService" } +source = { virtual = "BankServices/RoutineEmailService" } dependencies = [ + { name = "arrow" }, + { name = "fastapi" }, + { name = "jinja2" }, { name = "psycopg2-binary" }, - { name = "pymongo" }, { name = "redbox" }, + { name = "redmail" }, + { name = "sqlalchemy-mixins" }, ] [package.metadata] requires-dist = [ + { name = "arrow", specifier = ">=1.3.0" }, + { name = "fastapi", specifier = ">=0.115.11" }, + { name = "jinja2", specifier = ">=3.1.6" }, + { name = "psycopg2-binary", specifier = ">=2.9.10" }, + { name = "redbox", specifier = ">=0.2.1" }, + { name = "redmail", specifier = ">=0.6.0" }, + { name = "sqlalchemy-mixins", specifier = ">=2.0.5" }, +] + +[[package]] +name = "senderservice" +version = "0.1.0" +source = { virtual = "BankServices/SenderService" } +dependencies = [ + { name = "arrow" }, + { name = "fastapi" }, + { name = "jinja2" }, + { name = "psycopg2-binary" }, + { name = "pymongo" }, + { name = "redbox" }, + { name = "redmail" }, + { name = "sqlalchemy-mixins" }, +] + +[package.metadata] +requires-dist = [ + { name = "arrow", specifier = ">=1.3.0" }, + { name = "fastapi", specifier = ">=0.115.11" }, + { name = "jinja2", specifier = ">=3.1.6" }, { name = "psycopg2-binary", specifier = ">=2.9.10" }, { name = "pymongo", specifier = ">=4.11.3" }, { name = "redbox", specifier = ">=0.2.1" }, + { name = "redmail", specifier = ">=0.6.0" }, + { name = "sqlalchemy-mixins", specifier = ">=2.0.5" }, ] [[package]]