using BotSharp.Abstraction.Conversations.Settings; using MailKit.Net.Smtp; using MailKit.Security; using MimeKit; namespace BotSharp.Plugin.EmailHandler.Functions; public class HandleEmailSenderFn : IFunctionCallback { public string Name => "util-email-handle_email_sender"; public string Indication => "Handling email send request"; private readonly IServiceProvider _services; private readonly ILogger _logger; private readonly BotSharpOptions _options; private readonly EmailSenderSettings _emailSettings; public HandleEmailSenderFn( IServiceProvider services, ILogger logger, BotSharpOptions options, EmailSenderSettings emailPluginSettings) { _services = services; _logger = logger; _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; var isNeedAttachments = args?.IsNeedAttachemnts ?? false; var bodyBuilder = new BodyBuilder(); try { var mailMessage = new MimeMessage(); mailMessage.From.Add(new MailboxAddress(_emailSettings.Name, _emailSettings.EmailAddress)); mailMessage.To.Add(new MailboxAddress("", recipient)); mailMessage.Subject = subject; bodyBuilder.TextBody = body; if (isNeedAttachments) { var files = await GetConversationFiles(); BuildEmailAttachments(bodyBuilder, files); } mailMessage.Body = bodyBuilder.ToMessageBody(); var response = await SendEmailBySMTP(mailMessage); message.Content = response; _logger.LogWarning($"Email successfully send over to {recipient}. Email Subject: {subject} [{response}]"); return true; } catch (Exception ex) { var msg = $"Failed to send the email. {ex.Message}"; _logger.LogError(ex, $"{msg}"); message.Content = msg; return false; } } private async Task> GetConversationFiles() { var convService = _services.GetRequiredService(); var fileInstruct = _services.GetRequiredService(); var convSettings = _services.GetRequiredService(); var selecteds = await fileInstruct.SelectMessageFiles(convService.ConversationId, options: new() { IsIncludeBotFiles = true, IsAttachFiles = true, MessageLimit = convSettings?.FileSelect?.MessageLimit, Provider = convSettings?.FileSelect?.Provider, Model = convSettings?.FileSelect?.Model, MaxOutputTokens = convSettings?.FileSelect?.MaxOutputTokens, ReasoningEffortLevel = convSettings?.FileSelect?.ReasoningEffortLevel }); return selecteds; } private void BuildEmailAttachments(BodyBuilder builder, IEnumerable files) { if (files.IsNullOrEmpty()) return; var fileStorage = _services.GetRequiredService(); foreach (var file in files) { if (string.IsNullOrEmpty(file.FileStorageUrl)) continue; var fileBinary = fileStorage.GetFileBytes(file.FileStorageUrl); builder.Attachments.Add($"{file.FileName}.{file.FileExtension}", fileBinary.ToArray(), ContentType.Parse(file.ContentType)); Thread.Sleep(100); } } private async Task SendEmailBySMTP(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 ?? "Email sent"; } }