从发现.NET Framework中SmtpClient的Bug并拿出解决方案,然后给微软开发者社区提交Bug开始,总共耗时一个多月,对Bug修复的代码最终被采纳,现已合并到.NET Core Libraries (CoreFX)主线中。

修复记录https://github.com/dotnet/corefx/commit/94b1f1eae84fd4823cfa2bbdde6fc87c46b57908

虽然对Bug修复实际生效的代码只有20个字符,但意义重大,这个Bug不遇上一点事没有,遇上了不对框架开刀是非常棘手的,而且备受折磨也稍微有点难摸得清头脑。

相关详情见我的另外一篇博客《记录一次.Net框架Bug发现和提交过程:.Net Framework和.Net Core均受影响》

问题描述

我们用SmtpClientSendAsync、 SendMailAsync异步方法发送邮件,并且要求使用DeliveryFormat = SmtpDeliveryFormat.SevenBit 格式来编码中文内容,本来预期是邮件内容中带中文的SubjectAttachments file name 都会进行Base64编码。

但实际结果是:如果邮件服务器支持SMTPUTF8扩展,那么异步发送SevenBit邮件并不会进行Base64编码,同步方法没有此问题。

问题根源

原因是在SmtpClient.SendMailCallback方法中,message.BeginSend allowUnicode参数直接使用的ServerSupportsEai,而不是统一的IsUnicodeSupported()

 private void SendMailCallback(IAsyncResult result){ ......_message.BeginSend(_writer, DeliveryMethod != SmtpDeliveryMethod.Network, ServerSupportsEai, new AsyncCallback(SendMessageCallback), result.AsyncState); ......} 

ServerSupportsEai改成IsUnicodeSupported()问题解决。就这20个字符的改动~

另外附对现有带Bug的.Net框架修复方法

比如使用的.NET Framework 4.7.2,纯天然原生自带此Bug,我们可以用我们的代码修复它。

最开始测试时以为此方法无效,没想到是Hook错了地方,换到最深层次调用地方,一抓一个准。

使用DotNetDetour库对.Net框架内方法进行Hook,找出SmtpClient.ServerSupportsEai最结果最终是从SmtpConnection.ServerSupportsEai得来的,也许是C#编译后把整个调用过程都优化掉了,变成了取值的地方直接调用的SmtpConnection中的方法,导致Hook前面的方法都是不会被执行,Hook SmtpConnection.ServerSupportsEai一抓一个准。

附上Hook代码:

