From 3a2c8ccc4fde65866f2832dc3e2680f2541f6177 Mon Sep 17 00:00:00 2001 From: 103048 <103048@MJ0AJ7XO-LNPC> Date: Wed, 10 Jul 2024 14:06:34 -0500 Subject: [PATCH 1/3] Initial commit for Email handler utility --- .../Email/Settings/EmailPluginSettings.cs | 12 +++ .../BotSharp.Plugin.EmailHandler.csproj | 35 +++++++++ .../EmailHandlerPlugin.cs | 33 ++++++++ .../Enums/Utility.cs | 13 ++++ .../Functions/HandleEmailRequestFn.cs | 75 +++++++++++++++++++ .../Hooks/EmailHandlerHook.cs | 64 ++++++++++++++++ .../Hooks/EmailHandlerUtilityHook.cs | 18 +++++ .../LlmContexts/LlmContextIn.cs | 20 +++++ .../BotSharp.Plugin.EmailHandler/Using.cs | 19 +++++ .../functions/handle_email_request.json | 22 ++++++ .../templates/handle_email_request.fn.liquid | 1 + 11 files changed, 312 insertions(+) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/LlmContexts/LlmContextIn.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/Using.cs create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/functions/handle_email_request.json create mode 100644 src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/templates/handle_email_request.fn.liquid diff --git a/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs new file mode 100644 index 000000000..4eb08e0d1 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs @@ -0,0 +1,12 @@ +namespace BotSharp.Abstraction.Email.Settings +{ + public class EmailPluginSettings + { + public string EmailAddress { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string Username { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public string SMTPServer { get; set; } = string.Empty; + public int SMTPPort { get; set; } + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj b/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj new file mode 100644 index 000000000..64f724701 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj @@ -0,0 +1,35 @@ + + + + $(TargetFramework) + enable + $(LangVersion) + $(BotSharpVersion) + $(GeneratePackageOnBuild) + $(GenerateDocumentationFile) + $(SolutionDir)packages + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs new file mode 100644 index 000000000..444464fbd --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs @@ -0,0 +1,33 @@ +using BotSharp.Abstraction.Agents; +using BotSharp.Abstraction.Email.Settings; +using BotSharp.Abstraction.Settings; +using BotSharp.Plugin.EmailHandler.Hooks; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BotSharp.Plugin.EmailHandler +{ + public class EmailHandlerPlugin : IBotSharpPlugin + { + public string Id => "a8e217de-e413-47a8-bbf1-af9207392a63"; + public string Name => "Email Handler"; + public string Description => "Empower agent to handle sending out emails"; + public string IconUrl => "https://cdn-icons-png.freepik.com/512/6711/6711567.png"; + + public void RegisterDI(IServiceCollection services, IConfiguration config) + { + services.AddScoped(provider => + { + var settingService = provider.GetRequiredService(); + return settingService.Bind("EmailPlugin"); + }); + + services.AddScoped(); + services.AddScoped(); + } + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs new file mode 100644 index 000000000..7fc65728e --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BotSharp.Plugin.EmailHandler.Enums +{ + public class Utility + { + public const string EmailHandler = "email-handler"; + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs new file mode 100644 index 000000000..60edabf82 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs @@ -0,0 +1,75 @@ +using BotSharp.Abstraction.Email.Settings; +using BotSharp.Plugin.EmailHandler.LlmContexts; +using MailKit.Net.Smtp; +using MailKit.Security; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using MimeKit; +using System.Net.Http; + +namespace BotSharp.Plugin.EmailHandler.Functions +{ + public class HandleEmailRequestFn : IFunctionCallback + { + public string Name => "handle_email_request"; + public string Indication => "Handling email request"; + + private readonly IServiceProvider _services; + private readonly ILogger _logger; + private readonly IHttpClientFactory _httpClientFactory; + private readonly IHttpContextAccessor _context; + private readonly BotSharpOptions _options; + private readonly EmailPluginSettings _emailSettings; + + public HandleEmailRequestFn(IServiceProvider services, + ILogger logger, + IHttpClientFactory httpClientFactory, + IHttpContextAccessor context, + BotSharpOptions options, + EmailPluginSettings emailPluginSettings) + { + _services = services; + _logger = logger; + _httpClientFactory = httpClientFactory; + _context = context; + _options = options; + _emailSettings = emailPluginSettings; + } + public async Task Execute(RoleDialogModel message) + { + var args = JsonSerializer.Deserialize(message.FunctionArgs, _options.JsonSerializerOptions); + var recipient = args?.ToAddress; + var body = args?.Content; + var subject = args?.Subject; + + try + { + var mailMessage = new MimeMessage(); + mailMessage.From.Add(new MailboxAddress(_emailSettings.Name, _emailSettings.EmailAddress)); + mailMessage.To.Add(new MailboxAddress("", recipient)); + mailMessage.Subject = subject; + mailMessage.Body = new TextPart("plain") + { + Text = body + }; + + using (var smtpClient = new SmtpClient()) + { + smtpClient.Connect(_emailSettings.SMTPServer, _emailSettings.SMTPPort, SecureSocketOptions.StartTls); + smtpClient.Authenticate(_emailSettings.EmailAddress, _emailSettings.Password); + smtpClient.Send(mailMessage); + smtpClient.Disconnect(true); + } + message.Content = $"Email successfully send over to {recipient}. Email Subject: {subject}"; + return true; + } + catch (Exception ex) + { + var msg = $"Failed to send the email. {ex.Message}"; + _logger.LogWarning($"{msg}\n(Error: {ex.Message})"); + message.Content = msg; + return false; + } + } + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs new file mode 100644 index 000000000..dfa60a68f --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs @@ -0,0 +1,64 @@ +using BotSharp.Abstraction.Agents; +using BotSharp.Abstraction.Agents.Settings; +using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Repositories; +using BotSharp.Plugin.EmailHandler.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BotSharp.Plugin.EmailHandler.Hooks +{ + public class EmailHandlerHook : AgentHookBase + { + private static string UTILITY_ASSISTANT = Guid.Empty.ToString(); + private static string FUNCTION_NAME = "handle_email_request"; + + public override string SelfId => string.Empty; + + public EmailHandlerHook(IServiceProvider services, AgentSettings settings) + : base(services, settings) + { + } + public override void OnAgentLoaded(Agent agent) + { + var conv = _services.GetRequiredService(); + var isConvMode = conv.IsConversationMode(); + var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(Utility.EmailHandler); + + if (isConvMode && isEnabled) + { + var (prompt, fn) = GetPromptAndFunction(); + if (fn != null) + { + if (!string.IsNullOrWhiteSpace(prompt)) + { + agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n"; + } + + if (agent.Functions == null) + { + agent.Functions = new List { fn }; + } + else + { + agent.Functions.Add(fn); + } + } + } + + base.OnAgentLoaded(agent); + } + + private (string, FunctionDef?) GetPromptAndFunction() + { + var db = _services.GetRequiredService(); + var agent = db.GetAgent(UTILITY_ASSISTANT); + var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{FUNCTION_NAME}.fn"))?.Content ?? string.Empty; + var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(FUNCTION_NAME)); + return (prompt, loadAttachmentFn); + } + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs new file mode 100644 index 000000000..26d82ab09 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs @@ -0,0 +1,18 @@ +using BotSharp.Abstraction.Agents; +using BotSharp.Plugin.EmailHandler.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BotSharp.Plugin.EmailHandler.Hooks +{ + public class EmailHandlerUtilityHook : IAgentUtilityHook + { + public void AddUtilities(List utilities) + { + utilities.Add(Utility.EmailHandler); + } + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/LlmContexts/LlmContextIn.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/LlmContexts/LlmContextIn.cs new file mode 100644 index 000000000..a5231c963 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/LlmContexts/LlmContextIn.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace BotSharp.Plugin.EmailHandler.LlmContexts +{ + public class LlmContextIn + { + [JsonPropertyName("to_address")] + public string? ToAddress { get; set; } + + [JsonPropertyName("email_content")] + public string? Content { get; set; } + [JsonPropertyName("subject")] + public string? Subject { get; set; } + } +} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Using.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Using.cs new file mode 100644 index 000000000..4344b4305 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Using.cs @@ -0,0 +1,19 @@ +global using System; +global using System.Collections.Generic; +global using System.Text; +global using BotSharp.Abstraction.Conversations; +global using BotSharp.Abstraction.Plugins; +global using System.Text.Json; +global using BotSharp.Abstraction.Conversations.Models; +global using System.Threading.Tasks; +global using BotSharp.Abstraction.Functions; +global using BotSharp.Abstraction.Agents.Models; +global using BotSharp.Abstraction.Templating; +global using Microsoft.Extensions.DependencyInjection; +global using System.Linq; +global using BotSharp.Abstraction.Utilities; +global using BotSharp.Abstraction.Messaging; +global using BotSharp.Abstraction.Messaging.Models.RichContent; +global using BotSharp.Abstraction.Options; +global using BotSharp.Abstraction.Http.Settings; +global using BotSharp.Abstraction.Messaging.Enums; \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/functions/handle_email_request.json b/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/functions/handle_email_request.json new file mode 100644 index 000000000..e59a2150f --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/functions/handle_email_request.json @@ -0,0 +1,22 @@ +{ + "name": "handle_email_request", + "description": "If the user requests to send an email, you need to capture the email content and the recipient email address. If the user explicitly enter email subject use the same if not intelligently capture the email subject from the content. Then call this function to send out email.", + "parameters": { + "type": "object", + "properties": { + "to_address": { + "type": "string", + "description": "The email address to which the email should be sent to. It needs to be a valid email address in the correct string format." + }, + "email_content": { + "type": "string", + "description": "The content of the email which needs to be send over. It can be plain string or a raw html." + }, + "subject": { + "type": "string", + "description": "The subject of the email which needs to be send over." + } + }, + "required": [ "to_address", "email_content", "subject" ] + } +} \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/templates/handle_email_request.fn.liquid b/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/templates/handle_email_request.fn.liquid new file mode 100644 index 000000000..01163ab5f --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/templates/handle_email_request.fn.liquid @@ -0,0 +1 @@ +Please call handle_email_request if user wants to send out an email. \ No newline at end of file From 73ba204c061b64abe371d9545f0c1ad44fcdfde3 Mon Sep 17 00:00:00 2001 From: 103048 <103048@MJ0AJ7XO-LNPC> Date: Wed, 10 Jul 2024 14:14:38 -0500 Subject: [PATCH 2/3] Make the send email using SMTP as async --- .../Functions/HandleEmailRequestFn.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs index 60edabf82..12c24e3a5 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs @@ -52,14 +52,7 @@ public async Task Execute(RoleDialogModel message) { Text = body }; - - using (var smtpClient = new SmtpClient()) - { - smtpClient.Connect(_emailSettings.SMTPServer, _emailSettings.SMTPPort, SecureSocketOptions.StartTls); - smtpClient.Authenticate(_emailSettings.EmailAddress, _emailSettings.Password); - smtpClient.Send(mailMessage); - smtpClient.Disconnect(true); - } + await HandleSendEmailBySMTP(mailMessage); message.Content = $"Email successfully send over to {recipient}. Email Subject: {subject}"; return true; } @@ -71,5 +64,15 @@ public async Task Execute(RoleDialogModel message) return false; } } + public async Task HandleSendEmailBySMTP(MimeMessage mailMessage) + { + using (var smtpClient = new SmtpClient()) + { + await smtpClient.ConnectAsync(_emailSettings.SMTPServer, _emailSettings.SMTPPort, SecureSocketOptions.StartTls); + await smtpClient.AuthenticateAsync(_emailSettings.EmailAddress, _emailSettings.Password); + await smtpClient.SendAsync(mailMessage); + smtpClient.Disconnect(true); + } + } } } From 149de9a62d08cdade78342de177c784504925648 Mon Sep 17 00:00:00 2001 From: 103048 <103048@MJ0AJ7XO-LNPC> Date: Thu, 11 Jul 2024 11:02:14 -0500 Subject: [PATCH 3/3] Code improvement based on feedback. --- .../Email/Settings/EmailHandlerSettings.cs | 11 ++ .../Email/Settings/EmailPluginSettings.cs | 12 -- .../BotSharp.Plugin.EmailHandler.csproj | 8 +- .../EmailHandlerPlugin.cs | 2 +- .../Functions/HandleEmailRequestFn.cs | 118 +++++++++--------- .../Hooks/EmailHandlerHook.cs | 79 ++++++------ .../functions/handle_email_request.json | 0 .../templates/handle_email_request.fn.liquid | 0 8 files changed, 114 insertions(+), 116 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailHandlerSettings.cs delete mode 100644 src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs rename src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/{00000000-0000-0000-0000-000000000000 => 6745151e-6d46-4a02-8de4-1c4f21c7da95}/functions/handle_email_request.json (100%) rename src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/{00000000-0000-0000-0000-000000000000 => 6745151e-6d46-4a02-8de4-1c4f21c7da95}/templates/handle_email_request.fn.liquid (100%) diff --git a/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailHandlerSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailHandlerSettings.cs new file mode 100644 index 000000000..e51972a8d --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailHandlerSettings.cs @@ -0,0 +1,11 @@ +namespace BotSharp.Abstraction.Email.Settings; + +public class EmailHandlerSettings +{ + public string EmailAddress { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string Username { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public string SMTPServer { get; set; } = string.Empty; + public int SMTPPort { get; set; } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs deleted file mode 100644 index 4eb08e0d1..000000000 --- a/src/Infrastructure/BotSharp.Abstraction/Email/Settings/EmailPluginSettings.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace BotSharp.Abstraction.Email.Settings -{ - public class EmailPluginSettings - { - public string EmailAddress { get; set; } = string.Empty; - public string Name { get; set; } = string.Empty; - public string Username { get; set; } = string.Empty; - public string Password { get; set; } = string.Empty; - public string SMTPServer { get; set; } = string.Empty; - public int SMTPPort { get; set; } - } -} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj b/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj index 64f724701..f5995e96d 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/BotSharp.Plugin.EmailHandler.csproj @@ -11,15 +11,15 @@ - - + + - + PreserveNewest - + PreserveNewest diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs index 444464fbd..ed472fc5e 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/EmailHandlerPlugin.cs @@ -23,7 +23,7 @@ public void RegisterDI(IServiceCollection services, IConfiguration config) services.AddScoped(provider => { var settingService = provider.GetRequiredService(); - return settingService.Bind("EmailPlugin"); + return settingService.Bind("EmailHandler"); }); services.AddScoped(); diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs index 12c24e3a5..731e338b2 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Functions/HandleEmailRequestFn.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Email.Settings; using BotSharp.Plugin.EmailHandler.LlmContexts; +using MailKit; using MailKit.Net.Smtp; using MailKit.Security; using Microsoft.AspNetCore.Http; @@ -7,72 +8,71 @@ using MimeKit; using System.Net.Http; -namespace BotSharp.Plugin.EmailHandler.Functions +namespace BotSharp.Plugin.EmailHandler.Functions; + +public class HandleEmailRequestFn : IFunctionCallback { - public class HandleEmailRequestFn : IFunctionCallback - { - public string Name => "handle_email_request"; - public string Indication => "Handling email request"; + public string Name => "handle_email_request"; + public string Indication => "Handling email request"; - private readonly IServiceProvider _services; - private readonly ILogger _logger; - private readonly IHttpClientFactory _httpClientFactory; - private readonly IHttpContextAccessor _context; - private readonly BotSharpOptions _options; - private readonly EmailPluginSettings _emailSettings; + private readonly IServiceProvider _services; + private readonly ILogger _logger; + private readonly IHttpClientFactory _httpClientFactory; + private readonly IHttpContextAccessor _context; + private readonly BotSharpOptions _options; + private readonly EmailHandlerSettings _emailSettings; - public HandleEmailRequestFn(IServiceProvider services, - ILogger logger, - IHttpClientFactory httpClientFactory, - IHttpContextAccessor context, - BotSharpOptions options, - EmailPluginSettings emailPluginSettings) - { - _services = services; - _logger = logger; - _httpClientFactory = httpClientFactory; - _context = context; - _options = options; - _emailSettings = emailPluginSettings; - } - public async Task Execute(RoleDialogModel message) - { - var args = JsonSerializer.Deserialize(message.FunctionArgs, _options.JsonSerializerOptions); - var recipient = args?.ToAddress; - var body = args?.Content; - var subject = args?.Subject; + public HandleEmailRequestFn(IServiceProvider services, + ILogger logger, + IHttpClientFactory httpClientFactory, + IHttpContextAccessor context, + BotSharpOptions options, + EmailHandlerSettings emailPluginSettings) + { + _services = services; + _logger = logger; + _httpClientFactory = httpClientFactory; + _context = context; + _options = options; + _emailSettings = emailPluginSettings; + } + public async Task Execute(RoleDialogModel message) + { + var args = JsonSerializer.Deserialize(message.FunctionArgs, _options.JsonSerializerOptions); + var recipient = args?.ToAddress; + var body = args?.Content; + var subject = args?.Subject; - try - { - var mailMessage = new MimeMessage(); - mailMessage.From.Add(new MailboxAddress(_emailSettings.Name, _emailSettings.EmailAddress)); - mailMessage.To.Add(new MailboxAddress("", recipient)); - mailMessage.Subject = subject; - mailMessage.Body = new TextPart("plain") - { - Text = body - }; - await HandleSendEmailBySMTP(mailMessage); - message.Content = $"Email successfully send over to {recipient}. Email Subject: {subject}"; - return true; - } - catch (Exception ex) + try + { + var mailMessage = new MimeMessage(); + mailMessage.From.Add(new MailboxAddress(_emailSettings.Name, _emailSettings.EmailAddress)); + mailMessage.To.Add(new MailboxAddress("", recipient)); + mailMessage.Subject = subject; + mailMessage.Body = new TextPart("plain") { - var msg = $"Failed to send the email. {ex.Message}"; - _logger.LogWarning($"{msg}\n(Error: {ex.Message})"); - message.Content = msg; - return false; - } + Text = body + }; + var response = await HandleSendEmailBySMTP(mailMessage); + _logger.LogWarning($"Email successfully send over to {recipient}. Email Subject: {subject} [{response}]"); + message.Content = response; + return true; } - public async Task HandleSendEmailBySMTP(MimeMessage mailMessage) + catch (Exception ex) { - using (var smtpClient = new SmtpClient()) - { - await smtpClient.ConnectAsync(_emailSettings.SMTPServer, _emailSettings.SMTPPort, SecureSocketOptions.StartTls); - await smtpClient.AuthenticateAsync(_emailSettings.EmailAddress, _emailSettings.Password); - await smtpClient.SendAsync(mailMessage); - smtpClient.Disconnect(true); - } + var msg = $"Failed to send the email. {ex.Message}"; + _logger.LogError($"{msg}\n(Error: {ex.Message})"); + message.Content = msg; + return false; } } + + public async Task HandleSendEmailBySMTP(MimeMessage mailMessage) + { + using var smtpClient = new SmtpClient(); + await smtpClient.ConnectAsync(_emailSettings.SMTPServer, _emailSettings.SMTPPort, SecureSocketOptions.StartTls); + await smtpClient.AuthenticateAsync(_emailSettings.EmailAddress, _emailSettings.Password); + var response = await smtpClient.SendAsync(mailMessage); + return response; + } } diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs index dfa60a68f..41c97eba5 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Agents; +using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Settings; using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Repositories; @@ -9,56 +10,54 @@ using System.Text; using System.Threading.Tasks; -namespace BotSharp.Plugin.EmailHandler.Hooks +namespace BotSharp.Plugin.EmailHandler.Hooks; + +public class EmailHandlerHook : AgentHookBase { - public class EmailHandlerHook : AgentHookBase - { - private static string UTILITY_ASSISTANT = Guid.Empty.ToString(); - private static string FUNCTION_NAME = "handle_email_request"; + private static string FUNCTION_NAME = "handle_email_request"; - public override string SelfId => string.Empty; + public override string SelfId => string.Empty; - public EmailHandlerHook(IServiceProvider services, AgentSettings settings) - : base(services, settings) - { - } - public override void OnAgentLoaded(Agent agent) - { - var conv = _services.GetRequiredService(); - var isConvMode = conv.IsConversationMode(); - var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(Utility.EmailHandler); + public EmailHandlerHook(IServiceProvider services, AgentSettings settings) + : base(services, settings) + { + } + public override void OnAgentLoaded(Agent agent) + { + var conv = _services.GetRequiredService(); + var isConvMode = conv.IsConversationMode(); + var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(Utility.EmailHandler); - if (isConvMode && isEnabled) + if (isConvMode && isEnabled) + { + var (prompt, fn) = GetPromptAndFunction(); + if (fn != null) { - var (prompt, fn) = GetPromptAndFunction(); - if (fn != null) + if (!string.IsNullOrWhiteSpace(prompt)) { - if (!string.IsNullOrWhiteSpace(prompt)) - { - agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n"; - } + agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n"; + } - if (agent.Functions == null) - { - agent.Functions = new List { fn }; - } - else - { - agent.Functions.Add(fn); - } + if (agent.Functions == null) + { + agent.Functions = new List { fn }; + } + else + { + agent.Functions.Add(fn); } } - - base.OnAgentLoaded(agent); } - private (string, FunctionDef?) GetPromptAndFunction() - { - var db = _services.GetRequiredService(); - var agent = db.GetAgent(UTILITY_ASSISTANT); - var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{FUNCTION_NAME}.fn"))?.Content ?? string.Empty; - var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(FUNCTION_NAME)); - return (prompt, loadAttachmentFn); - } + base.OnAgentLoaded(agent); + } + + private (string, FunctionDef?) GetPromptAndFunction() + { + var db = _services.GetRequiredService(); + var agent = db.GetAgent(BuiltInAgentId.UtilityAssistant); + var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{FUNCTION_NAME}.fn"))?.Content ?? string.Empty; + var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(FUNCTION_NAME)); + return (prompt, loadAttachmentFn); } } diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/functions/handle_email_request.json b/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/handle_email_request.json similarity index 100% rename from src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/functions/handle_email_request.json rename to src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/handle_email_request.json diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/templates/handle_email_request.fn.liquid b/src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/handle_email_request.fn.liquid similarity index 100% rename from src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/00000000-0000-0000-0000-000000000000/templates/handle_email_request.fn.liquid rename to src/Plugins/BotSharp.Plugin.EmailHandler/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/handle_email_request.fn.liquid