65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 SSIS 调用 .Net 程序集:邮件框架

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (3投票s)

2008 年 10 月 22 日

CPOL

3分钟阅读

viewsIcon

50366

downloadIcon

237

本文演示了一个 SSIS 包的使用,该包有助于调用包含邮件组件的 .Net 程序集。

引言

有一个需求,需要自动向大约 25000 个用户发送邮件。在这种情况下,我们需要将详细信息从数据库服务器拉取到安装了 Windows 服务的 Web 服务器来发送邮件。这种方法在性能方面对我们的设计造成了很大的影响。因此,我们将设计转移到数据库服务器。这样就可以减少 Web 服务器的负载。现在将这个功能迁移到数据库服务器带来了一个问题,因为我们的邮件模板内容是 HTML 格式存储在平面文件中的,从 SQL Server 读取这个平面文件是个问题。一种方法是将这些邮件内容保存在数据库表中。但编辑这些邮件内容会涉及大量的测试和审查工作。因此,我们求助于 SSIS (Sql Server Integration services),它调用包含邮件组件的 .net 程序集。SSIS 包调用此类的 notification 方法,该方法反过来从数据库获取用户详细信息,并选择正确的邮件模板将邮件发送给收件人。此包在 SQL Server 2005 的 SQL Server Agent 下作为作业进行计划。这不仅解决了邮件内容管理的问题,还降低了 Web 服务器的负载。到目前为止,这已被证明是我们业务解决方案的一个很好的工作模型。

