项目背景:

最近在对几年前的一个项目进行重构,发现发送邮件功能需要一定的时间来处理,而由于发送是同步的因此导致在发送邮件时无法执行后续的操作

实际上发送邮件后只需要将发送结果写入系统日志即可对其他业务没有任何影响,因此决定将发送邮件操作更改为异步的
 
由于使用的是C#的邮件类库,而C#本身已经提供了异步发送的功能即只需要将Send方法更改为SendAsync即可,更改方法名并不难但发送后再写入日志就有点难了
因为项目中发送邮件是单独的组件,所以我不可能在发送邮件类库中直接添加写入日志操作(不在同一个类库,网络和MSDN上的例子都是同一组件下)
但C#可以使用委托将方法作为参数来传递的,因此我就可以在发送邮件的方法中添加一个回调方法,在异步发送邮件后再执行回调方法即可
 
完整代码:
/******************************************************************
* 创建人:HTL
* 创建时间:2015-04-16 21:34:25
* 说明:C# 发送异步邮件Demo
* Email:huangyuan413026@163.com
*******************************************************************/
using System;
using System.Net.Mail;
namespace SendAsyncEmailTest
{
class Program
{
const string dateFormat = "yyyy-MM-dd :HH:mm:ss:ffffff";
static void Main(string[] args)
{
Console.WriteLine("开始异步发送邮件,时间:" + DateTime.Now.ToString(dateFormat));
new MailHelper().SendAsync("Send Async Email Test", "This is Send Async Email Test", "huangyuan413026@163.com", emailCompleted);
Console.WriteLine("邮件正在异步发送,时间:" + DateTime.Now.ToString(dateFormat));
Console.ReadKey();
Console.WriteLine();
}
/// <summary>
/// 邮件发送后的回调方法
/// </summary>
/// <param name="message"></param>
static void emailCompleted(string message)
{
//延时1秒
System.Threading.Thread.Sleep(1000);
Console.WriteLine();
Console.WriteLine("邮件发送结果:\r\n" + (message == "true" ? "邮件发送成功" : "邮件发送失败") + ",时间:" + DateTime.Now.ToString(dateFormat));
//写入日志
}
}
/// <summary>
/// 发送邮件类
/// </summary>
public class MailHelper
{
public delegate int MethodDelegate(int x, int y);
private readonly int smtpPort = 25;
readonly string SmtpServer = "smtp.baidu.com";
private readonly string UserName = "support@baidu.com";
readonly string Pwd = "baidu.com";
private readonly string AuthorName = "BaiDu";
public string Subject { get; set; }
public string Body { get; set; }
public string Tos { get; set; }
public bool EnableSsl { get; set; }
MailMessage GetClient
{
get
{ if (string.IsNullOrEmpty(Tos)) return null;
MailMessage mailMessage = new MailMessage();
//多个接收者
foreach (string _str in Tos.Split(','))
{
mailMessage.To.Add(_str);
}
mailMessage.From = new System.Net.Mail.MailAddress(UserName, AuthorName);
mailMessage.Subject = Subject;
mailMessage.Body = Body;
mailMessage.IsBodyHtml = true;
mailMessage.BodyEncoding = System.Text.Encoding.UTF8;
mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
mailMessage.Priority = System.Net.Mail.MailPriority.High;
return mailMessage;
}
}
SmtpClient GetSmtpClient
{
get
{
return new SmtpClient
{
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential(UserName, Pwd),
DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network,
Host = SmtpServer,
Port = smtpPort,
EnableSsl = EnableSsl,
};
}
}
//回调方法
Action<string> actionSendCompletedCallback = null;
///// <summary>
///// 使用异步发送邮件
///// </summary>
///// <param name="subject">主题</param>
///// <param name="body">内容</param>
///// <param name="to">接收者,以,分隔多个接收者</param>
//// <param name="_actinCompletedCallback">邮件发送后的回调方法</param>
///// <returns></returns>
public void SendAsync(string subject, string body, string to, Action<string> _actinCompletedCallback)
{
if (string.IsNullOrEmpty(to)) return; Tos = to; SmtpClient smtpClient = GetSmtpClient;
MailMessage mailMessage = GetClient;
if (smtpClient == null || mailMessage == null) return;
Subject = subject;
Body = body;
EnableSsl = false;
//发送邮件回调方法
actionSendCompletedCallback = _actinCompletedCallback;
smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
try
{
smtpClient.SendAsync(mailMessage, "true");//异步发送邮件,如果回调方法中参数不为"true"则表示发送失败
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
smtpClient = null;
mailMessage = null;
}
}
/// <summary>
/// 异步操作完成后执行回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SendCompletedCallback(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
//同一组件下不需要回调方法,直接在此写入日志即可
//写入日志
//return;
if (actionSendCompletedCallback == null) return;
string message = string.Empty;
if (e.Cancelled)
{
message = "异步操作取消";
}
else if (e.Error != null)
{
message = (string.Format("UserState:{0},Message:{1}", (string)e.UserState, e.Error.ToString()));
}
else
message = (string)e.UserState;
//执行回调方法
actionSendCompletedCallback(message);
}
}
}
有图有真相

 
 
 

