zoukankan      html  css  js  c++  java
  • 实现发送邮件动态html内容的几种思路

    需求:
         一个B2B系统在注册用户申请买家,申请审批通过,订单创建,申批通过时都需要发送邮件,邮件内容需要包括一些比较正规的格式,而且其中会包含用户信息,订单信息这些动态内容。另外邮件内容以后可能会频繁调整,需要有比较灵活的定制化。

    实现:
        
    了解过这个需求后,大概想到了或找到了几种实现:
          1.通过代码构造邮件内容,对于其中的动态的内容,直接拼凑。优点是最直接,不会涉及其它的技术思考。缺点是需要繁琐的拼接代码,不容易直接看到显示效果,不方便发现问题,对后不调整的话不容易修改。
          2.和上面的方法类似,但是一个文件中只指定好固定的格式,把变化的部分用特定的字符代替,由程序读取这个”模板“文件内容,用具体内容替换模板文件中的指定字符即可。优点是实现比较简单,固定的部分比较容易控制和修改,但是动态读取的内容部分比较难以实现和维护。由于邮件中的内容并不是简单的几个字符,而是说整个订单信息,这其中包括单头和单身列表,而且其中会有比较特殊的格式显示控制。 所以使用这个方法也不合适。
        相关连接:http://www.c-sharpcorner.com/UploadFile/dsdaf/sendEmailTemplate09292006221150PM/sendEmailTemplate.aspx
          3.使用页面来表示需要发送的邮件内容,然后请求这个页面生成的Html直接作为发送内容。在这里可以使用用户控件代替普通的APSX文件,在用户控件的前台,我们直接象显示页面内容那样来显示我们的邮件内容:
         

    隐藏行号 复制代码 MailTemplate.ascx
    1.  <table style="border-bottom: #006699 1px solid; border-left: #006699 1px solid; font-size: 12px;
    2.         border-top: #006699 1px solid; border-right: #006699 1px solid" border="0" cellspacing="0"
    3.         cellpadding="2" width="80%">
    4.         <tbody>
    5.             <tr>
    6.                 <td>
    7.                     订单号: <%=Order.OrderNo%>
    8.                 </td>
    9.                 <td>
    10.                     客户编号:<%=Order.CardCode%>
    11.                 </td>
    12.                 <td>
    13.                     下单日期:<%=Order.CreateDate%>
    14.                 </td>
    15.             </tr>
    16.             <tr>
    17.                 <td>
    18.                     运费:<%=Order.Freight%>
    19.                 <td>
    20.                     交易币种:<%=Order.Currency%>
    21.                 </td>
    22.                 <td>
    23.                   
    24.                 </td>
    25.             </tr>
    26.             <tr>
    27.                 <td colspan="3">
    28.                     &nbsp;
    29.                 </td>
    30.             </tr>
    31.             <tr>
    32.                 <td colspan="3">
    33.                     送货地址:<%=Order.ShipAddress%>
    34.                 </td>
    35.             </tr>
    36.            
    37.              
    38.             <tr>
    39.             <td  colspan="3">
    40.             <font  color="red">具体的交货时将将由我们的客服人员与您联系协商 </font>
    41.             </td>
    42.             </tr>
    43.             <tr>
    44.           
    45.             <tr>
    46.                 <td colspan="3">
    47.                     <br>
    48.                     <table style="font-size: 12px" border="0" cellspacing="5" cellpadding="4" width="100%"
    49.                         align="center">
    50.                         <tbody>
    51.                             <tr>
    52.                                 <td>
    53.                                     <strong>产品编号</strong>
    54.                                 </td>
    55.                                 <td>
    56.                                     <strong>单位</strong>
    57.                                 </td>
    58.                                 <td width="60">
    59.                                     <strong>数量</strong>
    60.                                 </td>
    61.                                 <td width="80">
    62.                                     <strong>单价</strong>
    63.                                 </td>
    64.                             </tr>
    65.                             
    66.                             <%  foreach (SendMailTemplate.OrderItem item in Order.OrderItems)
    67.                                 { %>
    68.                             <tr>
    69.                                 <td>
    70.                                      <%=item.ItemCode%>
    71.                                 </td>
    72.                                 <td>
    73.                                         <%=item.Unit%>   
    74.                                 </td>
    75.                                 <td>
    76.                                         <%=item.Quantity%>  
    77.                                 </td>
    78.                                 <td>
    79.                                        <%=item.BasicPrice%>  
    80.                                 </td>
    81.                                   
    82.                             </tr>
    83.                           <%} %>
    84.                         </tbody>
    85.                     </table>
    86.                 
    87.                 </td>
    88.             </tr>
    89.         </tbody>
    90.     </table>
         这里只列出来代码的一个片段,邮件还包括其它的一些固定的内容,详细的请直接下载源代码查看,其中包括实体类的代码这里也就不再列出来了。在用户控件的后台,我们只需要添加一个公开的属性: 
        
    1:  public Order Order
    2:        {
    3:            get;
    4:            set;
    5:        }

       然后我们需要动态加载这个用户控件,指定属性,再输出成Html属性即可:
     

     1:  Order order = Tools.CreateOrder();
     2:  Control mailTemplate = LoadControl("MailTemplate.ascx");
     3:   
     4:  ((MailTemplate)mailTemplate).Order = order;
     5:  StringBuilder stringBuilder = new StringBuilder();
     6:  StringWriter stringWriter = new StringWriter(stringBuilder);
     7:  HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);
     8:  mailTemplate.RenderControl(htmlTextWriter);
     9:  htmlTextWriter.Close();
    10:   
    11:  //发送邮件
    12:  MailMessage mm = new MailMessage();
    13:  mm.Subject = string.Format("您的订单({0}) -- 订单已经确认", order.OrderNo);
    14:  mm.IsBodyHtml = true;
    15:  mm.To.Add("lonely_7345@hotmail.com");
    16:  mm.Body = stringBuilder.ToString();
    17:  Tools.SendEmail(mm);

      在这里我们也省略发邮件的代码,运行,查看一下收到的邮件,OK.
      screenshot

    使用这种方法应该是比较快捷的,相对于以上来说灵活了不少,格式容易控制,以后修改起来也比较方便。不过就是模板文件和代码文件混在一起。
      
      4.使用模板引擎,比如Nvelocity,StringTemplate。因为之前接触过Nvelocity,所以尝试了使用Nvelocity,具体有关的配置可以参照这个文章  http://www.cnblogs.com/McJeremy/archive/2008/06/25/1229848.html
        Nvelocity的模板文件和上面我们的方法也是相当类似的。
     

     1:  <table style="border-bottom: #006699 1px solid; border-left: #006699 1px solid; font-size: 12px;
     2:      border-top: #006699 1px solid; border-right: #006699 1px solid" border="0" cellspacing="0"
     3:      cellpadding="2" width="80%">
     4:      <tbody>
     5:          <tr>
     6:              <td>
     7:                  订单号:$order.OrderNo
     8:              </td>
     9:              <td>
    10:                  客户编号:$order.CardCode
    11:              </td>
    12:              <td>
    13:                  下单日期:$order.CreateDate
    14:              </td>
    15:          </tr>
    16:          <tr>
    17:              <td>
    18:                  运费:$order.Freight
    19:              </td>
    20:              <td>
    21:                  交易币种:$order.Currency
    22:              </td>
    23:              <td>
    24:                
    25:              </td>
    26:          </tr>
    27:          <tr>
    28:              <td colspan="3">
    29:                  &nbsp;
    30:              </td>
    31:          </tr>
    32:          <tr>
    33:              <td colspan="3">
    34:                  送货地址:$order.ShipAddress
    35:              </td>
    36:          </tr>
    37:         
    38:           
    39:          <tr>
    40:          <td  colspan="3">
    41:          <font  color="red">具体的交货时将将由我们的客服人员与您联系协商 </font>
    42:          </td>
    43:          </tr>
    44:          <tr>
    45:        
    46:          <tr>
    47:              <td colspan="3">
    48:                  <br>
    49:                  <table style="font-size: 12px" border="0" cellspacing="5" cellpadding="4" width="100%"
    50:                      align="center">
    51:                      <tbody>
    52:                          <tr>
    53:                              <td>
    54:                                  <strong>产品编号</strong>
    55:                              </td>
    56:                              <td>
    57:                                  <strong>单位</strong>
    58:                              </td>
    59:                              <td width="60">
    60:                                  <strong>数量</strong>
    61:                              </td>
    62:                              <td width="80">
    63:                                  <strong>单价</strong>
    64:                              </td>
    65:                          </tr>
    66:                          #foreach( $item  in   $order.OrderItems) 
    67:                          <tr>
    68:                              <td>
    69:                                 ${item.ItemCode} 
    70:                              </td>
    71:                              <td>
    72:                                        ${item.Unit} 
    73:                              </td>
    74:                              <td>
    75:                                       ${item.Quantity} 
    76:                              </td>
    77:                              <td>
    78:                                      ${item.BasicPrice} 
    79:                              </td>
    80:                                
    81:                          </tr>
    82:                   #end 
    83:                      </tbody>
    84:                  </table>
    85:              
    86:              </td>
    87:          </tr>
    88:      </tbody>
    89:  </table>

      不同的是,我们的模板文件是单独的一个文件,而我们只需要加载这个模板文件,指定参数就可以了。

     1:  public static VelocityEngine InitVelocity()
     2:        {
     3:            //创建NVelocity引擎的实例对象
     4:            VelocityEngine velocity = new VelocityEngine();
     5:            //初始化该实例对象
     6:            ExtendedProperties props = new ExtendedProperties();
     7:            props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");
     8:            props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, System.Web.HttpContext.Current.Server.MapPath("\\mailTemplate"));
     9:            props.AddProperty(RuntimeConstants.INPUT_ENCODING, "gb2312");
    10:            props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "gb2312");
    11:            velocity.Init(props);
    12:            return velocity;
    13:        }
    14:   
    15:        private  void SendOrderConfirmdEmail()
    16:        {
    17:            VelocityEngine velocity = InitVelocity();
    18:            //从文件中读取模板
    19:            Template temp = velocity.GetTemplate("CreateOrderMail.vm");
    20:   
    21:            Order order = Tools.CreateOrder();
    22:            IContext context = new VelocityContext();
    23:            context.Put("order", order);
    24:            //合并模板
    25:            StringWriter writer = new StringWriter();
    26:            temp.Merge(context, writer);
    27:   
    28:            //发送邮件
    29:            MailMessage mm = new MailMessage();
    30:            mm.Subject = string.Format("您的订单({0}) -- 订单已经确认", order.OrderNo);
    31:            mm.IsBodyHtml = true;
    32:            mm.To.Add("lonely_7345@hotmail.com");
    33:            mm.Body = writer.GetStringBuilder().ToString();
    34:            Tools.SendEmail(mm);
    35:        }

          在这里需要注意的是上面的第8行,这里需要加载的是你的模板文件所在父级物理路径,我把模板文件放在mailTemplate文件夹下面。运行,我们可以看到结果和上面的是一样一样的。这个方法要求对这个模板引擎有些了解,其实还是没有啥难度的。带来了比较大的灵活性,模板文件可以创建一个功能模块,允许用户编辑修改,而不会造成编译错误。

       5.使用通常的XML+Xsl的方式生成html,这也是很容易想到的一个方法。但是由于发送邮件的点实在太多,使用这种方法编写的难度比较大了,而且需要匹配每个属性,不可取。
       6.搜索了一下有没有相关的开源项目,只搜索到了一个Email Template Framework,是通过xml文件来配置发送的选项和邮件的内容,但是看介绍觉得对于比较简单的格式应该能够实现,但是比较复制的夹杂着比较多的html的邮件内容,有可能会遇到问题,另外由于时间问题,应尽量少用比较少见的开源项目,避免遇到不能解决的问题。
    参照:http://www.bitethebullet.co.uk/EmailTemplateFramework/tabid/58/Default.aspx

    结论:
       1.通往一个目的地的途径真的很多,大概了解了以上几种方法之后,最后还是决定使用nvelocity模板的方式来完成这个功能,完成几个点的邮件发送只用了半个小时。当然,应该还有更多的方法,更简单的方法,如果您有不同的思路和想法,请在评论中分享.
       2.往往在研究某个技术的本身,有时会在遇到具体的功能问题时,反而不会把技术和实现联系起来。而只有联系起来才能够使技术产生实用价值。

    代码下载:
        https://files.cnblogs.com/lonely7345/SendMailTemplate.rar

    作者:孤独侠客似水流年
    出处:http://lonely7345.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    row migeration and row chain
    测量sql 解析耗费的时间比例
    Introduction to Oracle Wait Interface notes
    查看 library cache 命中率
    keep buffer cache
    recycle pool
    JAVA annotation入门
    从 08年开始写博客,之前一直在 新浪上写,但是好多朋友都在CSDN上,所以今天也搬家了;
    Linux I2C核心、总线与设备驱动
    从 08年开始写博客,之前一直在 新浪上写,但是好多朋友都在CSDN上,所以今天也搬家了;
  • 原文地址:https://www.cnblogs.com/lonely7345/p/1561212.html
Copyright © 2011-2022 走看看