您现在的位置: 365建站网 > 365文章 > 实现发送邮件动态html内容的几种思路

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

文章来源:365jz.com     点击数:692    更新时间:2009-09-16 11:50   参与评论

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

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

隐藏行号 复制代码 MailTemplate.ascx
  1. </>code

    1. <table style="border-bottom: #006699 1px solid; border-left: #006699 1px solid; font-size: 12px;
  2. </>code

    1. border-top: #006699 1px solid; border-right: #006699 1px solid" border="0" cellspacing="0"
  3. </>code

    1. cellpadding="2" width="80%">
  4. </>code

    1. <tbody>
  5. </>code

    1. <tr>
  6. </>code

    1. <td>
  7. </>code

    1. 订单号: <%=Order.OrderNo%>
  8. </>code

    1. </td>
  9. </>code

    1. <td>
  10. </>code

    1. 客户编号:<%=Order.CardCode%>
  11. </>code

    1. </td>
  12. </>code

    1. <td>
  13. </>code

    1. 下单日期:<%=Order.CreateDate%>
  14. </>code

    1. </td>
  15. </>code

    1. </tr>
  16. </>code

    1. <tr>
  17. </>code

    1. <td>
  18. </>code

    1. 运费:<%=Order.Freight%>
  19. </>code

    1. <td>
  20. </>code

    1. 交易币种:<%=Order.Currency%>
  21. </>code

    1. </td>
  22. </>code

    1. <td>
  23. </>code

  24. </>code

    1. </td>
  25. </>code

    1. </tr>
  26. </>code

    1. <tr>
  27. </>code

    1. <td colspan="3">
  28. </>code

    1. &nbsp;
  29. </>code

    1. </td>
  30. </>code

    1. </tr>
  31. </>code

    1. <tr>
  32. </>code

    1. <td colspan="3">
  33. </>code

    1. 送货地址:<%=Order.ShipAddress%>
  34. </>code

    1. </td>
  35. </>code

    1. </tr>
  36. </>code

  37. </>code

  38. </>code

    1. <tr>
  39. </>code

    1. <td colspan="3">
  40. </>code

    1. <font color="red">具体的交货时将将由我们的客服人员与您联系协商 </font>
  41. </>code

    1. </td>
  42. </>code

    1. </tr>
  43. </>code

    1. <tr>
  44. </>code

  45. </>code

    1. <tr>
  46. </>code

    1. <td colspan="3">
  47. </>code

    1. <br>
  48. </>code

    1. <table style="font-size: 12px" border="0" cellspacing="5" cellpadding="4" width="100%"
  49. </>code

    1. align="center">
  50. </>code

    1. <tbody>
  51. </>code

    1. <tr>
  52. </>code

    1. <td>
  53. </>code

    1. <strong>产品编号</strong>
  54. </>code

    1. </td>
  55. </>code

    1. <td>
  56. </>code

    1. <strong>单位</strong>
  57. </>code

    1. </td>
  58. </>code

    1. <td width="60">
  59. </>code

    1. <strong>数量</strong>
  60. </>code

    1. </td>
  61. </>code

    1. <td width="80">
  62. </>code

    1. <strong>单价</strong>
  63. </>code

    1. </td>
  64. </>code

    1. </tr>
  65. </>code

  66. </>code

    1. <% foreach (SendMailTemplate.OrderItem item in Order.OrderItems)
  67. </>code

    1. { %>
  68. </>code

    1. <tr>
  69. </>code

    1. <td>
  70. </>code

    1. <%=item.ItemCode%>
  71. </>code

    1. </td>
  72. </>code

    1. <td>
  73. </>code

    1. <%=item.Unit%>
  74. </>code

    1. </td>
  75. </>code

    1. <td>
  76. </>code

    1. <%=item.Quantity%>
  77. </>code

    1. </td>
  78. </>code

    1. <td>
  79. </>code

    1. <%=item.BasicPrice%>
  80. </>code

    1. </td>
  81. </>code

  82. </>code

    1. </tr>
  83. </>code

    1. <%} %>
  84. </>code

    1. </tbody>
  85. </>code

    1. </table>
  86. </>code

  87. </>code

    1. </td>
  88. </>code

    1. </tr>
  89. </>code

    1. </tbody>
  90. </>code

    1. </table>
     这里只列出来代码的一个片段,邮件还包括其它的一些固定的内容,详细的请直接下载源代码查看,其中包括实体类的代码这里也就不再列出来了。在用户控件的后台,我们只需要添加一个公开的属性: 
    