系统要求

  • SQL Server 2005
  • 已安装 SQL Server Integration 服务组件。
  • SMTP 端口已启用用于发送电子邮件。
  • 邮件框架的特点

  • 邮件内容存储在平面文件中。邮件内容中有一个占位符,将在运行时替换。
  • 该组件在 SQL Server Agent 中作为作业进行计划。
  • 邮件组件可针对生产或测试环境进行配置。为测试环境提供了邮件服务启动/停止机制。
  • 已实现邮件内容日志记录机制。
  • 所有部署都完全在数据库服务器上进行。
  • 物理架构

    State Diagram

    逻辑架构

    State Diagram

    交互/序列图

    State Diagram

    邮件框架的实现

    让我们开始实现邮件组件。

    创建邮件组件

    此静态构造函数从 app.config 文件加载配置设置。由于此程序集在 GAC 中,因此引用其 app.config 存在问题。所以我们提供了物理路径。所有设置信息都存储在通用集合 Dictionary 中。所以需要通过键来获取所需的值。

     static EmailServices() 
            { 
                XmlDocument xmlDocument = new XmlDocument(); 
                xmlDocument.Load("D:/EmailFramework/EmailFramework/EmailFramework/app.config"); 
                XmlNodeList nodeList = xmlDocument.SelectNodes("configuration/appSettings/add"); 
                int index = 0; 
                
                foreach (XmlNode node in nodeList) { 
                    string key = node.Attributes.GetNamedItem("key").Value; 
                    string value = node.Attributes.GetNamedItem("value").Value; 
                    emailSettings.Add(key, value); 
                    index += 1; 
                } 
            } 
    

    这会将邮件内容记录到文本文件中。

    public static void GenerateTraceLog(string content) 
            { 
                System.IO.File.AppendAllText(emailSettings["EmailTraceLogPath"], content); 
            } 
    

    此块通过 smtp 服务器发送邮件。

         public static void SendRegisterNotification(MailContent mailContent, Hashtable templateVars, string templateFileName) 
            { 
                string hostName = null; 
                System.Net.Mail.SmtpClient smtpClient = null; 
                int port = 0; 
                MailMessage mailMessage = new MailMessage(); 
                
                
                try { 
                    hostName = emailSettings["SMTPServerName"]; 
                    if (hostName == null | hostName == string.Empty) { 
                        throw new Exception
    ("Invalid Configuration.
    The configuration could not be found. Please contact support professionals."); 
                    } 
                    port = Convert.ToInt16(emailSettings["PortNumber"]); 
                    
                    if (port == 0) { 
                        port = C_DEFAULT_PORT; 
                    } 
                    
                    GenerateTraceLog("***EMAIL SENDING REPORT STARTED*****"); 
                    
                    // Creating the instance of SMTP Client 
                    smtpClient = new SmtpClient(hostName, port); 
                    smtpClient.EnableSsl = false; 
                                                                   
                    GenerateTraceLog("Mail From :" + mailContent.MailFrom); 
                    if ((Convert.ToInt16(emailSettings["IsProduction"]) == 1)) { 
                        //TO List 
                        if ((mailContent.ToList == null)) { 
                            GenerateTraceLog("Mail To :" + mailContent.MailTo); 
                            mailMessage = new MailMessage(mailContent.MailFrom, mailContent.MailTo); 
                        } 
                        else { 
                            foreach (string recipient in mailContent.ToList) { 
                                
                                GenerateTraceLog("To List :" + recipient); 
                                mailMessage.To.Add(new MailAddress(recipient)); 
                                
                            } 
                            mailMessage.From = new MailAddress(mailContent.MailFrom); 
                        } 
                        //CC List 
                        if ((mailContent.CCList == null)) { 
                            GenerateTraceLog("CC :" + mailContent.MailCC); 
                            if ((string.IsNullOrEmpty(mailContent.MailCC) == false)) { 
                                mailMessage.CC.Add(mailContent.MailCC); 
                            } 
                        } 
                        else { 
                            foreach (string recipient in mailContent.CCList) { 
                                GenerateTraceLog("CC List :" + recipient); 
                                mailMessage.CC.Add(new MailAddress(recipient)); 
                            } 
                        } 
                        //BCC List 
                        if ((mailContent.BCCList == null)) { 
                            GenerateTraceLog("BCC :" + mailContent.MailBCC); 
                            if ((string.IsNullOrEmpty(mailContent.MailBCC) == false)) { 
                                mailMessage.Bcc.Add(mailContent.MailBCC); 
                            } 
                        } 
                        else { 
                            foreach (string recipient in mailContent.BCCList) { 
                                GenerateTraceLog("BCC List :" + recipient); 
                                mailMessage.Bcc.Add(new MailAddress(recipient)); 
                            } 
                        } 
                    } 
                    
                    else { 
                        mailMessage = new MailMessage(mailContent.MailFrom, emailSettings["ToTestID"]); 
                    } 
                    
                    //Subject 
                    GenerateTraceLog("Subject :" + mailContent.Subject); 
                    mailMessage.Subject = mailContent.Subject; 
                    
                    //Attachment 
                    //This internal attachment through system 
                    
                    if ((string.IsNullOrEmpty(mailContent.AttachmentPath) == false)) { 
                        GenerateTraceLog("AttachmentPath :" + mailContent.AttachmentPath); 
                        Attachment mailAttachment = new Attachment(mailContent.AttachmentPath); 
                        mailMessage.Attachments.Add(mailAttachment); 
                    } 
                    
                    Attachment mailAttachmentEntity = null; 
                    
                    if ((mailContent.AttachmentList != null)) { 
                        foreach (string attachmentPath in mailContent.AttachmentList) { 
                            GenerateTraceLog("AttachmentPath :" + attachmentPath); 
                            mailAttachmentEntity = new Attachment(attachmentPath); 
                            mailMessage.Attachments.Add(mailAttachmentEntity); 
                        } 
                    } 
                                    
                    //This is uploaded using external interface. 
                    if ((string.IsNullOrEmpty(mailContent.AttachmentFileName) == false)) { 
                        GenerateTraceLog("External Attachment :" + mailContent.AttachmentFileName); 
                        Attachment mailAttachment = 
    new Attachment(mailContent.AttachmentFileContent, mailContent.AttachmentFileName); 
                        mailMessage.Attachments.Add(mailAttachment); 
                    } 
                    
                    mailMessage.IsBodyHtml = mailContent.IsBodyHTML; 
                    mailMessage.Priority = (MailPriority)mailContent.MessagePriority; 
                    
                    //Parse Email Template 
                    if ((string.IsNullOrEmpty(mailContent.MessageText) == true)) {                     
                        EmailTemplateParser.EmailTemplateParser.Parser parser = null; 
                        parser = 
    new EmailTemplateParser.EmailTemplateParser.Parser(templateFileName, templateVars); 
                        mailMessage.Body = parser.Parse();
                        GenerateTraceLog("Body:" + parser.Parse()); 
                    } 
                    else { 
                        GenerateTraceLog("Body "); 
                        GenerateTraceLog("Body Content :" + mailContent.MessageText); 
                        mailMessage.Body = mailContent.MessageText; 
                    } 
                    
                    if ((Convert.ToString(emailSettings["IsSendMail"]) == "NO"))
     { 
                        GenerateTraceLog("*****EMAIL SENDING REPORT ENDED******"); 
                        mailMessage.Dispose(); 
                        return; 
                    } 
                    else { 
                        smtpClient.Send(mailMessage); 
                        mailMessage.Dispose(); 
                    }                 
                    GenerateTraceLog("*****EMAIL SENDING REPORT ENDED******"); 
                } 
                
                catch (Exception ex) { 
                    GenerateTraceLog(
    ex.Message + "***ERROR SENDING EMAIL THROUGH APPLICATION *****"); 
                } 
            } 
    

    创建 Notification Manager 类

    此类包含所有方法,并且每个方法都指定给 SSIS 的脚本任务包,然后计划为作业。

     public class NotificationManager
        {
            private static IDictionary configSettings = new Dictionary(); 
            static NotificationManager()
            {                 
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load("D:/EmailFramework/EmailFramework/EmailFramework/app.config"); 
                XmlNodeList nodeList = xmlDocument.SelectNodes("configuration/appSettings/add"); 
                int index = 0;
    
                foreach (XmlNode node in nodeList)
                {
                    string key = node.Attributes.GetNamedItem("key").Value;
                    string value = node.Attributes.GetNamedItem("value").Value;
                    configSettings.Add(key, value);
                    index += 1;
                }
            }
            public static void NotifyDueForCreditPayment()
            {
                MailContent mailContent=new MailContent();
                try
                {
                    mailContent.MailTo = "xyz@addd.com";
                    mailContent.MailFrom = "xyz@addd.com";
                    mailContent.Subject = "THIS TEST MAILER";
                    //Body Content 
                    Hashtable templatePlaceHolder = new Hashtable();
                    templatePlaceHolder.Add("To", "xyz");
                    templatePlaceHolder.Add("Credit_Card_Number",104562321373263 );
                    templatePlaceHolder.Add("Due_Date", DateTime.Now);
                    mailContent.IsBodyHTML = true;
                    mailContent.MessagePriority = 1;
                    mailContent.MessageText = string.Empty;
                    EmailServices.SendRegisterNotification
    (mailContent, templatePlaceHolder, configSettings["ET_DueForCreditPayment"]);
                } 
                catch
                {
                }
            }
            public static void NotifyCreditCardExpiry()
            {
    
            }
            public static void NotifyApplicationForAddOnCard()
            {
    
            }
    

    创建 SSIS - Dtsx 包:脚本任务

    打开 Business Intelligence Studio 并创建一个新的 SSIS 包。将脚本任务拖到控制面板屏幕。

    State Diagram

    将脚本任务的 enable 属性设置为 true,然后双击任务块以打开脚本设置对话框。

    State Diagram

    单击 Design Script 打开 vbscript 编码部分。

    注意

  • 将 EmailFramework 和 EmailTemplateParser dll 添加到指定文件夹。
  • 使用 gac utility 将 EmailFramework 和 EmailTemplateParser dll 添加到 GAC。确保为其创建强名称密钥。如果使用 Visual Studio 创建了强名称,请确保在将 dll 注册到 GAC 缓存之前编译并构建它。
  • State Diagram

    现在像截图所示那样为此包添加引用。

    State Diagram

    部署到生产环境

  • 将 app.config 文件放置在代码中提到的位置。
  • 将 Email Template 文件夹放置在 app.config 文件中提到的位置。
  • 双击 Install_Assembly_In_GAC.bat。这将把程序集安装到 GAC。
  • 要测试包,请执行包。设置 SendMail="No" 并检查 EmailLog.txt。
  • ***EMAIL SENDING REPORT STARTED*****Mail 
    From :xyz@xyz.comMail To :zzz@zzzz.comCC :BCC :Subject :THIS TEST MAILERBody:<html>
    <head>
        <style >
    p {
     font-family: Verdana;
    }
    </style >
    </head >
    <body >
        <p >
            <small >*** 
    THIS IS AN AUTOGENERATED MAIL.PLEASE DO NOT REPLY TO THIS MESSAGE ***</small></p>
    <p>
            <small>xyz</small></p>
        <p>
            <small>Credit Card No. 104562321373263 has due date on 10/21/2008 5:08:22 PM .
    Please pay you bill before due date. </small>
    </p>
         
       
        <p>
            <small></small>
            <br>
            <small>Regards </small>
            <br>
            <small>ZCZC Bank</small>
            <br>
    
    

    缺点

    我设计的唯一问题是,app.config 被显式解析,因为它需要保留在 GAC 中。需要一位了解如何配置 GAC 中的程序集及其配置的人员的帮助。

    参考

    邮件模板解析器:作者 Alexandra Email Templates

    结论

    任何更正、批评和建议都非常欢迎。

    © . All rights reserved.