mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 11:42:29 +08:00
feat: add builtin tools for send email (#10493)
This commit is contained in:
parent
0867821ae7
commit
9c7edb9242
1
api/core/tools/provider/builtin/email/_assets/icon.svg
Normal file
1
api/core/tools/provider/builtin/email/_assets/icon.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
7
api/core/tools/provider/builtin/email/email.py
Normal file
7
api/core/tools/provider/builtin/email/email.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from core.tools.provider.builtin.email.tools.send_mail import SendMailTool
|
||||||
|
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
|
||||||
|
|
||||||
|
|
||||||
|
class SmtpProvider(BuiltinToolProviderController):
|
||||||
|
def _validate_credentials(self, credentials: dict) -> None:
|
||||||
|
SendMailTool()
|
83
api/core/tools/provider/builtin/email/email.yaml
Normal file
83
api/core/tools/provider/builtin/email/email.yaml
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
identity:
|
||||||
|
author: wakaka6
|
||||||
|
name: email
|
||||||
|
label:
|
||||||
|
en_US: email
|
||||||
|
zh_Hans: 电子邮件
|
||||||
|
description:
|
||||||
|
en_US: send email through smtp protocol
|
||||||
|
zh_Hans: 通过smtp协议发送电子邮件
|
||||||
|
icon: icon.svg
|
||||||
|
tags:
|
||||||
|
- utilities
|
||||||
|
credentials_for_provider:
|
||||||
|
email_account:
|
||||||
|
type: text-input
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: email account
|
||||||
|
zh_Hans: 邮件账号
|
||||||
|
placeholder:
|
||||||
|
en_US: input you email account
|
||||||
|
zh_Hans: 输入你的邮箱账号
|
||||||
|
help:
|
||||||
|
en_US: email account
|
||||||
|
zh_Hans: 邮件账号
|
||||||
|
email_password:
|
||||||
|
type: secret-input
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: email password
|
||||||
|
zh_Hans: 邮件密码
|
||||||
|
placeholder:
|
||||||
|
en_US: email password
|
||||||
|
zh_Hans: 邮件密码
|
||||||
|
help:
|
||||||
|
en_US: email password
|
||||||
|
zh_Hans: 邮件密码
|
||||||
|
smtp_server:
|
||||||
|
type: text-input
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: smtp server
|
||||||
|
zh_Hans: 发信smtp服务器地址
|
||||||
|
placeholder:
|
||||||
|
en_US: smtp server
|
||||||
|
zh_Hans: 发信smtp服务器地址
|
||||||
|
help:
|
||||||
|
en_US: smtp server
|
||||||
|
zh_Hans: 发信smtp服务器地址
|
||||||
|
smtp_port:
|
||||||
|
type: text-input
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: smtp server port
|
||||||
|
zh_Hans: 发信smtp服务器端口
|
||||||
|
placeholder:
|
||||||
|
en_US: smtp server port
|
||||||
|
zh_Hans: 发信smtp服务器端口
|
||||||
|
help:
|
||||||
|
en_US: smtp server port
|
||||||
|
zh_Hans: 发信smtp服务器端口
|
||||||
|
encrypt_method:
|
||||||
|
type: select
|
||||||
|
required: true
|
||||||
|
options:
|
||||||
|
- value: NONE
|
||||||
|
label:
|
||||||
|
en_US: NONE
|
||||||
|
zh_Hans: 无加密
|
||||||
|
- value: SSL
|
||||||
|
label:
|
||||||
|
en_US: SSL
|
||||||
|
zh_Hans: SSL加密
|
||||||
|
- value: TLS
|
||||||
|
label:
|
||||||
|
en_US: START TLS
|
||||||
|
zh_Hans: START TLS加密
|
||||||
|
label:
|
||||||
|
en_US: encrypt method
|
||||||
|
zh_Hans: 加密方式
|
||||||
|
help:
|
||||||
|
en_US: smtp server encrypt method
|
||||||
|
zh_Hans: 发信smtp服务器加密方式
|
53
api/core/tools/provider/builtin/email/tools/send.py
Normal file
53
api/core/tools/provider/builtin/email/tools/send.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import logging
|
||||||
|
import smtplib
|
||||||
|
import ssl
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class SendEmailToolParameters(BaseModel):
|
||||||
|
smtp_server: str
|
||||||
|
smtp_port: int
|
||||||
|
|
||||||
|
email_account: str
|
||||||
|
email_password: str
|
||||||
|
|
||||||
|
sender_to: str
|
||||||
|
subject: str
|
||||||
|
email_content: str
|
||||||
|
encrypt_method: str
|
||||||
|
|
||||||
|
|
||||||
|
def send_mail(parmas: SendEmailToolParameters):
|
||||||
|
timeout = 60
|
||||||
|
msg = MIMEMultipart("alternative")
|
||||||
|
msg["From"] = parmas.email_account
|
||||||
|
msg["To"] = parmas.sender_to
|
||||||
|
msg["Subject"] = parmas.subject
|
||||||
|
msg.attach(MIMEText(parmas.email_content, "plain"))
|
||||||
|
msg.attach(MIMEText(parmas.email_content, "html"))
|
||||||
|
|
||||||
|
ctx = ssl.create_default_context()
|
||||||
|
|
||||||
|
if parmas.encrypt_method.upper() == "SSL":
|
||||||
|
try:
|
||||||
|
with smtplib.SMTP_SSL(parmas.smtp_server, parmas.smtp_port, context=ctx, timeout=timeout) as server:
|
||||||
|
server.login(parmas.email_account, parmas.email_password)
|
||||||
|
server.sendmail(parmas.email_account, parmas.sender_to, msg.as_string())
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception("send email failed: %s", e)
|
||||||
|
return False
|
||||||
|
else: # NONE or TLS
|
||||||
|
try:
|
||||||
|
with smtplib.SMTP(parmas.smtp_server, parmas.smtp_port, timeout=timeout) as server:
|
||||||
|
if parmas.encrypt_method.upper() == "TLS":
|
||||||
|
server.starttls(context=ctx)
|
||||||
|
server.login(parmas.email_account, parmas.email_password)
|
||||||
|
server.sendmail(parmas.email_account, parmas.sender_to, msg.as_string())
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception("send email failed: %s", e)
|
||||||
|
return False
|
66
api/core/tools/provider/builtin/email/tools/send_mail.py
Normal file
66
api/core/tools/provider/builtin/email/tools/send_mail.py
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import re
|
||||||
|
from typing import Any, Union
|
||||||
|
|
||||||
|
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||||
|
from core.tools.provider.builtin.email.tools.send import (
|
||||||
|
SendEmailToolParameters,
|
||||||
|
send_mail,
|
||||||
|
)
|
||||||
|
from core.tools.tool.builtin_tool import BuiltinTool
|
||||||
|
|
||||||
|
|
||||||
|
class SendMailTool(BuiltinTool):
|
||||||
|
def _invoke(
|
||||||
|
self, user_id: str, tool_parameters: dict[str, Any]
|
||||||
|
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
|
||||||
|
"""
|
||||||
|
invoke tools
|
||||||
|
"""
|
||||||
|
sender = self.runtime.credentials.get("email_account", "")
|
||||||
|
email_rgx = re.compile(r"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$")
|
||||||
|
password = self.runtime.credentials.get("email_password", "")
|
||||||
|
smtp_server = self.runtime.credentials.get("smtp_server", "")
|
||||||
|
if not smtp_server:
|
||||||
|
return self.create_text_message("please input smtp server")
|
||||||
|
smtp_port = self.runtime.credentials.get("smtp_port", "")
|
||||||
|
try:
|
||||||
|
smtp_port = int(smtp_port)
|
||||||
|
except ValueError:
|
||||||
|
return self.create_text_message("Invalid parameter smtp_port(should be int)")
|
||||||
|
|
||||||
|
if not sender:
|
||||||
|
return self.create_text_message("please input sender")
|
||||||
|
if not email_rgx.match(sender):
|
||||||
|
return self.create_text_message("Invalid parameter userid, the sender is not a mailbox")
|
||||||
|
|
||||||
|
receiver_email = tool_parameters["send_to"]
|
||||||
|
if not receiver_email:
|
||||||
|
return self.create_text_message("please input receiver email")
|
||||||
|
if not email_rgx.match(receiver_email):
|
||||||
|
return self.create_text_message("Invalid parameter receiver email, the receiver email is not a mailbox")
|
||||||
|
email_content = tool_parameters.get("email_content", "")
|
||||||
|
|
||||||
|
if not email_content:
|
||||||
|
return self.create_text_message("please input email content")
|
||||||
|
|
||||||
|
subject = tool_parameters.get("subject", "")
|
||||||
|
if not subject:
|
||||||
|
return self.create_text_message("please input email subject")
|
||||||
|
|
||||||
|
encrypt_method = self.runtime.credentials.get("encrypt_method", "")
|
||||||
|
if not encrypt_method:
|
||||||
|
return self.create_text_message("please input encrypt method")
|
||||||
|
|
||||||
|
send_email_params = SendEmailToolParameters(
|
||||||
|
smtp_server=smtp_server,
|
||||||
|
smtp_port=smtp_port,
|
||||||
|
email_account=sender,
|
||||||
|
email_password=password,
|
||||||
|
sender_to=receiver_email,
|
||||||
|
subject=subject,
|
||||||
|
email_content=email_content,
|
||||||
|
encrypt_method=encrypt_method,
|
||||||
|
)
|
||||||
|
if send_mail(send_email_params):
|
||||||
|
return self.create_text_message("send email success")
|
||||||
|
return self.create_text_message("send email failed")
|
46
api/core/tools/provider/builtin/email/tools/send_mail.yaml
Normal file
46
api/core/tools/provider/builtin/email/tools/send_mail.yaml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
identity:
|
||||||
|
name: send_mail
|
||||||
|
author: wakaka6
|
||||||
|
label:
|
||||||
|
en_US: send email
|
||||||
|
zh_Hans: 发送邮件
|
||||||
|
icon: icon.svg
|
||||||
|
description:
|
||||||
|
human:
|
||||||
|
en_US: A tool for sending email
|
||||||
|
zh_Hans: 用于发送邮件
|
||||||
|
llm: A tool for sending email
|
||||||
|
parameters:
|
||||||
|
- name: send_to
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: Recipient email account
|
||||||
|
zh_Hans: 收件人邮箱账号
|
||||||
|
human_description:
|
||||||
|
en_US: Recipient email account
|
||||||
|
zh_Hans: 收件人邮箱账号
|
||||||
|
llm_description: Recipient email account
|
||||||
|
form: llm
|
||||||
|
- name: subject
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: email subject
|
||||||
|
zh_Hans: 邮件主题
|
||||||
|
human_description:
|
||||||
|
en_US: email subject
|
||||||
|
zh_Hans: 邮件主题
|
||||||
|
llm_description: email subject
|
||||||
|
form: llm
|
||||||
|
- name: email_content
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: email content
|
||||||
|
zh_Hans: 邮件内容
|
||||||
|
human_description:
|
||||||
|
en_US: email content
|
||||||
|
zh_Hans: 邮件内容
|
||||||
|
llm_description: email content
|
||||||
|
form: llm
|
|
@ -0,0 +1,75 @@
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
from typing import Any, Union
|
||||||
|
|
||||||
|
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||||
|
from core.tools.provider.builtin.email.tools.send import (
|
||||||
|
SendEmailToolParameters,
|
||||||
|
send_mail,
|
||||||
|
)
|
||||||
|
from core.tools.tool.builtin_tool import BuiltinTool
|
||||||
|
|
||||||
|
|
||||||
|
class SendMailTool(BuiltinTool):
|
||||||
|
def _invoke(
|
||||||
|
self, user_id: str, tool_parameters: dict[str, Any]
|
||||||
|
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
|
||||||
|
"""
|
||||||
|
invoke tools
|
||||||
|
"""
|
||||||
|
sender = self.runtime.credentials.get("email_account", "")
|
||||||
|
email_rgx = re.compile(r"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$")
|
||||||
|
password = self.runtime.credentials.get("email_password", "")
|
||||||
|
smtp_server = self.runtime.credentials.get("smtp_server", "")
|
||||||
|
if not smtp_server:
|
||||||
|
return self.create_text_message("please input smtp server")
|
||||||
|
smtp_port = self.runtime.credentials.get("smtp_port", "")
|
||||||
|
try:
|
||||||
|
smtp_port = int(smtp_port)
|
||||||
|
except ValueError:
|
||||||
|
return self.create_text_message("Invalid parameter smtp_port(should be int)")
|
||||||
|
|
||||||
|
if not sender:
|
||||||
|
return self.create_text_message("please input sender")
|
||||||
|
if not email_rgx.match(sender):
|
||||||
|
return self.create_text_message("Invalid parameter userid, the sender is not a mailbox")
|
||||||
|
|
||||||
|
receivers_email = tool_parameters["send_to"]
|
||||||
|
if not receivers_email:
|
||||||
|
return self.create_text_message("please input receiver email")
|
||||||
|
receivers_email = json.loads(receivers_email)
|
||||||
|
for receiver in receivers_email:
|
||||||
|
if not email_rgx.match(receiver):
|
||||||
|
return self.create_text_message(
|
||||||
|
f"Invalid parameter receiver email, the receiver email({receiver}) is not a mailbox"
|
||||||
|
)
|
||||||
|
email_content = tool_parameters.get("email_content", "")
|
||||||
|
|
||||||
|
if not email_content:
|
||||||
|
return self.create_text_message("please input email content")
|
||||||
|
|
||||||
|
subject = tool_parameters.get("subject", "")
|
||||||
|
if not subject:
|
||||||
|
return self.create_text_message("please input email subject")
|
||||||
|
|
||||||
|
encrypt_method = self.runtime.credentials.get("encrypt_method", "")
|
||||||
|
if not encrypt_method:
|
||||||
|
return self.create_text_message("please input encrypt method")
|
||||||
|
|
||||||
|
msg = {}
|
||||||
|
for receiver in receivers_email:
|
||||||
|
send_email_params = SendEmailToolParameters(
|
||||||
|
smtp_server=smtp_server,
|
||||||
|
smtp_port=smtp_port,
|
||||||
|
email_account=sender,
|
||||||
|
email_password=password,
|
||||||
|
sender_to=receiver,
|
||||||
|
subject=subject,
|
||||||
|
email_content=email_content,
|
||||||
|
encrypt_method=encrypt_method,
|
||||||
|
)
|
||||||
|
if send_mail(send_email_params):
|
||||||
|
msg[receiver] = "send email success"
|
||||||
|
else:
|
||||||
|
msg[receiver] = "send email failed"
|
||||||
|
return self.create_text_message(json.dumps(msg))
|
|
@ -0,0 +1,46 @@
|
||||||
|
identity:
|
||||||
|
name: send_mail_batch
|
||||||
|
author: wakaka6
|
||||||
|
label:
|
||||||
|
en_US: send email to multiple recipients
|
||||||
|
zh_Hans: 发送邮件给多个收件人
|
||||||
|
icon: icon.svg
|
||||||
|
description:
|
||||||
|
human:
|
||||||
|
en_US: A tool for sending email to multiple recipients
|
||||||
|
zh_Hans: 用于发送邮件给多个收件人的工具
|
||||||
|
llm: A tool for sending email to multiple recipients
|
||||||
|
parameters:
|
||||||
|
- name: send_to
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: Recipient email account(json list)
|
||||||
|
zh_Hans: 收件人邮箱账号(json list)
|
||||||
|
human_description:
|
||||||
|
en_US: Recipient email account
|
||||||
|
zh_Hans: 收件人邮箱账号
|
||||||
|
llm_description: A list of recipient email account(json format)
|
||||||
|
form: llm
|
||||||
|
- name: subject
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: email subject
|
||||||
|
zh_Hans: 邮件主题
|
||||||
|
human_description:
|
||||||
|
en_US: email subject
|
||||||
|
zh_Hans: 邮件主题
|
||||||
|
llm_description: email subject
|
||||||
|
form: llm
|
||||||
|
- name: email_content
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
label:
|
||||||
|
en_US: email content
|
||||||
|
zh_Hans: 邮件内容
|
||||||
|
human_description:
|
||||||
|
en_US: email content
|
||||||
|
zh_Hans: 邮件内容
|
||||||
|
llm_description: email content
|
||||||
|
form: llm
|
Loading…
Reference in New Issue
Block a user