Skip to content

Commit 6fdd0c1

Browse files
committed
feat: add example to send mail
1 parent 2605ae6 commit 6fdd0c1

File tree

11 files changed

+335
-0
lines changed

11 files changed

+335
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ YoMo support multiple LLM providers, like Ollama, Mistral, Llama, Azure OpenAI,
1414
- [node-tool-currency-converter](./node-tool-currency-converter): Currency Calculator by 3rd party API.
1515
- [node-tool-get-utc-time](./node-tool-get-utc-time): Get the UTC time by city name.
1616
- [node-tool-get-ip-and-latency](./node-tool-get-ip-and-latency): Get IP and Latency by give website name like "Nike" and "Amazone" by `ping` command.
17+
- [node-tool-send-mail](./node-tool-send-mail): Send email by `nodemailer` and `maildev`.
1718

1819
### Golang
1920

@@ -22,6 +23,7 @@ YoMo support multiple LLM providers, like Ollama, Mistral, Llama, Azure OpenAI,
2223
- [golang-tool-get-utc-time](./golang-tool-get-utc-time): Get the UTC time by city name.
2324
- [golang-tool-timezone-calculator](./golang-tool-timezone-calculator): Calculate the timezone for a specific time.
2425
- [golang-tool-get-ip-and-latency](./golang-tool-get-ip-and-latency): Get IP and Latency by give website name like "Nike" and "Amazone" by `ping` command.
26+
- [golang-tool-send-mail](./golang-tool-send-mail): Send email by `nodemailer` and `maildev`.
2527

2628
## Self Hosting
2729

golang-tool-send-mail/.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
YOMO_SFN_NAME=my_first_llm_function_tool
2+
YOMO_SFN_ZIPPER="zipper.vivgrid.com:9000"
3+
YOMO_SFN_CREDENTIAL=<your-yomo-sfn-credential>
4+
SMTP_HOST=localhost
5+
SMTP_PORT=1025
6+

