需求:
     一个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.
 

使用这种方法应该是比较快捷的,相对于以上来说灵活了不少,格式容易控制,以后修改起来也比较方便。不过就是模板文件和代码文件混在一起。
  
  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.往往在研究某个技术的本身,有时会在遇到具体的功能问题时,反而不会把技术和实现联系起来。而只有联系起来才能够使技术产生实用价值。

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

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

分类: .NET
标签: 邮件模板, nvelocity, email tempalte, 用户控件 email, 邮件 html
本文转自孤独侠客博客园博客,原文链接:http://www.cnblogs.com/lonely7345/archive/2009/09/06/1561212.html,如需转载请自行联系原作者

实现发送邮件动态html内容的几种思路相关推荐

  1. js学习-DOM之动态创建元素的三种方式、插入元素、onkeydown与onkeyup两个事件整理...

    动态创建元素的三种方式: 第一种: Document.write(); <body> <input type="button" id="btn" ...

  2. vue动态设置文字布局方式_详解Vue动态添加模板的几种方法

    动态添加模板需要收集原始数据的页面,这个时候我们需要很多原始数据收集模板,下面给大家详解Vue 动态添加模板的几种方法,希望对你学习这方面知识有所帮助. 通常我们会在组件里的 template 属性定 ...

  3. QListWidget动态添加内容,交换两行内容

    文章目录 写在前面 实现界面和第一种添加方式 两种内容动态添加方式 交换两行内容 写在最后及程序下载 写在前面 我们使用QListWidget是想实现单列的列表形式,无论是简单的文本列表形式或是复杂的 ...

  4. 静态链接库(LIB)和动态链接库(DLL),DLL的静态加载和动态加载,两种LIB文件。

    静态链接库(LIB)和动态链接库(DLL),DLL的静态加载和动态加载,两种LIB文件. 一. 静态链接库(LIB,也简称"静态库")与动态链接库(DLL,也简称"动态库 ...

  5. 又拍云张聪:OpenResty 动态流控的几种姿势

    2019 年 1 月 12 日,由又拍云.OpenResty 中国社区主办的 OpenResty × Open Talk 全国巡回沙龙·深圳站圆满结束,又拍云首席架构师张聪在活动上做了< Ope ...

  6. 写一个静态HTML页面,直接写HTML代码和用JS动态生成代码,哪种方式要好

    如果写一个静态HTML页面,直接写HTML代码和用JS动态生成代码,哪种方式要好点?为什么? 不考虑人力因素(手写HTML太费时间排除),请从读取和解析或者其他的角度分析.谢谢 添加评论 分享 按投票 ...

  7. 仿联想商城laravel实战---5、无刷新的增删改查(动态页面更新的三种方式(html))...

    仿联想商城laravel实战---5.无刷新的增删改查(动态页面更新的三种方式(html)) 一.总结 一句话总结: 直接js增加删除修改html 控制器直接返回处理好的页面 用双向绑定插件比如vue ...

  8. CSS 动画相关属性动态实例大全(82种),2023年祝福第二弹(送你一只守护兔)(下),守护兔源代码免费下载

    2023年春节祝福第二弹--送你一只守护兔(下) CSS 动画相关属性动态实例大全(82种).守护兔源代码免费下载 本文目录: 五.CSS3 动画相关属性实例大全 (1).CSS3的动画基本属性 (2 ...

  9. php读取文件内容不全,php读取文件内容的三种方法

    //**************第一种读取方式***************************** 代码如下: header("content-type:text/html;chars ...

  10. python一次性读取整个文件-python逐行读取文件内容的三种方法

    一.使用open打开文件后一定要记得调用文件对象的close()方法.比如可以用try/finally语句来确保最后能关闭文件. 二.需要导入import os 三.下面是逐行读取文件内容的三种方法: ...

最新文章

  1. 格式化时间算前七天php,php 格式化时间 秒前 分钟前 小时前 天前
  2. pytorch 时间序列预测,梯度裁剪
  3. hive中的数据库与mysql中的hive数据库的关系
  4. 牛客题霸 [进制转换] C++题解/答案
  5. 蓝宝石英语怎么读_黑金和蓝宝石
  6. 实验吧-密码学-杯酒人生(特殊凯撒--维吉尼亚密码)(凯撒加解密脚本、维吉尼亚密码加解密脚本)...
  7. c++ 使用正则匹配url
  8. 利用http-server测试vue-cli打包后的项目
  9. Unity3D DoTween插件 的基本用法
  10. 中拉光伏产业合作蓬勃发展前景远大
  11. Ke模拟器kemulator 1.0 绿色中文版
  12. VB脚本:快速入门教程
  13. java常量池存放什么_java常量池存放在哪里
  14. C# 中的Finalize 和Dispose(bool disposing)和 Dispose()
  15. 数据分析神器Alteryx
  16. linux命令-ll之按时间、大小顺序排列显示
  17. 轮椅上的AI博士矣晓沅:9年求学路,我从清华毕业了!
  18. java base是什么文件_JavaBase 面向对象
  19. android原生输入法皮肤,duang_精选布局_触屏皮肤_皮肤布局_百度手机输入法
  20. 英特尔®傲腾™持久内存+MemVerge软硬结合发挥极致性能

热门文章

  1. Atitit.检测文本文件的编码 自动获取文件的中文编码
  2. UIView用户事件响应
  3. cocos3 开篇helloworld
  4. [Codeforces Round #152 (Div. 2)]A. Cupboards
  5. 从输入URL到页面呈现经历了哪些?DOM文档加载的步骤?
  6. Laravel 5.1 文档攻略 —— Eloquent Collection
  7. mysql 中的bool值
  8. putty+Xming使用方法
  9. STM32F207和DM9161A的以太网实现方案
  10. android的listview单项中包含RadioButton,实现RadioButton的单选显示效果