Skip to content

Commit

Permalink
feat: add builtin tools for send email (langgenius#10493)
Browse files Browse the repository at this point in the history
  • Loading branch information
wakaka6 authored and jiangzhijie committed Nov 14, 2024
1 parent ade8e32 commit f4ebb56
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/core/tools/provider/builtin/email/_assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions api/core/tools/provider/builtin/email/email.py
Original file line number Diff line number Diff line change
@@ -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 changes: 83 additions & 0 deletions api/core/tools/provider/builtin/email/email.yaml
Original file line number Diff line number Diff line change
@@ -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 changes: 53 additions & 0 deletions api/core/tools/provider/builtin/email/tools/send.py
Original file line number Diff line number Diff line change
@@ -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 changes: 66 additions & 0 deletions api/core/tools/provider/builtin/email/tools/send_mail.py
Original file line number Diff line number Diff line change
@@ -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 changes: 46 additions & 0 deletions api/core/tools/provider/builtin/email/tools/send_mail.yaml
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit f4ebb56

Please sign in to comment.