golang-tool-send-mail/README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# LLM Function Calling - Send Email
2+
3+
This is a serverless function for sending emails.
4+
5+
## Prerequisites
6+
7+
### 1. Environment Variables
8+
9+
```sh
10+
YOMO_SFN_NAME=my_first_llm_function_tool
11+
YOMO_SFN_ZIPPER=zipper.vivgrid.com:9000
12+
YOMO_SFN_CREDENTIAL=<your-yomo-sfn-credential>
13+
```
14+
15+
You can find other environment variables in the serverless page of [vivgrid dashboard](https://dashboard.vivgrid.com/).
16+
17+
## Development
18+
19+
### 1. Install YoMo CLI
20+
21+
```bash
22+
curl -fsSL https://get.yomo.run | sh
23+
```
24+
25+
For detailed CLI usage, check [Doc: YoMo CLI](https://yomo.run/docs/cli).
26+
27+
### 2. Start Mail Development Server
28+
29+
```bash
30+
docker run -p 1080:1080 -p 1025:1025 maildev/maildev
31+
```
32+
33+
### 3. Add Environment Variables
34+
35+
Add the following environment variables to your `.env` file:
36+
37+
```bash
38+
SMTP_HOST=localhost
39+
SMTP_PORT=1025
40+
41+
```
42+
43+
### 4. Test the Function
44+
45+
You can test the email sending functionality with the following curl command:
46+
47+
```bash
48+
curl --request POST \
49+
--url https://api.vivgrid.com/v1/chat/completions \
50+
--header 'Authorization: Bearer <token>' \
51+
--header 'content-type: application/json' \
52+
--data '{
53+
"model": "gpt-4o",
54+
"messages": [
55+
{
56+
"role": "assistant",
57+
"content": "send an email to [email protected], subject is '\''hello'\'', body is '\''world'\''"
58+
}
59+
]
60+
}'
61+
```
62+
63+
### 4. Connect this Function to Your LLM Bridge
64+
65+
```bash
66+
yomo run app.go -n my_first_llm_function_tool
67+
```
68+
69+
## Web Interface
70+
71+
After starting the mail development server, you can access the web interface at `http://localhost:1080` to view sent emails.

golang-tool-send-mail/app.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log/slog"
6+
"net/smtp"
7+
"os"
8+
9+
"github.com/yomorun/yomo/serverless"
10+
)
11+
12+
// Description describes the functionality of this Function Calling
13+
func Description() string {
14+
return `This function is called when users need to send emails. You need to determine if the user's input contains complete email information (recipient, subject, content).
15+
If the information is incomplete, you should ask for the missing information.`
16+
}
17+
18+
// Parameter defines the required parameters for sending emails
19+
type Parameter struct {
20+
To string `json:"to" jsonschema:"description=Recipient's email address,[email protected]"`
21+
Subject string `json:"subject" jsonschema:"description=Email subject"`
22+
Body string `json:"body" jsonschema:"description=Email content"`
23+
}
24+
25+
func InputSchema() any {
26+
return &Parameter{}
27+
}
28+
29+
// Handler processes the email sending logic
30+
func Handler(ctx serverless.Context) {
31+
var msg Parameter
32+
ctx.ReadLLMArguments(&msg)
33+
34+
// Get email configuration from environment variables
35+
smtpHost := os.Getenv("SMTP_HOST")
36+
smtpPort := os.Getenv("SMTP_PORT")
37+
fromEmail := os.Getenv("FROM_EMAIL")
38+
39+
// Construct email content
40+
emailBody := fmt.Sprintf("Subject: %s\r\n\r\n%s", msg.Subject, msg.Body)
41+
42+
// Send email
43+
err := smtp.SendMail(
44+
smtpHost+":"+smtpPort,
45+
nil,
46+
fromEmail,
47+
[]string{msg.To},
48+
[]byte(emailBody),
49+
)
50+
51+
if err != nil {
52+
slog.Error("Failed to send email", "error", err)
53+
ctx.WriteLLMResult("Failed to send email, please try again later")
54+
return
55+
}
56+
57+
ctx.WriteLLMResult(fmt.Sprintf("Email has been successfully sent to %s", msg.To))
58+
}
59+
60+
// DataTags specifies the data tags to which this serverless function
61+
// subscribes, essential for data reception. Upon receiving data with these
62+
// tags, the Handler function is triggered.
63+
func DataTags() []uint32 {
64+
return []uint32{0x65}
65+
}

golang-tool-send-mail/go.mod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module llm-fn-get-weather
2+
3+
go 1.22.3
4+
5+
require github.com/yomorun/yomo v1.18.11
6+
7+
require (
8+
github.com/caarlos0/env/v6 v6.10.1 // indirect
9+
github.com/lmittmann/tint v1.0.4 // indirect
10+
github.com/sashabaranov/go-openai v1.27.0 // indirect
11+
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
12+
)

golang-tool-send-mail/go.sum

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
2+
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
3+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
4+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc=
6+
github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
7+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
8+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
9+
github.com/sashabaranov/go-openai v1.27.0 h1:L3hO6650YUbKrbGUC6yCjsUluhKZ9h1/jcgbTItI8Mo=
10+
github.com/sashabaranov/go-openai v1.27.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
11+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
12+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
13+
github.com/yomorun/yomo v1.18.11 h1:lWA+YtRnm/ppQKPztoV2XekmCcQVRHJajyYSFu49h+g=
14+
github.com/yomorun/yomo v1.18.11/go.mod h1:aDnZBSmXMCBH/73jnqtUdYvzVDeqGx25Z87y80cOU34=
15+
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
16+
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
17+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
18+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

node-tool-send-mail/.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
YOMO_SFN_NAME=my_first_llm_function_tool
2+
YOMO_SFN_ZIPPER="zipper.vivgrid.com:9000"
3+
YOMO_SFN_CREDENTIAL=<your-yomo-sfn-credential>
4+
SMTP_HOST=localhost
5+
SMTP_PORT=1025
6+

node-tool-send-mail/README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# LLM Function Calling - Send Email
2+
3+
This is a serverless function for sending emails.
4+
5+
## Prerequisites
6+
7+
### 1. Environment Variables
8+
9+
```sh
10+
YOMO_SFN_NAME=my_first_llm_function_tool
11+
YOMO_SFN_ZIPPER=zipper.vivgrid.com:9000
12+
YOMO_SFN_CREDENTIAL=<your-yomo-sfn-credential>
13+
```
14+
15+
You can find other environment variables in the serverless page of [vivgrid dashboard](https://dashboard.vivgrid.com/).
16+
17+
## Development
18+
19+
### 1. Install YoMo CLI
20+
21+
```bash
22+
curl -fsSL https://get.yomo.run | sh
23+
```
24+
25+
For detailed CLI usage, check [Doc: YoMo CLI](https://yomo.run/docs/cli).
26+
27+
### 2. Start Mail Development Server
28+
29+
```bash
30+
docker run -p 1080:1080 -p 1025:1025 maildev/maildev
31+
```
32+
33+
### 3. Add Environment Variables
34+
35+
Add the following environment variables to your `.env` file:
36+
37+
```bash
38+
SMTP_HOST=localhost
39+
SMTP_PORT=1025
40+
41+
```
42+
43+
### 4. Test the Function
44+
45+
You can test the email sending functionality with the following curl command:
46+
47+
```bash
48+
curl --request POST \
49+
--url https://api.vivgrid.com/v1/chat/completions \
50+
--header 'Authorization: Bearer <token>' \
51+
--header 'content-type: application/json' \
52+
--data '{
53+
"model": "gpt-4o",
54+
"messages": [
55+
{
56+
"role": "assistant",
57+
"content": "send an email to [email protected], subject is '\''hello'\'', body is '\''world'\''"
58+
}
59+
]
60+
}'
61+
```
62+
63+
### 4. Connect this Function to Your LLM Bridge
64+
65+
```bash
66+
yomo run app.go -n my_first_llm_function_tool
67+
```
68+
69+
## Web Interface
70+
71+
After starting the mail development server, you can access the web interface at `http://localhost:1080` to view sent emails.

node-tool-send-mail/app.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import * as dotenv from 'dotenv';
2+
import * as nodemailer from 'nodemailer';
3+
4+
dotenv.config();
5+
6+
// Description outlines the functionality for the LLM Function Calling feature
7+
export const description = `This function is called when users need to send emails. You need to determine if the user's input contains complete email information (recipient, subject, content).
8+
If the information is incomplete, you should ask for the missing information.`;
9+
10+
// Define the parameter structure for the LLM Function Calling
11+
interface Argument {
12+
to: string;
13+
subject: string;
14+
body: string;
15+
}
16+
17+
// Tag specifies the data tag that this serverless function
18+
// subscribes to, which is essential for data reception. When data with this
19+
// tag is received, the Handler function will be triggered.
20+
export const tag = 0x65;
21+
22+
async function sendEmail(args: Argument): Promise<string> {
23+
try {
24+
const transporter = nodemailer.createTransport({
25+
host: process.env.SMTP_HOST,
26+
port: parseInt(process.env.SMTP_PORT || '1025'),
27+
secure: false,
28+
});
29+
30+
await transporter.sendMail({
31+
from: process.env.FROM_EMAIL,
32+
to: args.to,
33+
subject: args.subject,
34+
text: args.body,
35+
});
36+
37+
return `Email has been successfully sent to ${args.to}`;
38+
} catch (error) {
39+
console.error('Failed to send email:', error);
40+
return 'Failed to send email, please try again later';
41+
}
42+
}
43+
44+
/**
45+
* Handler orchestrates the core processing logic of this function.
46+
* @param args - LLM Function Calling Arguments.
47+
* @returns The result of the email sending operation.
48+
*/
49+
export async function handler(args: Argument): Promise<string> {
50+
const result = await sendEmail(args);
51+
return result;
52+
}

node-tool-send-mail/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "tool-node-send-mail",
3+
"version": "1.0.0",
4+
"description": "LLM Function Calling - Send Email",
5+
"main": ".wrapper.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"devDependencies": {
12+
"@types/node": "^22.10.1",
13+
"@types/nodemailer": "^6.4.14",
14+
"typescript": "^5.7.2"
15+
},
16+
"dependencies": {
17+
"@yomo/sfn": "^1.0.5",
18+
"dotenv": "^16.4.7",
19+
"nodemailer": "^6.9.12"
20+
}
21+
}

0 commit comments

Comments
 (0)