diff --git a/api/controllers/inner_api/__init__.py b/api/controllers/inner_api/__init__.py index 9f124736a9..831f766261 100644 --- a/api/controllers/inner_api/__init__.py +++ b/api/controllers/inner_api/__init__.py @@ -6,3 +6,4 @@ bp = Blueprint("inner_api", __name__, url_prefix="/inner/api") api = ExternalApi(bp) from .workspace import workspace +import mail diff --git a/api/controllers/inner_api/mail.py b/api/controllers/inner_api/mail.py new file mode 100644 index 0000000000..44ad4b6b00 --- /dev/null +++ b/api/controllers/inner_api/mail.py @@ -0,0 +1,25 @@ +from flask_restful import Resource # type: ignore +from flask_restful import reqparse + +from controllers.console.wraps import setup_required +from controllers.inner_api import api +from controllers.inner_api.wraps import inner_api_only +from services.enterprise.mail_service import DifyMail, EnterpriseMailService + + +class EnterpriseMail(Resource): + @setup_required + @inner_api_only + def post(self): + parser = reqparse.RequestParser() + parser.add_argument("to", type=str, required=True) + parser.add_argument("subject", type=str, required=True) + parser.add_argument("body", type=str, required=True) + parser.add_argument("substitutions", type=dict, required=False) + args = parser.parse_args() + + EnterpriseMailService.send_mail(DifyMail(**args)) + return {"message": "success"}, 200 + + +api.add_resource(EnterpriseMail, "/enterprise/mail") diff --git a/api/services/enterprise/mail_service.py b/api/services/enterprise/mail_service.py new file mode 100644 index 0000000000..24b22008a1 --- /dev/null +++ b/api/services/enterprise/mail_service.py @@ -0,0 +1,26 @@ + +from typing import Dict, List + +from pydantic import BaseModel + +from tasks.mail_enterprise_task import send_enterprise_email_task + + +class DifyMail(BaseModel): + to: List[str] + subject: str + body: str + substitutions: Dict[str, str] = {} + + +class EnterpriseMailService: + + @classmethod + def send_mail(cls, mail: DifyMail): + + send_enterprise_email_task.delay( + to=mail.to, + subject=mail.subject, + body=mail.body, + substitutions=mail.substitutions + ) diff --git a/api/tasks/mail_enterprise_task.py b/api/tasks/mail_enterprise_task.py new file mode 100644 index 0000000000..67475185db --- /dev/null +++ b/api/tasks/mail_enterprise_task.py @@ -0,0 +1,37 @@ +import logging +import time + +import click +from celery import shared_task # type: ignore +from flask import render_template_string + +from extensions.ext_mail import mail + + +@shared_task(queue="mail") +def send_enterprise_email_task(to, subject, body, substitutions): + if not mail.is_inited(): + return + + logging.info( + click.style("Start enterprise mail to {} with subject {}".format(to, subject), fg="green") + ) + start_at = time.perf_counter() + + try: + html_content = render_template_string(body, **substitutions) + + if isinstance(to, list): + for t in to: + mail.send(to=t, subject=subject, html=html_content) + else: + mail.send(to=to, subject=subject, html=html_content) + + end_at = time.perf_counter() + logging.info( + click.style( + "Send enterprise mail to {} succeeded: latency: {}".format(to, end_at - start_at), fg="green" + ) + ) + except Exception: + logging.exception("Send enterprise mail to {} failed".format(to))