</>code

  1. 1: public Order Order

</>code

  1. 2: {

</>code

  1. 3: get;

</>code

  1. 4: set;

</>code

  1. 5: }

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

</>code

  1. 1: Order order = Tools.CreateOrder();

</>code

  1. 2: Control mailTemplate = LoadControl("MailTemplate.ascx");

</>code

  1. 3:  

</>code

  1. 4: ((MailTemplate)mailTemplate).Order = order;

</>code

  1. 5: StringBuilder stringBuilder = new StringBuilder();

</>code

  1. 6: StringWriter stringWriter = new StringWriter(stringBuilder);

</>code

  1. 7: HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);

</>code

  1. 8: mailTemplate.RenderControl(htmlTextWriter);

</>code

  1. 9: htmlTextWriter.Close();

</>code

  1. 10:  

</>code

  1. 11: //发送邮件

</>code

  1. 12: MailMessage mm = new MailMessage();

</>code

  1. 13: mm.Subject = string.Format("您的订单({0}) -- 订单已经确认", order.OrderNo);

</>code

  1. 14: mm.IsBodyHtml = true;

</>code

  1. 15: mm.To.Add("lonely_7345@hotmail.com");

</>code

  1. 16: mm.Body = stringBuilder.ToString();

</>code

  1. 17: Tools.SendEmail(mm);

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

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

</>code

  1. 1: <table style="border-bottom: #006699 1px solid; border-left: #006699 1px solid; font-size: 12px;

</>code

  1. 2: border-top: #006699 1px solid; border-right: #006699 1px solid" border="0" cellspacing="0"

</>code

  1. 3: cellpadding="2" width="80%">

</>code

  1. 4: <tbody>

</>code

  1. 5: <tr>

</>code

  1. 6: <td>

</>code

  1. 7: 订单号:$order.OrderNo

</>code

  1. 8: </td>

</>code

  1. 9: <td>

</>code

  1. 10: 客户编号:$order.CardCode

</>code

  1. 11: </td>

</>code

  1. 12: <td>

</>code

  1. 13: 下单日期:$order.CreateDate

</>code

  1. 14: </td>

</>code

  1. 15: </tr>

</>code

  1. 16: <tr>

</>code

  1. 17: <td>

</>code

  1. 18: 运费:$order.Freight

</>code

  1. 19: </td>

</>code

  1. 20: <td>

</>code

  1. 21: 交易币种:$order.Currency

</>code

  1. 22: </td>

</>code

  1. 23: <td>

</>code

  1. 24:

</>code

  1. 25: </td>

</>code

  1. 26: </tr>

</>code

  1. 27: <tr>

</>code

  1. 28: <td colspan="3">

</>code

  1. 29: &nbsp;

</>code

  1. 30: </td>

</>code

  1. 31: </tr>

</>code

  1. 32: <tr>

</>code

  1. 33: <td colspan="3">

</>code

  1. 34: 送货地址:$order.ShipAddress

</>code

  1. 35: </td>

</>code

  1. 36: </tr>

</>code

  1. 37:

</>code

  1. 38:

</>code

  1. 39: <tr>

</>code

  1. 40: <td colspan="3">

</>code

  1. 41: <font color="red">具体的交货时将将由我们的客服人员与您联系协商 </font>

</>code

  1. 42: </td>

</>code

  1. 43: </tr>

</>code

  1. 44: <tr>

</>code

  1. 45:

</>code

  1. 46: <tr>

</>code

  1. 47: <td colspan="3">

</>code

  1. 48: <br>

</>code

  1. 49: <table style="font-size: 12px" border="0" cellspacing="5" cellpadding="4" width="100%"

</>code

  1. 50: align="center">

</>code

  1. 51: <tbody>

</>code

  1. 52: <tr>

