aboutsummaryrefslogtreecommitdiff
path: root/lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-08-28 21:54:26 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-08-28 21:54:26 -0400
commitb153adbd86e226ad805c2edbb90e4032d386a1b0 (patch)
tree9d3e5d7f2966c66e0264001cb38c67f74d6cf707 /lib/Emails.Transactional.Plugin/src/Mta/SmtpProvider.cs
parent964e81b81cdb430ecee8f67a68e3c616b3f339aa (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.cs143
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);
+ }
+ }
+}