0
votes

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="[email protected]"/>
    <add key="Abp.Net.Mail.DefaultFromDisplayName" value="Lutfi Kaddoura"/>
  </appSettings>     
</configuration>
2

2 Answers

1
votes

From the documentation on Setting Management:

The ISettingStore interface must be implemented in order to use the setting system. While you can implement it in your own way, it's fully implemented in the Module Zero project. If it's not implemented, settings are read from the application's configuration file (web.config or app.config) but those settings cannot be changed. Scoping will also not work.

To fallback on configuration file, subclass SettingStore and override GetSettingOrNullAsync:

public class MySettingStore : SettingStore
{
    public MySettingStore(
        IRepository<Setting, long> settingRepository,
        IUnitOfWorkManager unitOfWorkManager)
        : base(settingRepository, unitOfWorkManager)
    {
    }

    public override Task<SettingInfo> GetSettingOrNullAsync(int? tenantId, long? userId, string name)
    {
        return base.GetSettingOrNullAsync(tenantId, userId, name)
            ?? DefaultConfigSettingStore.Instance.GetSettingOrNullAsync(tenantId, userId, name);
    }
}

Then replace ISettingStore in your module:

// using Abp.Configuration.Startup;

public override void PreInitialize()
{
    Configuration.ReplaceService<ISettingStore, MySettingStore>(DependencyLifeStyle.Transient);
}
1
votes

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);
}