Email系列(QQ邮箱 + 含附件的邮箱案例 + 项目实战)
平台之大势何人能挡? 带着你的Net飞奔吧!
http://www.cnblogs.com/dunitian/p/4822808.html
邮箱系列:https://github.com/dunitian/LoTCodeBase/tree/master/NetCode/3.常用技能/07.Email
1.QQ邮箱:
他生成的是:http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=7oKBmoqAmq6fn8CNgYM
后来我把后面加密字符串换成明文的邮箱==》发现一样用 :http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=1054186320@qq.com
代码案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <! DOCTYPE html> < html lang="en" xmlns="http://www.w3.org/1999/xhtml"> < head > < meta charset="utf-8" /> < title ></ title > </ head > < body > 官方生成代码:(其实就是把你的邮件加了下密)< br />< br /> < a target="_blank" href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=7oKBmoqAmq6fn8CNgYM" style="text-decoration:none;"> < img src="http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_12.png" /> </ a > < br />< br /> 逆天通用土方法:(邮件可以任意替换)< br />< br /> < a target="_blank" href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=1054186320@qq.com">邮我</ a > </ body > </ html > |
效果:
订阅系列可以参考:http://www.cnblogs.com/dunitian/p/4554084.html
——————————————————————————————————————————————————————————————————————————————————————————————
邮件发送的前提设置:
QQ邮箱设置
授权码生成:
2.邮件案例:
简单熟悉邮件系列:点我就看基础案例
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #region 附件路径 /// <summary> /// 附件路径 /// </summary> public static List< string > filePathList = new List< string >(); #endregion #region 文件上传 /// <summary> /// LoTUploader-文件上传 /// </summary> /// <returns></returns> public JsonResult FileUpload(System.Web.HttpPostedFileBase file) { if (file == null ) { return Json( new { status = false , msg = "文件提交失败" }); } if (file.ContentLength > 10485760) { return Json( new { status = false , msg = "文件10M以内" }); } string filterStr = ".gif,.jpg,.jpeg,.bmp,.png|.rar,.7z,.zip" ; string fileExt = Path.GetExtension(file.FileName).ToLower(); if (!filterStr.Contains(fileExt)) { return Json( new { status = false , msg = "请上传图片或压缩包" }); } //防止黑客恶意绕过,判断下文件头文件 if (!file.InputStream.CheckingExt( "7173" , "255216" , "6677" , "13780" , "8297" , "55122" , "8075" )) { //todo:一次危险记录 return Json( new { status = false , msg = "请上传图片或压缩包" }); } //todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string .Format( "{0}/{1}" , "/lotFiles" , DateTime.Now.ToString( "yyyy-MM-dd" )); string fileName = string .Format( "{0}{1}" , Guid.NewGuid().ToString( "N" ), fileExt); string sqlPath = string .Format( "{0}/{1}" , path, fileName); string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } try { file.SaveAs(Path.Combine(dirPath, fileName)); file.InputStream.Dispose(); filePathList.Add(Path.Combine(dirPath, fileName)); } catch { return Json( new { status = false , msg = "文件保存失败" }); } return Json( new { status = true , msg = sqlPath }); } #endregion #region 发邮件 /// <summary> /// 发邮件 /// </summary> /// <param name="model"></param> /// <returns></returns> public async Task<JsonResult> SendMsg(MailModel model) { var obj = new AjaxOption< object >(); #region 校验系列 if (model == null ) { obj.Msg = "内容不能为空" ; } if ( string .IsNullOrWhiteSpace(model.MailSubject)) { obj.Msg = "邮件主题不能为空" ; } if ( string .IsNullOrWhiteSpace(model.MailContent)) { obj.Msg = "邮件内容不能为空" ; } #region 收件人邮箱 if (model.MailToList != null ) { foreach ( var item in model.MailToList) { if (!item.IsEmail()) { model.MailToList.Remove(item); } } } else { obj.Msg = "收件人邮箱不能为空" ; } //这个一定要加 if (model.MailToList.Count == 0) { obj.Msg = "收件人邮箱不能为空" ; } #endregion if (model.MailCCList.ExistsData()) { foreach ( var item in model.MailCCList) { if (!item.IsEmail()) { model.MailCCList.Remove(item); } } } #endregion //内容解码 model.MailContent = System.Web.HttpUtility.UrlDecode(model.MailContent); //添加附件 if (filePathList.ExistsData()) { model.AttachmentList=filePathList; } if (obj.Msg.IsNullOrWhiteSpace()) obj.Status = await EmailHelper.SendAsync(model); return Json(obj); } #endregion |
3.项目应用:https://github.com/dunitian/LoTCodeBase/tree/master/NetCode/3.常用技能/07.Email/2.EmailAPI
其实项目里面基本上是不用他附件功能的,比如你注册的时候发一个邮件给你来激活,你敏感操作的时候给你一个提示(比如异地登陆或者修改密码)
简单封装了一个api,一般每个项目里面都有这个发邮件的功能,很多公司把这些诸如上传,发邮件,短信通知的功能都封装成api,用的时候调用一下就可以了
效果图就不贴了,和上面差不多,就是没上传附件了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #region 发邮件 /// <summary> /// 发邮件 /// </summary> /// <param name="model"></param> /// <returns></returns> [CrossSite] public async Task< string > Post([FromUri]MailModel model) { var obj = new AjaxOption< object >(); #region 校验系列 if (model == null ) { obj.Msg = "内容不能为空" ; } if ( string .IsNullOrWhiteSpace(model.MailSubject)) { obj.Msg = "邮件主题不能为空" ; } if ( string .IsNullOrWhiteSpace(model.MailContent)) { obj.Msg = "邮件内容不能为空" ; } #region 收件人邮箱 if (model.MailToList != null ) { foreach ( var item in model.MailToList) { if (!item.IsEmail()) { model.MailToList.Remove(item); } } } else { obj.Msg = "收件人邮箱不能为空" ; } //这个一定要加 if (model.MailToList.Count == 0) { obj.Msg = "收件人邮箱不能为空" ; } #endregion if (model.MailCCList.ExistsData()) { foreach ( var item in model.MailCCList) { if (!item.IsEmail()) { model.MailCCList.Remove(item); } } } #endregion //内容解码 model.MailContent = System.Web.HttpUtility.UrlDecode(model.MailContent); if (obj.Msg.IsNullOrWhiteSpace()) obj.Status = await EmailHelper.SendAsync(model); return obj.ObjectToJson(); } #endregion |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | <! DOCTYPE html> < html > < head > < meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> < title >邮件系列</ title > < meta charset="utf-8" /> < link href="//cdn.bootcss.com/wangeditor/2.1.10/css/wangEditor.min.css" rel="stylesheet" /> < link href="//cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> </ head > < body > < div class="rows"> < div class="form-horizontal"> <!--收件人邮箱--> < div class="form-group"> < br /> < label class="col-sm-2 control-label">收件邮箱:</ label > < div class="col-sm-6"> < input type="text" class="form-control" id="mailTo" placeholder="请输入收件人邮箱..."> </ div > </ div > <!--收件人邮箱--> < div class="form-group"> < br /> < label class="col-sm-2 control-label">抄送邮箱:</ label > < div class="col-sm-6"> < input type="text" class="form-control" id="mailCC" placeholder="请输入抄送人邮箱..."> </ div > </ div > <!--标题--> < div class="form-group"> < br /> < label class="col-sm-2 control-label">主题名称:</ label > < div class="col-sm-6"> < input type="text" class="form-control" id="mailSubject" placeholder="请输入邮箱主题名称..."> </ div > </ div > <!--编辑器--> < div class="form-group"> < br /> < label class="col-sm-2 control-label">正文内容:</ label > < div class="col-sm-6"> < div id="edit" style="min-height:20em"></ div > </ div > </ div > <!--表单提交--> < div class="form-group"> < br /> < label class="col-sm-2 control-label"></ label > < div class="col-sm-6"> < button id="btn" class="btn btn-success form-control">发送邮件</ button > </ div > </ div > </ div > </ div > < div id="msg"></ div > < script src="//cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></ script > < script src="//cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js" async></ script > < script src="//cdn.bootcss.com/wangeditor/2.1.10/js/wangEditor.min.js"></ script > < script type="text/javascript"> // 为页面所有的editor配置全局的密钥 //wangEditor.config.mapAk = 'xxxxxxxxxxxxxx'; wangEditor.config.printLog = false; //阻止输出log var editor = new wangEditor('edit'); editor.create(); $('#btn').click(function () { // 获取编辑器区域完整html代码 var mailTo = $('#mailTo').val(); var mailCC = $('#mailCC').val(); var mailSubject = $('#mailSubject').val(); var mailContent = escape(editor.$txt.html()); if (mailTo.length < 1 || mailCC.length < 1 || mailSubject.length < 1 || mailContent.leng < 1) { $('#msg').html('<h2>除附件外,不能为空!</ h2 >'); return false; } $.post('/api/email?MailSubject=' + mailSubject + '&MailContent=' + mailContent + '&MailToList=' + mailTo + '&MailCCList=' + mailCC, {}, function (data) { data = JSON.parse(data); if (data.Status) { $('#msg').html('< h2 >发送成功!</ h2 >'); } else { $('#msg').html('< h2 >' + data.Msg + '</ h2 >'); } }) }); </ script > </ body > </ html > |
EmailHelper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | using System.Net.Mail; using System.Configuration; using System.Threading.Tasks; using System.Collections.Generic; #region MailModel /// <summary> /// MailModel /// </summary> public class MailModel { /// <summary> /// 邮箱主题 /// </summary> public string MailSubject { get ; set ; } /// <summary> /// 邮箱内容 /// </summary> public string MailContent { get ; set ; } /// <summary> /// 收件人邮箱 /// </summary> public List< string > MailToList { get ; set ; } /// <summary> /// 抄送人邮箱 /// </summary> public List< string > MailCCList { get ; set ; } /// <summary> /// 附件路径 /// </summary> public List< string > AttachmentList { get ; set ; } } #endregion public class EmailHelper { private static string mailFrom = ConfigurationManager.AppSettings[ "EmailForm" ]; //登陆用户名 private static string mailPass = ConfigurationManager.AppSettings[ "EmailPass" ]; //登陆密码 private static string mailSmtp = ConfigurationManager.AppSettings[ "EmailSmtp" ]; //SMTP服务器 #region 发送邮件 /// <summary> /// 发送邮件 /// </summary> /// <param name="mailSubject">邮箱主题</param> /// <param name="mailContent">邮箱内容</param> /// <param name="mailTo">收件人邮箱</param> /// <param name="mailCC">抄送人邮箱</param> /// <param name="attachmentsPath">附件路径</param> /// <returns>返回发送邮箱的结果</returns> public static async Task< bool > SendAsync(MailModel model) { #region 基本校验(一般都是调用前就验证了) //if (model == null || string.IsNullOrWhiteSpace(model.MailSubject) || string.IsNullOrWhiteSpace(model.MailContent) || model.MailTo == null) //{ // return false; //} #endregion //邮件服务设置 using ( var smtpClient = new SmtpClient()) { smtpClient.Host = mailSmtp; //指定SMTP服务器 smtpClient.Credentials = new System.Net.NetworkCredential(mailFrom, mailPass); //用户名和密码 using ( var mailMsg = new MailMessage()) { //发信人邮箱 mailMsg.From = new MailAddress(mailFrom); //收件人邮箱 foreach ( var item in model.MailToList) { mailMsg.To.Add(item); } //抄送人邮箱 if (model.MailCCList != null && model.MailCCList.Count > 0) { foreach ( var item in model.MailCCList) { mailMsg.CC.Add(item); } } //附件系列 if (model.AttachmentList != null ) { foreach ( var item in model.AttachmentList) { try { mailMsg.Attachments.Add( new Attachment(item)); } catch (System.Exception ex) { } } } mailMsg.Subject = model.MailSubject; //主题 mailMsg.Body = model.MailContent; //内容 mailMsg.BodyEncoding = System.Text.Encoding.UTF8; //编码 mailMsg.IsBodyHtml = true ; //HTML格式 try { await smtpClient.SendMailAsync(mailMsg); //发送邮件 return true ; } catch (System.Exception ex) { mailMsg.Dispose(); smtpClient.Dispose(); return false ; } } } } #endregion } |
如果没有账号,我提供几个测试账号:
mail.host = smtp.163.com
mail.username = php_tester@163.com
mail.password = php1234
mail.smtp.from = php_tester@163.com
mail.smtp.auth = true——————————————————
mail.host=smtp.yeah.net
mail.port=25
mail.smtp.auth=true
mail.smtp.timeout=25000
mail.username=techblog@yeah.net
mail.password=2436chao——————————————————
mail.server.host=smtp.yeah.net
mail.server.post=25
mail.server.validate=true
mail.server.username=zmc330563778
mail.server.password=zmc586858
mail.server.fromaddress=zmc330563778@yeah.net
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异