FluentEmail
FluentEmail copied to clipboard
Cannot resolve scoped service 'FluentEmail.Core.Interfaces.ISender' from root provider.
I have .NET Core 2.1.2 application with IHostedService for sending email notifications. I register an email sending stuff:
public class NotificationsFactory
{
public static void Register(IServiceCollection services, IAppSettings appSettings)
{
var client = new SmtpClient
{
Host = appSettings.EmailServerHost,
Port = appSettings.EmailServerPort,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(appSettings.EmailUser, appSettings.EmailPassword)
};
services
.AddFluentEmail(appSettings.EmailFrom)
.AddSmtpSender(client);
services.AddSingleton<IEmailNotificationProvider, EmailNotificationProvider>();
}
}
then inject IFluentEmailFactory in my EmailNotificationProvider
public class EmailNotificationProvider : IEmailNotificationProvider
{
private readonly IFluentEmailFactory _emailFactory;
public EmailNotificationProvider(IFluentEmailFactory emailFactory)
{
_emailFactory = emailFactory;
}
public async Task<bool> SendAsync(IOrder order)
{
try
{
var body = "Test body";
await _emailFactory.Create()
.To(order.Company?.Email, "User")
.Subject($"New Order #{order.OrderId}")
.Body(body, true)
.SetFrom("[email protected]", "Service")
.SendAsync();
return true;
}
catch (Exception e)
{
return false;
}
}
}
but get an error "Cannot resolve scoped service 'FluentEmail.Core.Interfaces.ISender' from root provider." when creating new FluentEmail from factory.
What am I doing wrong?
Fixed by removing .AddSmtpSender(client)
add adding services.AddSingleton<ISender>(x => new SmtpSender(client));
Is it a correct solution?
Fixed by removing
.AddSmtpSender(client)
add addingservices.AddSingleton<ISender>(x => new SmtpSender(client));
Is it a correct solution?
Get this error too, and fixed by this method. However I think this should be a bug in AddSmtpSender() method.
#172
I've the same error in
services.AddMailGunSender(mailgunApiDomain.Value, mailgunApiKey.Value);
and
services.AddSingleton<ISender>(x => new MailgunSender(mailgunApiDomain.Value, mailgunApiKey.Value));
did not solved my problem.
The problem is that IFluentEmail
and IFluentEmailFactory
cannot be injected in the constructor because when you use the provided AddFluentEmail()
helper it creates the services as transient services instead of singleton services. Only singleton services can be injected through the constructor.
You can either manually add the service as a singleton (as mentioned above) or you can use the built methods and manually create a scope using the automatically injected IServiceProvider
and explicitly request a dependency injection inside the created scope:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceProvider _serviceProvider;
public Worker(ILogger<Worker> logger, IServiceProvider serviceProvider)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var scope = _serviceProvider.CreateScope())
{
var response = await scope.ServiceProvider.GetRequiredService<IFluentEmail>()
.To("[email protected]")
.Subject(DateTime.Now.ToLongTimeString())
.Body("test")
.SendAsync(stoppingToken);
}
}
}
After 5 years since this was reported, i am facing this issue in .Net 8 project by the below lines of code usage from my backgroundService template app.
var smtpServer = configuration.GetSection("EmailSettings:Host").Value;
int.TryParse(configuration.GetSection("EmailSettings:Port").Value, out int smtpPort);
var mailFrom = configuration.GetSection("EmailSettings:From").Value;
var smtpUser = configuration.GetSection("EmailSettings:SmtpUsername").Value;
var smtpPwd = configuration.GetSection("EmailSettings:SmtpSecret").Value;
bool.TryParse(configuration.GetSection("EmailSettings:UseSslTls").Value, out bool useSslTls);
var smtpClient = new SmtpClientOptions()
{
Server = smtpServer,
Port = smtpPort,
UseSsl = useSslTls,
RequiresAuthentication = true,
User = smtpUser,
Password = smtpPwd,
SocketOptions = useSslTls ? MailKit.Security.SecureSocketOptions.StartTls : MailKit.Security.SecureSocketOptions.Auto
};
services
.AddFluentEmail(mailFrom)
.AddMailKitSender(smtpClient);
While the above comment from @belidzs has a suggestion to use scope within the usage or other solutions, but i'd expect the popular library should have a fix for this, isnt it?