C#发送邮件时提示:“不允许使用邮箱名称。服务器响应为:”的错误解决办法

由于项目需要,要为客户提供一个定期发送邮件的程序。本来原来自己还写过,但新写的程序一晚上也没通过测试,总是提示"不允许使用邮箱名称。服务器响应为..."

经过在网上搜索查找解决办法,似乎解决办法都是一个,就是把smtp.UseDefaultCredentials = true;写到smtp.Credentials = new NetworkCredential("myusername", "mypwd");的前面。

但使用此方法,也未能解决问题。

后来,我从邮箱设置入手,发现现在大多邮箱都采用了设置smtp发邮件和客户端授权码的双重功能,以126为例,在126邮箱网页版的设置里,就能看到,如下图

后期,我将smtp.Credentials = new NetworkCredential("myusername", "mypwd")中的mypwd换成了我的客户端授权码,立即通过了测试。

希望朋友们碰到此种问题也多一种解决办法。

C# 使用系统方法发送异步邮件的更多相关文章

  1. 用django发送异步邮件

    太阳底下没有新鲜事,github是一个神奇的地方,你有什么想法,需求,点子.其实别人早就想到,而且也已经做到. 所以不要高估自己,有什么想法还是GITHUB一下,免得成了井底之娃. 这几天一直在研究p ...

  2. ActiveMQ入门系列之应用:Springboot+ActiveMQ+JavaMail实现异步邮件发送

    现在邮件发送功能已经是几乎每个系统或网址必备的功能了,从用户注册的确认到找回密码再到消息提醒,这些功能普遍的会用到邮件发送功能.我们都买过火车票,买完后会有邮件提醒,有时候邮件并不是买完票立马就能收到 ...

  3. spring boot:使用async异步线程池发送注册邮件(spring boot 2.3.1)

    一,为什么要使用async异步线程池? 1,在生产环境中,有一些需要延时处理的业务场景: 例如:发送电子邮件, 给手机发短信验证码 大数据量的查询统计 远程抓取数据等 这些场景占用时间较长,而用户又没 ...

  4. CI框架使用PHPmail插件发送QQ邮件:

    有助请顶,不好请评.0:33 2016/3/12CI框架使用PHPmail插件发送QQ邮件:发送成功,不过修改了主机参数,还包含了一个phpmail中的一个另外的文件,详见下方:参见:http://c ...

  5. 如何利用sendmail发送外部邮件?

    在写监控脚本时,为了更好的监控服务器性能,如磁盘空间.系统负载等,有必要在系统出现瓶颈时,及时向管理员进行报告.在这里通常采用邮件报警,同时,邮件设置为收到邮件,即向指定手机号码发送短信.这样可以实现 ...

  6. outlook 2016 for windows 每次刷新发送接收邮件会弹出登陆界面

    Q: outlook2016 for windows 每次刷新发送接收邮件会弹出登陆界面,office365 ProPlus 都是正常激活了,Word 和Excel都不存在此类问题 A: 排除用户的o ...

  7. 使用phpmailer发送smtp邮件时提示 SMTP Error: Could not authenticate 错误

    使用phpmailer发送smtp邮件时提示 SMTP Error: Could not authenticate 错误 这个错误是验证出现错误, $mail->Port = 25; //SMT ...

  8. 关于NK3C使用富文本编辑器(CKEditor)发送HTML邮件的使用说明

     目前NK3C发送HTML邮件使用的的编辑器是CKEditor4.6版本,关于CKEditor的使用说明如下:   1.依赖JQuery1.7版本以上,在xxx.vm中<head>< ...

  9. .Net Mail SMTP 发送网络邮件

    刚刚迈入"开发"的行列 一直有一个想法 我什么时候能给我庞大的用户信息数据库给每一位用户邮箱发送推荐信息呢? 刚迈入"编程两个月的时间" 我采用 SMTP 发送 ...

