I'm trying to setup MailKit in ASP.NET Boilerplate to send emails, but I keep getting this exception although I have added the settings in the app.config file.
Code to send email:
_emailSender.Send(
to: "*****@gmail.com",
subject: "You have a new task!",
body: $"A new task is assigned for you: <b>Create doFramework</b>",
isBodyHtml: true
);
Exception received:
{Abp.AbpException: Setting value for 'Abp.Net.Mail.DefaultFromAddress' is null or empty! at Abp.Net.Mail.EmailSenderConfiguration.GetNotEmptySettingValue(String name) in D:\Github\aspnetboilerplate\src\Abp\Net\Mail\EmailSenderConfiguration.cs:line 44 at Abp.Net.Mail.EmailSenderBase.NormalizeMail(MailMessage mail) in D:\Github\aspnetboilerplate\src\Abp\Net\Mail\EmailSenderBase.cs:line 96 at Abp.Net.Mail.EmailSenderBase.Send(MailMessage mail, Boolean normalize) in D:\Github\aspnetboilerplate\src\Abp\Net\Mail\EmailSenderBase.cs:line 73 at TaskManagmentApp.Tasks.TaskAppService.GetAll(GetAllTasksInput input) in C:\Users\Dopravo\source\repos\doFramework\SampleProjects\TaskManagmentApp\src\TaskManagmentApp.Application\Services\TaskAppService.cs:line 36 at Castle.Proxies.Invocations.ITaskAppService_GetAll.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at Abp.Domain.Uow.UnitOfWorkInterceptor.PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options) in D:\Github\aspnetboilerplate\src\Abp\Domain\Uow\UnitOfWorkInterceptor.cs:line 68 at Castle.DynamicProxy.AbstractInvocation.Proceed() at Abp.Auditing.AuditingInterceptor.PerformSyncAuditing(IInvocation invocation, AuditInfo auditInfo) in D:\Github\aspnetboilerplate\src\Abp\Auditing\AuditingInterceptor.cs:line 51}
app.config file:
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
<appSettings>
<add key="Abp.Net.Mail.DefaultFromAddress" value="lkaddoura@dopravo.com"/>
<add key="Abp.Net.Mail.DefaultFromDisplayName" value="Lutfi Kaddoura"/>
</appSettings>
</configuration>
I finally was able to read the settings by implementing my own SettingStore that read from the config file. note that the GetAllListAsync call would need to be implemented.
public class MySettingStore : ISettingStore
{
public Task CreateAsync(SettingInfo setting)
{
throw new NotImplementedException();
}
public Task DeleteAsync(SettingInfo setting)
{
throw new NotImplementedException();
}
public Task<List<SettingInfo>> GetAllListAsync(int? tenantId, long? userId)
{
var result = new List<SettingInfo>();
var keys = ConfigurationManager.AppSettings.AllKeys;
foreach (var key in keys)
{
result.Add(new SettingInfo(null, null, key, ConfigurationManager.AppSettings[key]));
}
return Task.FromResult(result);
}
public Task<SettingInfo> GetSettingOrNullAsync(int? tenantId, long? userId, string name)
{
var value = ConfigurationManager.AppSettings[name];
if (value == null)
{
return Task.FromResult<SettingInfo>(null);
}
return Task.FromResult(new SettingInfo(tenantId, userId, name, value));
}
public Task UpdateAsync(SettingInfo setting)
{
throw new NotImplementedException();
}
}
The MySettingStore would need to be replaced in the PreInitalize() of the module.
public override void PreInitialize()
{
Configuration.ReplaceService<ISettingStore, MySettingStore>(DependencyLifeStyle.Transient);
}