xml地图|网站地图|网站标签 [设为首页] [加入收藏]
结合ABP源码实现邮件发送功能,从零开始系列
分类:编程

在上一篇中我们一起学习了R语言的数据结构第一部分:向量、数组和矩阵,这次我们开始学习R语言的数据结构第二部分:数据框、因子和列表。

直接上代码:

 

一、数据框

    class Program
    {
        static void Main(string[] args)
        {
            StudentName student1 = new StudentName("Craig", "Playstead");

            //对象初始值设定必须先访问默认的实例构造函数
            //使用对象初始值设定项初始化对象
            StudentName student2 = new StudentName
            {
                FirstName = "Craig",
                LastName = "Playstead"
            };
            StudentName student3 = new StudentName
            {
                ID = 183
            };
            StudentName student4 = new StudentName
            {
                FirstName = "Craig",
                LastName = "Playstead",
                ID = 116
            };
            Console.WriteLine(student1.ToString());
            Console.WriteLine(student2.ToString());
            Console.WriteLine(student3.ToString());
            Console.WriteLine(student4.ToString());
            Console.WriteLine();

            //使用集合初始值设定项初始化字典
            Dictionary<int, StudentName> students = new Dictionary<int, StudentName>()
            {
                {111,new StudentName {FirstName="Sachin",LastName ="Karnik",ID =211 } },
                {112, new StudentName {FirstName ="Dina",LastName ="Salimzianova",ID =317 } },
                {113, new StudentName {FirstName ="Andy",LastName ="Ruth",ID=198 } }

            };

            //字典的使用举例
            //foreach (KeyValuePair<int, StudentName> s in students)
            //{
            //    Console.WriteLine(s.Value .FirstName +"  "+s.Value .LastName +"  "+s.Value .ID );
            //}

            Dictionary<int, StudentName>.KeyCollection keys = students.Keys;
            foreach (int s in keys )
            {
                Console.WriteLine(students[s].ToString());
            }
            Console.ReadKey();
        }
    }
    public class StudentName
    {
        //如果这是默认构造函数是private,那么对象初始值设定将会报错
        public StudentName ()
        {
            FirstName = "Lily";
        }
        public StudentName (string first,string last)
        {
            FirstName = first;
            LastName = last;
        }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int ID { get; set; }
        public override string ToString()
        {
            return FirstName + "  " +LastName +"  "+ ID;
        }
    }
  • 1. 前言
  • 2. 实现过程
    • 1. 代码图(重)
    • 2.具体实现
      • 2.1 定义AppSettingNames及AppSettingProvider
      • 2.2 EmailSenderConfiguration配置
      • 2.3 SmtpEmailSender实现(Smtp实现邮件发送)

类似于二维数组,但不同的列可以有不同的数据类型(每一列内的数据类型应当一致)。创建数据框使用的关键字是data.frame,用法是:

  

1. 前言

最近pm临时提出了多种邮件验证操作的需求,因为一时间也没有找到好的邮件收发组件,也抱着研究ABP的心态,就花了几小时时间探究了一下ABP中关于Email的处理和操作。其实邮件操作大多大同小异,这次只是希望介绍一下ABP中实现功能的代码结构而已,以下是具体过程

演示的ABP代码版本为0.9.0.0,不过后面版本对于这部分的修改较少,所以完全不影响之后版本的移植使用

 

    data.frame(..., row.names = NULL, check.rows = FALSE,

 

2. 实现过程

ABP的Mail操作放在了Abp.Net.Mail和Abp.Net.Mail.Smtp中,第一步先让我们直接看看这个文件夹下类及接口的代码图(未经允许不可使用)

 

                     check.names = TRUE, fix.empty.names = TRUE,

1. 代码图(重)

图片 1

根据代码图可以发现ABP对于Mail处理主要由三部分组成

  • 第一部分是通过继承SettingProvider的EmailSettingProvider来对Mail相关参数进行设置(其中EmailSettingNames定义相关字符串)
  • 第二部分是以IEmailSenderConfiguration接口为基派生出的对SettingProvider设置的邮件参数进行读取和传输的相关操作类
  • 第三部分是以IEmailSender接口为基派生出的Mail发送操作相关类

至于Smtp开头的文件,则是以Smtp形式进行邮件发送的一种实现文件而已,后文也将直接使用该种方式进行处理

 

                     stringsAsFactors = default.stringsAsFactors())

2.具体实现

在具体的实现上,我发现ABP本身的Mail相关类已经十分完整,只是在邮件参数的配置上需要采取自定义的实现,所以我直接抽取了ABP的源码来进行演示

 

例如一个简单的学生成绩表如下:

2.1 定义AppSettingNames及AppSettingProvider

AppSettingNames中定义相关的唯一字符串,大家可以认为是Key,而AppSettingProvider中则是将Key对应的邮件参数赋值,供之后的Configuration读取

邮件功能推荐放在Core模块中,完成相关的provider后在CoreModule加入Configuration.Settings.Providers.Add<AppSettingProvider>();即可生效

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.2 EmailSenderConfiguration配置

这个类的作用如上面提到的那样,主要是读取自定义的AppSettingProvider中设置的邮件参数值

IUserEmailSenderConfiguration接口略

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实现(Smtp实现邮件发送)

UserSmtpEmailSender类才是真正的对Mail操作类,它通过注入IUserEmailSenderConfiguration接口,读取相关的Mail参数,如Host,UserName,Password等,然后再调用.NET的Mail发送邮件。

IUserSmtpEmailSender接口略

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

 

之后我们只需要再调用该EmailSender的SendAsync,填入对应的参数,亲测有效。如果之后要更换邮件组件,则只需要实现对应的UserLibraryEmailSerder即可。

至此,我们便将ABP中单独的一个邮件功能抽离了出来并做了相关解释,其实只要花点功夫,自己手动剥离代码图也可以理解了。至于一个简单的邮件功能为什么在ABP中要实现得如此复杂,每个程序员有每个程序员的答案,还是继续学习吧

本文由澳门新葡亰手机版发布于编程,转载请注明出处:结合ABP源码实现邮件发送功能,从零开始系列

上一篇:函数使用,python_控制台输出带颜色的文字方法 下一篇:七夕福利,准备工作
猜你喜欢
热门排行
精彩图文