随机推荐

  1. OpenNebula学习第二节OpenNebula Node Installation

    一.准备工作 准备一台物理机或者虚拟机:Ubuntu16.0.4 已经更新了aliyun的source cpu支持虚拟化 关闭防火墙 二.安装步骤 2.1:下载opennebula repo源 wge ...

  2. mac 苹果鼠标 magic mouse2 当触摸代替点击当触摸板教程

    本文解决 mac 苹果鼠标 magic mouse2 触摸代替点击,鼠标当触摸板教程 买了magic mouse2之后,发现官方不推荐使用触摸代替点击,我感觉很不爽,这不就是一个触摸板嘛,于是各种搜软 ...

  3. 【Python】将对象存成json文件及从json取出对象

    常用代码,单拎出来以备查. 对象存json文件: import json obj={'name':'张有财','age':39,'arr':[2,34,5,6,7,88,'李有钱']} with op ...

  4. ECShop模板原理

    模板的原理 类似Smarty/ECShop这类模板的原理如下图所示. 1.首先是编译模板ECShop/Smart是利用PHP引擎,所以编译的结果是一个PHP文件,其编译过程就是 将分隔符{}替换成PH ...

  5. .NET Framework System.Array.Sort 数组类,加深对 IComparer、IComparable 以及泛型委托、匿名方法、Lambda 表达式的理解

    本文内容 自定义类 Array.Sort 参考资料 System.Array.Sort 有很多对集合的操作,比如排序,查找,克隆等等,你可以利用这个类加深对 IComparer.IComparable ...

  6. Android 开源项目 eoe 社区 Android 客户端

    本文内容 环境 开源项目 eoe 社区 Android 客户端 本文介绍 eoe 社区 Android 客户端.它是一个开源项目,功能相对简单,采用侧边菜单栏.可以学习一下.点击此处查看 GitHub ...

  7. Android Volley 库的使用

    本文内容 什么是 Volley 库 Volley 能做什么 Volley 架构 环境 演示 Volley 库的使用 参考资料 Android 关于网络操作一般都会介绍 HttpClient 以及 Ht ...

  8. Android开发——Android M(6.0) 权限解决方案

    Android开发--Android M(6.0) 权限解决方案 自从Android M(6.0)发布以来,权限管理相比以前有了很大的改变,很多程序员发现之前运行的好好的Android应用在Andro ...

  9. 去除Win10快捷图标小箭头

    有点强迫症,一看到操作系统上的快捷图标小箭头就想把它去除掉. 去除小箭头 reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Cur ...

  10. Server Performance Advisor (SPA) 3.0

    http://blogs.technet.com/b/windows-server-china-blog/archive/2013/03/26/server-performance-advisor-s ...