</>code

  1. 53: <td>

</>code

  1. 54: <strong>产品编号</strong>

</>code

  1. 55: </td>

</>code

  1. 56: <td>

</>code

  1. 57: <strong>单位</strong>

</>code

  1. 58: </td>

</>code

  1. 59: <td width="60">

</>code

  1. 60: <strong>数量</strong>

</>code

  1. 61: </td>

</>code

  1. 62: <td width="80">

</>code

  1. 63: <strong>单价</strong>

</>code

  1. 64: </td>

</>code

  1. 65: </tr>

</>code

  1. 66: #foreach( $item in $order.OrderItems)

</>code

  1. 67: <tr>

</>code

  1. 68: <td>

</>code

  1. 69: ${item.ItemCode}

</>code

  1. 70: </td>

</>code

  1. 71: <td>

</>code

  1. 72: ${item.Unit}

</>code

  1. 73: </td>

</>code

  1. 74: <td>

</>code

  1. 75: ${item.Quantity}

</>code

  1. 76: </td>

</>code

  1. 77: <td>

</>code

  1. 78: ${item.BasicPrice}

</>code

  1. 79: </td>

</>code

  1. 80:

</>code

  1. 81: </tr>

</>code

  1. 82: #end

</>code

  1. 83: </tbody>

</>code

  1. 84: </table>

</>code

  1. 85:

</>code

  1. 86: </td>

</>code

  1. 87: </tr>

</>code

  1. 88: </tbody>

</>code

  1. 89: </table>

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

</>code

  1. 1: public static VelocityEngine InitVelocity()

</>code

  1. 2: {

</>code

  1. 3: //创建NVelocity引擎的实例对象

</>code

  1. 4: VelocityEngine velocity = new VelocityEngine();

</>code

  1. 5: //初始化该实例对象

</>code

  1. 6: ExtendedProperties props = new ExtendedProperties();

</>code

  1. 7: props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");

</>code

  1. 8: props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, System.Web.HttpContext.Current.Server.MapPath("\\mailTemplate"));

</>code

  1. 9: props.AddProperty(RuntimeConstants.INPUT_ENCODING, "gb2312");

</>code

  1. 10: props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "gb2312");

</>code

  1. 11: velocity.Init(props);

</>code

  1. 12: return velocity;

</>code

  1. 13: }

</>code

  1. 14:  

</>code

  1. 15: private void SendOrderConfirmdEmail()

</>code

  1. 16: {

</>code

  1. 17: VelocityEngine velocity = InitVelocity();

</>code

  1. 18: //从文件中读取模板

</>code

  1. 19: Template temp = velocity.GetTemplate("CreateOrderMail.vm");

</>code

  1. 20:  

</>code

  1. 21: Order order = Tools.CreateOrder();

</>code

  1. 22: IContext context = new VelocityContext();

</>code

  1. 23: context.Put("order", order);

</>code

  1. 24: //合并模板

</>code

  1. 25: StringWriter writer = new StringWriter();

</>code

  1. 26: temp.Merge(context, writer);

</>code

  1. 27:  

</>code

  1. 28: //发送邮件

</>code

  1. 29: MailMessage mm = new MailMessage();

</>code

  1. 30: mm.Subject = string.Format("您的订单({0}) -- 订单已经确认", order.OrderNo);

</>code

  1. 31: mm.IsBodyHtml = true;

</>code

  1. 32: mm.To.Add("lonely_7345@hotmail.com");

</>code

  1. 33: mm.Body = writer.GetStringBuilder().ToString();

</>code

  1. 34: Tools.SendEmail(mm);

</>code

  1. 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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

Tag标签: 邮件模板,nvelocity,email tempalte,用户控件 email,邮件 html

如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛

发表评论 (692人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称:
最新评论
------分隔线----------------------------

快速入口

· 365软件
· 杰创官网
· 建站工具
· 网站大全

其它栏目

· 建站教程
· 365学习

业务咨询

· 技术支持
· 服务时间:9:00-18:00
365建站网二维码

Powered by 365建站网 RSS地图 HTML地图

copyright © 2013-2024 版权所有 鄂ICP备17013400号