The displayed version of the ABP code is 0.9.0.0. However, later versions have fewer modifications to this part, so it does not affect the porting of later versions.
2. Implementation Process
The Mail operation of the ABP is placed in the Abp. net. mail and Abp. net. mail. in Smtp, the first step is to take a look at the code diagram of the classes and interfaces in this folder (unavailable without permission)
1. Code diagram (heavy)
According to the Code diagram, it can be found that the content of abcfor Mail processing is mainly composed of three parts:
For Files starting with Smtp, it is only an implementation file that is sent by mail in the form of Smtp, and this method will be directly used for processing later.
2. Specific implementation
In specific implementation, I found that the Mail-related classes of the ABP itself are very complete, but the custom implementation is needed in the Mail parameter configuration, so I directly extracted the source code of the ABP for demonstration.
2.1 define etettingnames and AppSettingProvider
The unique string defined in AppSettingNames can be considered as the Key, while the parameter ettingprovider assigns values to the mail parameter corresponding to the Key for later Configuration reading.
The mail function is recommended to be placed in the Core module. After the related provider is completed, add it to CoreModule.Configuration.Settings.Providers.Add<AppSettingProvider>();
To take effect
public static class AppSettings{ /// <summary> /// SMTP related email settings. /// </summary> public static class Smtp { /// <summary> /// Abp.Net.Mail.DefaultFromAddress /// </summary> public const string DefaultAddress = "Trucking.Net.Mail.DefaultFromAddress"; /// <summary> /// Abp.Net.Mail.DefaultFromDisplayName /// </summary> public const string DefaultDisplayName = "Trucking.Net.Mail.DefaultFromDisplayName"; /// <summary> /// Abp.Net.Mail.Smtp.Host /// </summary> public const string Host = "Trucking.Net.Mail.Smtp.Host"; /// <summary> /// Abp.Net.Mail.Smtp.Port /// </summary> public const string Port = "Trucking.Net.Mail.Smtp.Port"; /// <summary> /// Abp.Net.Mail.Smtp.UserName /// </summary> public const string UserName = "Trucking.Net.Mail.Smtp.UserName"; /// <summary> /// Abp.Net.Mail.Smtp.Password /// </summary> public const string Password = "Trucking.Net.Mail.Smtp.Password"; /// <summary> /// Abp.Net.Mail.Smtp.Domain /// </summary> public const string Domain = "Trucking.Net.Mail.Smtp.Domain"; /// <summary> /// Abp.Net.Mail.Smtp.EnableSsl /// </summary> public const string EnableSsl = "Trucking.Net.Mail.Smtp.EnableSsl"; /// <summary> /// Abp.Net.Mail.Smtp.UseDefaultCredentials /// </summary> public const string UseDefaultCredentials = "Trucking.Net.Mail.Smtp.UseDefaultCredentials"; }}public class AppSettingProvider : SettingProvider{ public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context) { return new[] { new SettingDefinition(AppSettings.Smtp.Host, "smtp.gmail.com", L("SmtpHost"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.Port, "587", L("SmtpPort"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.UserName, "myemail@gmail.com", L("Username"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.Password, "mypassword", L("Password"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.Domain, "", L("DomainName"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.EnableSsl, "true", L("UseSSL"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.UseDefaultCredentials, "false", L("UseDefaultCredentials"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.DefaultAddress, "myemail@gmail.com", L("DefaultEmailAddress"), scopes: SettingScopes.Application | SettingScopes.Tenant), new SettingDefinition(AppSettings.Smtp.DefaultDisplayName, "CompanyName", L("DefaultDisplayName"), scopes: SettingScopes.Application | SettingScopes.Tenant) }; } private static LocalizableString L(string name) { return new LocalizableString(name, AbpConsts.LocalizationSourceName); }}
2.2 EmailSenderConfiguration Configuration
As mentioned above, this class is mainly used to read the mail parameter value set in the Custom AppSettingProvider.
IUserEmailSenderConfiguration interface omitted
public class UserEmailSenderConfiguration : TruckingServiceBase, IUserEmailSenderConfiguration, ITransientDependency{ /// <summary> /// Gets a setting value by checking. Throws <see cref="AbpException"/> if it's null or empty. /// </summary> /// <param name="name">Name of the setting</param> /// <returns>Value of the setting</returns> protected string GetNotEmptySettingValue(string name) { var value = SettingManager.GetSettingValue(name); if (value.IsNullOrEmpty()) { throw new AbpException(String.Format("Setting value for '{0}' is null or empty!", name)); } return value; } /// <summary> /// SMTP Host name/IP. /// </summary> public string Host { get { return GetNotEmptySettingValue(AppSettings.Smtp.Host); } } /// <summary> /// SMTP Port. /// </summary> public int Port { get { return SettingManager.GetSettingValue<int>(AppSettings.Smtp.Port); } } /// <summary> /// User name to login to SMTP server. /// </summary> public string UserName { get { return GetNotEmptySettingValue(AppSettings.Smtp.UserName); } } /// <summary> /// Password to login to SMTP server. /// </summary> public string Password { get { return GetNotEmptySettingValue(AppSettings.Smtp.Password); } } /// <summary> /// Domain name to login to SMTP server. /// </summary> public string Domain { get { return SettingManager.GetSettingValue(AppSettings.Smtp.Domain); } } /// <summary> /// Is SSL enabled? /// </summary> public bool EnableSsl { get { return SettingManager.GetSettingValue<bool>(AppSettings.Smtp.EnableSsl); } } /// <summary> /// Use default credentials? /// </summary> public bool UseDefaultCredentials { get { return SettingManager.GetSettingValue<bool>(AppSettings.Smtp.UseDefaultCredentials); } } public string DefaultAddress { get { return GetNotEmptySettingValue(AppSettings.Smtp.DefaultAddress); } } public string DefaultDisplayName { get { return SettingManager.GetSettingValue(AppSettings.Smtp.DefaultDisplayName); } }}
2.3 SmtpEmailSender implementation (Smtp implements mail sending)
The UserSmtpEmailSender class is the true Mail operation class. It injects the IUserEmailSenderConfiguration interface to read related Mail parameters, such as Host, UserName, and Password, and then calls. NET Mail to send emails.
IUserSmtpEmailSender interface omitted
public class UserSmtpEmailSender : IUserSmtpEmailSender, ITransientDependency{ private readonly IUserEmailSenderConfiguration _configuration; public UserSmtpEmailSender(IUserEmailSenderConfiguration configuration) { _configuration = configuration; } public async Task SendAsync(string to, string subject, string body, bool isBodyHtml = true) { await SendAsync(_configuration.DefaultAddress, to, subject, body, isBodyHtml); } public void Send(string to, string subject, string body, bool isBodyHtml = true) { Send(_configuration.DefaultAddress, to, subject, body, isBodyHtml); } public async Task SendAsync(string from, string to, string subject, string body, bool isBodyHtml = true) { await SendAsync(new MailMessage(from, to, subject, body) {IsBodyHtml = isBodyHtml}); } public void Send(string from, string to, string subject, string body, bool isBodyHtml = true) { Send(new MailMessage(from, to, subject, body) {IsBodyHtml = isBodyHtml}); } public async Task SendAsync(MailMessage mail, bool normalize = true) { if (normalize) NormalizeMail(mail); await SendEmailAsync(mail); } public void Send(MailMessage mail, bool normalize = true) { if (normalize) NormalizeMail(mail); SendEmail(mail); } public SmtpClient BuildClient() { var host = _configuration.Host; var port = _configuration.Port; var smtpClient = new SmtpClient(host, port); try { if (_configuration.EnableSsl) smtpClient.EnableSsl = true; if (_configuration.UseDefaultCredentials) { smtpClient.UseDefaultCredentials = true; } else { smtpClient.UseDefaultCredentials = false; var userName = _configuration.UserName; if (!userName.IsNullOrEmpty()) { var password = _configuration.Password; var domain = _configuration.Domain; smtpClient.Credentials = !domain.IsNullOrEmpty() ? new NetworkCredential(userName, password, domain) : new NetworkCredential(userName, password); } } return smtpClient; } catch { smtpClient.Dispose(); throw; } } /// <summary> /// Normalizes given email. /// Fills <see cref="MailMessage.From" /> if it's not filled before. /// Sets encodings to UTF8 if they are not set before. /// </summary> /// <param name="mail">Mail to be normalized</param> protected virtual void NormalizeMail(MailMessage mail) { if ((mail.From == null) || mail.From.Address.IsNullOrEmpty()) mail.From = new MailAddress( _configuration.DefaultAddress, _configuration.DefaultDisplayName, Encoding.UTF8 ); if (mail.HeadersEncoding == null) mail.HeadersEncoding = Encoding.UTF8; if (mail.SubjectEncoding == null) mail.SubjectEncoding = Encoding.UTF8; if (mail.BodyEncoding == null) mail.BodyEncoding = Encoding.UTF8; } protected async Task SendEmailAsync(MailMessage mail) { using (var smtpClient = BuildClient()) { await smtpClient.SendMailAsync(mail); } } protected void SendEmail(MailMessage mail) { using (var smtpClient = BuildClient()) { smtpClient.Send(mail); } }}
Then we only need to call SendAsync of the EmailSender and fill in the corresponding parameters, which is valid for test. If you want to change the mail component, you only need to implement the corresponding UserLibraryEmailSerder.
So far, we have extracted a separate email function from the ABC and explained it. In fact, you only need to spend some time to manually strip the code diagram. Why is the implementation of a Simple Mail function so complicated in the ABC? Every programmer has the answer from every programmer. Continue to learn.