/*
* Copyright (c) 2022 Vaughn Nugent
*
* Library: VNLib
* Package: Transactional Emails
* File: SmtpProvider.cs
*
* SmtpProvider.cs is part of Transactional Emails which is part of the larger
* VNLib collection of libraries and utilities.
*
* Transactional Emails 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.
*
* Transactional Emails 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 Transactional Emails. If not, see http://www.gnu.org/licenses/.
*/
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using MailKit.Net.Smtp;
using MimeKit;
using MimeKit.Text;
namespace Emails.Transactional
{
internal sealed class SmtpProvider
{
private readonly Uri ServerAddress;
private readonly ICredentials ServerCreds;
private readonly TimeSpan Timeout;
public SmtpProvider(Uri ServerAddress, ICredentials ServerCreds, TimeSpan Timeout)
{
this.ServerCreds = ServerCreds;
this.ServerAddress = ServerAddress;
this.Timeout = Timeout;
}
///
/// Opens a connection to the configured SMTP server and sends the specified email
/// request transaction on the server. When the operation completes, the transaction's
/// result property is populated with the result of the operation.
///
/// The transaction data
/// The content of the message to send
/// The format of the body content
/// A task that resolves the status of the operation
public async Task SendAsync(EmailTransaction transaction, string messageBody, TextFormat dataFromat, CancellationToken cancellation)
{
//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));
//Add to email addresses
foreach (KeyValuePair tos in transaction.ToAddresses)
{
message.To.Add(new MailboxAddress(tos.Value, tos.Key));
}
//Add ccs
if (transaction.CcAddresses != null)
{
foreach (KeyValuePair ccs in transaction.CcAddresses)
{
message.Cc.Add(new MailboxAddress(ccs.Value, ccs.Key));
}
}
//Add bccs
if (transaction.BccAddresses != null)
{
foreach (KeyValuePair 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(dataFromat)
{
IsAttachment = false,
Text = messageBody
};
//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);
//Aithenticate
await client.AuthenticateAsync(ServerCreds, cancellation);
//Send the email
string result = await client.SendAsync(message, cancellation);
//Disconnect from the server
await client.DisconnectAsync(true, CancellationToken.None);
//Update the transaction
transaction.Result = result;
return result;
}
}
}