I like the answer from @KeithS but I would like to add some updates with ConfigureServices
, .NET Core dependency injection and MailKit.Net.Smtp
.
https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
Given the class below:
public class MailService
{
private readonly SmtpSettings _settings;
private readonly Func<ISmtpClient> _smtpClientFactory;
public MailService(SmtpSettings settings, Func<ISmtpClient> smtpClientFactory)
{
_settings = settings;
_smtpClientFactory = smtpClientFactory;
}
public async Task SendEmailAsync(string to, string subject, MimeEntity body, CancellationToken cancellationToken = default)
{
var message = new MimeMessage();
message.From.Add(MailboxAddress.Parse(_settings.UserName));
message.To.Add(MailboxAddress.Parse(to));
message.Subject = subject;
message.Body = body;
using (var smtpClient = _smtpClientFactory())
{
await smtpClient.ConnectAsync(_settings.Server, _settings.Port, SecureSocketOptions.StartTls, cancellationToken);
await smtpClient.AuthenticateAsync(_settings.UserName, _settings.Password, cancellationToken);
await smtpClient.SendAsync(message, cancellationToken);
await smtpClient.DisconnectAsync(true, cancellationToken);
}
}
}
It can be added like this to ConfigureServices(IServiceCollection services)
:
services.AddTransient<ISmtpClient, SmtpClient>();
services.AddSingleton(provider =>
new Func<ISmtpClient>(() => provider.GetService<ISmtpClient>()));
Complete Program.cs
example for Azure Function:
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureAppConfiguration((hostContext, builder) =>
{
if (hostContext.HostingEnvironment.IsDevelopment())
{
builder.AddJsonFile("local.settings.json");
//This will override any values added to local.settings.json - We will however follow the recommended approach for keeping secrets in dev
//https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#register-the-user-secrets-configuration-source
//builder.AddJsonFile("secret.settings.json");
builder.AddUserSecrets<Program>();
}
})
.ConfigureServices((hostContext, services) =>
{
var connectionString = hostContext.Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
connectionString,
sqlServerOptions => sqlServerOptions.CommandTimeout(600)));
services.AddHttpClient();
var configuration = hostContext.Configuration;
var smtpSettings = new SmtpSettings();
configuration.Bind("Smtp", smtpSettings);
services.AddSingleton(smtpSettings);
services.AddTransient<ISmtpClient, SmtpClient>();
services.AddSingleton(provider =>
new Func<ISmtpClient>(() => provider.GetService<ISmtpClient>()));
services.AddTransient<MailService>();
})
.Build();
host.Run();
}
Source to get Func<T>
registered and resolved:
https://mcmap.net/q/498660/-how-to-use-func-lt-t-gt-in-built-in-dependency-injection