public class Hook : IMethodMonitor {    

public bool ServerSupportsEai {[Monitor("System.Net.Mail", "SmtpConnection")]        get {Console.WriteLine("Hook");                     return !true?org():false;//什么情况下要Hook? AsyncLocal和CallContext上下文为什么在这里传不进来?}}[Original]      public bool org() {             return false;}
}

另外引出了另外一个折磨人Bug,异步环境下,ServerSupportsEai的调用栈中上下文怎么会丢失?难道哪里使用了类似ThreadPool.UnsafeXXX这种效果?我们没法通过CallContext(AsyncLocal)给Hook代码传参数,只能写死,不管调用方要不要修改返回值,都只能得到修改后的结果,尴尬不尴尬。

从.Net框架Bug的提交到修复代码成功合并到.NET CoreFX主线相关推荐

  1. 被冰封的 Bug:Fishhook Crash 修复纪实

    作者:郝连福,业界资深计算机技术专家,现任声网Agora 首席前端架构师.先后担任过 Principal Engineer/Engineering Director(UTStarcom).Sr. ar ...

  2. uplay服务器未响应,《看门狗:军团》存在崩溃丢失存档BUG 育碧正在修复

    原标题:<看门狗:军团>存在崩溃丢失存档BUG 育碧正在修复 <看门狗:军团>的部分玩家们近日在游戏中遇到了一个十分恼人的问题--在进行游戏时,有时会遇到游戏未响应或崩溃的问题 ...

  3. 雪碧图工具sprity(20151201更新修复了同时合并多张图的bug)

    前身是css-sprite,前几天帮新同事搭建环境,意外发现sprity在window下可以安装成功了,同时也发现node版本已经4点几了,自己电脑的版本还停留在0.10,赶紧把自己的node升级到最 ...

  4. 我需要完全理解这部分代码才能确保它能够正常工作,如果由我来修复代码中的问题,我是不会这么写的,因此希望你也不要这么来写(转)...

    Jim Bird是一位经验丰富的软件开发经理.项目经理与CTO,专注于软件开发与维护.软件质量与安全等领域中疑难问题的解决.在过去的15年间,Jim曾管理过团队建设并主导过高性能的财务系统的建设.他的 ...

  5. 污点修复代码_立即修复该代码!

    污点修复代码 您正在从事这个新项目,并且在某处看到一段不好的代码. 处理它的错误方法是"不,那是别人的代码,我对此没有做任何事情","我没有时间解决这个问题–我还有其他任 ...

  6. SSM框架——使用MyBatis Generator自动创建代码

    SSM框架--使用MyBatis Generator自动创建代码 这是通过命令行, 不用ide插件. 若在IDEA中通过插件generator, 还可以参考另一篇: IDEA搭建Spring+Spri ...

  7. java集合框架的结构_集合框架(Collections Framework)详解及代码示例

    简介 集合和数组的区别: 数组存储基础数据类型,且每一个数组都只能存储一种数据类型的数据,空间不可变. 集合存储对象,一个集合中可以存储多种类型的对象.空间可变. 严格地说,集合是存储对象的引用,每个 ...

  8. java 死锁的检测与修复_调查死锁–第4部分:修复代码

    java 死锁的检测与修复 在这个简短的博客系列的最后BadTransferOperation中,我一直在讨论分析死锁,我将修复BadTransferOperation代码. 如果您已经看过本系列的其 ...

  9. 研究僵局–第4部分:修复代码

    在这个简短的博客系列的最后BadTransferOperation中,我一直在讨论分析死锁,我将修复BadTransferOperation代码. 如果您看过本系列的其他博客 ,那么您将知道,为了达到 ...

最新文章

  1. 机器学习中的一些概念
  2. Entity Framework-02
  3. sublime配置python3环境_【env】Sublime配置Python3开发环境
  4. wopi php,Office Online Server WOPI 接口
  5. mysql异步复制参数_MySQL Replication(异步复制)基本原理
  6. C语言 十进制和二进制相互转换 - C语言零基础入门教程
  7. maven离线安装jar包
  8. Spring Boot 国际化踩坑指南
  9. Java job interview:WinForm桌面小程序设计思想及项目实现思路
  10. Win10系统怎么还原?Win10如何回到以前的系统
  11. 上海租房提取公积金(提醒)
  12. 深度神经网络概念整理,最简单的神经网络是什么样子?
  13. vim复制、粘贴以及配置总结
  14. 在Excel中给不足位数的数字前面补0
  15. MT6(8)735平台Android5.1 codege.dws 配置
  16. 微信小程序(优惠券)
  17. 最小生成树--牛客练习赛43-C
  18. 基于STM32F103移植FreeRTOS教程
  19. 嵌入式:I/O接口扩展
  20. IP头以及头的各部分含义

热门文章

  1. php xxtea加密,php - esp32和php XXTEA字符串加密 - SO中文参考 - www.soinside.com
  2. 通过url来设置log4j的记录级别
  3. Linux 远程开机(walk on lan)
  4. WPF 使用DrawingVisual绘制高性能曲线图
  5. 都说不要装箱,那装箱到底带来了什么开销?
  6. 你真的了解扩展方法吗?
  7. 初探IdentityServer4(客户端模式)
  8. 在 .NET Core 中如何让 Entity Framework Core 在日志中记录由 LINQ 生成的SQL语句
  9. 在 ASP.NET Core 中使用托管服务实现后台任务
  10. switch类型模式