diff options
author | vnugent <public@vaughnnugent.com> | 2023-08-28 21:54:26 -0400 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2023-08-28 21:54:26 -0400 |
commit | b153adbd86e226ad805c2edbb90e4032d386a1b0 (patch) | |
tree | 9d3e5d7f2966c66e0264001cb38c67f74d6cf707 /lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs | |
parent | 964e81b81cdb430ecee8f67a68e3c616b3f339aa (diff) |
Refactor overhaul, data extensions & Resend.com support
Diffstat (limited to 'lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs')
-rw-r--r-- | lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs b/lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs new file mode 100644 index 0000000..78781d4 --- /dev/null +++ b/lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs @@ -0,0 +1,143 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: Emails.Transactional +* File: SmtpProvider.cs +* +* SmtpProvider.cs is part of Emails.Transactional which is part of the larger +* VNLib collection of libraries and utilities. +* +* Emails.Transactional is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published +* by the Free Software Foundation, either version 2 of the License, +* or (at your option) any later version. +* +* Emails.Transactional is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with Emails.Transactional. If not, see http://www.gnu.org/licenses/. +*/ + +using System; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; + +using MailKit.Net.Smtp; + +using MimeKit; +using MimeKit.Text; + +using VNLib.Utils.Extensions; +using VNLib.Plugins; +using VNLib.Plugins.Extensions.Loading; + +namespace Emails.Transactional.Mta +{ + + [ConfigurationName("smtp")] + internal sealed class SmtpProvider : IMailTransferAgent + { + private readonly Uri ServerAddress; + private readonly IAsyncLazy<ICredentials> ServerCreds; + private readonly TimeSpan Timeout; + + public SmtpProvider(PluginBase plugin, IConfigScope config) + { + ServerAddress = config.GetRequiredProperty("server_address", e => new Uri(e.GetString()!)); + Timeout = config["timeout_ms"].GetTimeSpan(TimeParseType.Milliseconds); + + //Get the client id from the config + string clientId = config.GetRequiredProperty("username", e => e.GetString()!); + + //Get the password from the secret store and make it lazy loaded + ServerCreds = plugin.GetSecretAsync("smtp_password").ToLazy<ICredentials>(r => new NetworkCredential(clientId, r.Result.ToString())); + } + + + ///<inheritdoc/> + public async Task<MtaResult> SendEmailAsync(EmailTransaction transaction, IEmailMessageData template, CancellationToken cancellation = default) + { + _ = transaction ?? throw new ArgumentNullException(nameof(transaction)); + + ICredentials creds = await ServerCreds; + + //Configured a new message + using MimeMessage message = new() + { + Date = DateTime.UtcNow, + Subject = transaction.Subject + }; + + //From address is the stored from address + message.From.Add(new MailboxAddress(transaction.FromName, transaction.From)); + + if (transaction.ToAddresses == null) + { + throw new ArgumentException("The transaction must contain at least one To address"); + } + + //Add to email addresses + foreach (KeyValuePair<string, string> tos in transaction.ToAddresses) + { + message.To.Add(new MailboxAddress(tos.Value, tos.Key)); + } + + //Add ccs + if (transaction.CcAddresses != null) + { + foreach (KeyValuePair<string, string> ccs in transaction.CcAddresses) + { + message.Cc.Add(new MailboxAddress(ccs.Value, ccs.Key)); + } + } + + //Add bccs + if (transaction.BccAddresses != null) + { + foreach (KeyValuePair<string, string> bccs in transaction.BccAddresses) + { + message.Bcc.Add(new MailboxAddress(bccs.Value, bccs.Key)); + } + } + + //Use html format since we expect to be reading html templates + using TextPart body = new(TextFormat.Html) + { + IsAttachment = false + }; + + //Set the body text + body.SetText(Encoding.UTF8, template.GetHtml()); + + //Set message body + message.Body = body; + + //Open a new mail client + using SmtpClient client = new(); + + //Set timeout for senting messages + client.Timeout = (int)Timeout.TotalMilliseconds; + + //Connect to server + await client.ConnectAsync(ServerAddress, cancellation); + + //Authenticate + await client.AuthenticateAsync(creds, cancellation); + + //Send the email + transaction.Result = await client.SendAsync(message, cancellation); + + //Disconnect from the server + await client.DisconnectAsync(true, CancellationToken.None); + + return new MtaResult(true, transaction.Result); + } + } +} |