C#发送正文带图片带附件的邮件
1,开启服务,获取授权码。以QQ邮箱为例:

点击管理服务,进入账号与安全页面

2,相关设置参数,以QQ邮箱为例:
登录时,请在第三方客户端的密码输入框里面填入授权码进行验证。(不是填入QQ的密码)
IMAP/SMTP 设置方法用户名/帐户: 你的QQ邮箱完整的地址密码: 生成的授权码电子邮件地址: 你的QQ邮箱的完整邮件地址接收邮件服务器: imap.qq.com,使用SSL,端口号993发送邮件服务器: smtp.qq.com,使用SSL,端口号587POP3/SMTP 设置方法用户名/帐户: 你的QQ邮箱完整的地址密码: 生成的授权码电子邮件地址: 你的QQ邮箱的完整邮件地址接收邮件服务器: pop.qq.com,使用SSL,端口号995发送邮件服务器: smtp.qq.com,使用SSL,端口号587
3,2次包装代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Common
{/// <summary>/// 软件的邮箱类,用于发送邮箱数据/// </summary>public class Emailhelp{public static Emailhelp MailSystem163 = new Emailhelp(mail =>{mail.Host = "smtp.163.com";//使用163的SMTP服务器发送邮件//mail.UseDefaultCredentials = true;//在winform平台使用默认值mail.EnableSsl = true;mail.UseDefaultCredentials = false;//在.framework或mvc下使用这个mail.Port = 25;//端口号mail.DeliveryMethod = SmtpDeliveryMethod.Network;mail.Credentials = new System.Net.NetworkCredential("邮件发送地址(自己的邮件号)如1234656@qq.com", "刚才获取的授权码");},"邮件发送地址(自己的邮件号)如1234656@qq.com","邮件发送地址(自己的邮件号)如1234656@qq.com");/// <summary>/// 系统连续发送失败的次数,为了不影响系统,连续三次失败就禁止发送/// </summary>private static long SoftMailSendFailedCount { get; set; } = 0L;/// <summary>/// 系统的邮件发送客户端/// </summary>private SmtpClient smtpClient { get; set; }/// <summary>/// 发送邮件的地址/// </summary>private string MailFromAddress { get; set; } = "";/// <summary>/// 邮件发送的地址/// </summary>public string MailSendAddress { get; set; } = "";/// <summary>/// 实例化一个邮箱发送类,需要指定初始化信息/// </summary>/// <param name="mailIni">初始化的方法</param>/// <param name="addr_From">发送地址,应该和账户匹配</param>/// <param name="addr_to">邮件接收地址</param>/// <remarks>/// </remarks>public Emailhelp(Action<SmtpClient> mailIni, string addr_From = "", string addr_to = ""){smtpClient = new SmtpClient();mailIni(smtpClient);MailFromAddress = addr_From;MailSendAddress = addr_to;}private string GetExceptionMail(Exception ex){return ex.Message;}/// <summary>/// 发送邮件/// </summary>/// <param name="addr_from">发送地址</param>/// <param name="name">发送别名</param>/// <param name="addr_to">接收地址</param>/// <param name="subject">邮件主题</param>/// <param name="body">邮件内容</param>/// <param name="attachment">附件地址</param>/// <param name="isHtml">邮件内容是否是HTML语言</param>/// <param name="priority">优先级</param>/// <returns>发生是否成功,内容不正确会被视为垃圾邮件</returns>public bool SendMail(string addr_from, string name, string[] addr_to, string subject, string body, string[] attachment, bool isHtml = false, MailPriority priority = MailPriority.Normal){if (SoftMailSendFailedCount > 10){SoftMailSendFailedCount++;return true;}MailMessage mailMessage = new MailMessage();try{mailMessage.From = new MailAddress(addr_from, name, Encoding.UTF8);foreach (string addresses in addr_to){mailMessage.To.Add(addresses);}mailMessage.Subject = subject;mailMessage.Body = body;MailMessage mailMessage2 = mailMessage;mailMessage2.Body = mailMessage2.Body + Environment.NewLine + Environment.NewLine + Environment.NewLine;mailMessage.SubjectEncoding = Encoding.UTF8;mailMessage.BodyEncoding = Encoding.UTF8;mailMessage.Priority = priority;mailMessage.IsBodyHtml = isHtml;for (int i = 0; i < attachment.Length; i++){Attachment address = new Attachment(attachment[i]);mailMessage.Attachments.Add(address);}smtpClient.Send(mailMessage);SoftMailSendFailedCount = 0L;return true;}catch (Exception ex){SoftMailSendFailedCount++;return false;}}/// <summary>/// 发送内容带有图片的邮件/// </summary>/// <param name="sfrom">发件人邮箱地址</param>/// <param name="displayName">显示名</param>/// <param name="addr_to">收件人地址</param>/// <param name="sSubject">标题</param>/// <param name="sBody">邮件内容</param>/// <param name="attachment">邮件附件</param>/// <returns></returns>public bool Send(string sfrom, string displayName, string[] addr_to, string sSubject, string sBody, string[] attachment){MailMessage oMail = new MailMessage();oMail.From = new MailAddress(sfrom, displayName, Encoding.UTF8);foreach (var item in addr_to){oMail.To.Add(item);}// 添加附件if (attachment != null){foreach (var item in attachment){oMail.Attachments.Add(new Attachment(item));}}sBody = ReplaceImg(sBody, oMail); // 处理图片oMail.Subject = sSubject; //邮件标题oMail.Body = sBody; //邮件内容oMail.IsBodyHtml = true; //邮件格式oMail.BodyEncoding = Encoding.GetEncoding("GB2312"); //邮件采用的编码oMail.Priority = MailPriority.High; //设置邮件的优先级为高try{smtpClient.Send(oMail);return true;}catch (Exception e){SoftMailSendFailedCount++;return false;}finally{oMail.Dispose(); //释放资源}}/// <summary>/// 处理邮件内容中的图片/// 将图片改为附件形式在body中显示/// </summary>/// <param name="body"></param>/// <returns></returns>private string ReplaceImg(string body, MailMessage m){try{Dictionary<string, Stream> imgDic = new Dictionary<string, Stream>();body = GetImgStream(body, imgDic);AlternateView avHtml = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);if (imgDic.Count != 0) // 内容添加图片{foreach (var dic in imgDic){LinkedResource lrImage = new LinkedResource(dic.Value, "image/gif");lrImage.ContentId = dic.Key;avHtml.LinkedResources.Add(lrImage);}}m.AlternateViews.Add(avHtml);return body;}catch (Exception){return body;}}private string GetImgStream(string body, Dictionary<string, Stream> imgDic){string mactch;Regex reg = new Regex(@"(?i)<img[^>]*?\ssrc\s*=\s*(['""]?)(?<src>[^'""\s>]+)\1[^>]*>");MatchCollection mc = reg.Matches(body);for (int i = 0; i < mc.Count; i++){string key = "pic" + i;mactch = mc[i].Groups["src"].Value;body = body.Replace(mactch, "cid:" + key);FileStream fs = new FileStream(mactch, FileMode.Open);imgDic.Add(key, fs);}return body;}}
}
4,邮件效果:

特别说明:若要实现:
第1,正文带有背景图片。
第2,正文为自定义编辑风格(带有边框,不同颜色的字体)。
正文需要为html格式,普通文本格式无法实现。
相关文章:
C#发送正文带图片带附件的邮件
1,开启服务,获取授权码。以QQ邮箱为例: 点击管理服务,进入账号与安全页面 2,相关设置参数,以QQ邮箱为例: 登录时,请在第三方客户端的密码输入框里面填入授权码进行验证。࿰…...
【C#跨平台开发详解】C#跨平台开发技术之.NET Core基础学习及快速入门
1. C#与.NET的发展历程 C#是由Microsoft开发的现代编程语言,最初伴随着.NET Framework发布。随着技术的进步,特别是针对跨平台开发的需求,Microsoft推出了.NET Core,这是一个开源且跨平台的框架,支持Windows、macOS和…...
请解释Java中的死锁产生的原因和解决方法。什么是Java中的并发工具类?请列举几个并解释其用途。
请解释Java中的死锁产生的原因和解决方法。 Java中的死锁是指两个或两个以上的线程在执行过程中,因为争夺资源而造成的一种相互等待的现象,若无外力作用,这些线程都将无法向前推进。死锁是并发编程中常见的问题,它会导致程序运行…...
三分钟带你看懂,低代码开发赋能办公方式转变
随着技术的不断进步,企业对办公效率和灵活性的需求日益增长。低代码开发作为一种新兴的开发模式,正在改变传统的办公方式,让非技术背景的业务人员也能参与到应用的创建和维护中来。本文将带你快速了解低代码开发如何赋能办公方式的转变。 什么…...
视频剪辑软件哪个好用?11款软件轻松上手,让创意视频流畅呈现!
视频剪辑已经涉及到很多个领域,视频剪辑软件的需求也是越来越普遍了。很多朋友在日常办公学习中,经常会遇到视频剪辑的问题。借助专业的视频剪辑软件,我们可以快速的对视频进行剪辑,制作出属于自己的作品。 市面上有各种各样的视频…...
pytest二次开发:生成用例参数
pytest.fixture是一个装饰器,用于声明一个fixture。Fixture是pytest中的一个核心概念,它提供了一种将测试前的准备代码(如设置测试环境、准备测试数据等)和测试后的清理代码(如恢复测试环境、删除临时文件等࿰…...
想抹黑华为的 请换一种方式
文|琥珀食酒社 作者 | 积溪 咱能不能有点创意? 能不能换个方式? 之前我说预测过 我说华为的三折叠手机 MateXT非凡大师发布 会引来一大波华为黑 还真是被我说中了 华为MateXT刚曝光 就被黄牛炒到10多万 有人说华为要割韭菜 是电子…...
学习学习学习
1. 面试算法 算法题空间限制64MB 2x 10^7 int codetop.cc 数字中文读 🔗 kmp 奶牛生小牛问题 丑数LCR 168. 丑数 - 力扣(LeetCode) 166. 分数到小数 - 力扣(LeetCode) 小数循环节 深入解析力扣166题ÿ…...
requestAnimationFrame原理和使用
requestAnimationFrame 是一个用于在浏览器中实现高效动画的方法。它告诉浏览器你希望执行一个动画,并在下一次重绘之前调用指定的回调函数来更新动画。浏览器会自动优化动画的刷新频率,以确保动画的流畅性和性能。 原理 帧刷新:浏览器通常…...
线程的状态(java)
“苦? 何止是苦~~~~~” 本期内容来分享一下线程状态相关的知识哦!!! 对于进程来说,进程是有两种状态的。 一种是就绪状态:正在CPU上执行,或者随时可以去CPU上执行的。 另一种是阻塞状态&…...
Linux IO模型:IO多路复用
● 应用程序中同时处理多路输入输出流,若采用阻塞模式,得不到预期的目的; ● 若采用非阻塞模式,对多个输入进行轮询,但又太浪费CPU时间; ● 若设置多个进程/线程,分别处理一条数据通路ÿ…...
[数据集][目标检测]电梯内广告牌电动车检测数据集VOC+YOLO格式2787张4类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2787 标注数量(xml文件个数):2787 标注数量(txt文件个数):2787 标注…...
MATLAB下载详细教程及下载链接
欢迎大家进评论区交流经验 1. 准备工作 下载MATLAB安装包:首先,从MathWorks官方网站(http://www.mathworks.com)下载适合您操作系统的MATLAB安装包。确保选择与您的操作系统(如Windows、macOS或Linux)兼容的…...
利用发电量和气象数据分析来判断光伏仿真系统的准确性
随着光伏产业的迅速发展,光伏仿真系统通过集成气象数据分析、发电量分析、投融资分析及损耗估算等功能,为光伏项目的全生命周期管理提供了科学依据。 光伏仿真系统集成了气象数据分析、发电量预测、投融资分析、损耗估算及光伏设计等功能。其中…...
Model-based RL动态规划(基于价值、基于策略,泛化迭代)
白盒环境和黑盒环境 白盒环境:知道环境的状态转移函数P(s’|s)或P(s’|s,a)和奖励函数R(s)或R(s,a): 白盒环境下的学习相当于直接给出了有监督学习的数据分布(就是有了目标靶子),不需要采样了,直接最小…...
外接串口板,通过串口打开adb模式
一、依赖库 import subprocess import serial from serial.tools import list_ports import logging import time 二、代码 import subprocessimport serial from serial.tools import list_ports import logging import timedef openAdb(com):# com []# for i in list_por…...
ssm微信小程序校园失物招领论文源码调试讲解
第二章 开发技术与环境配置 以Java语言为开发工具,利用了当前先进的SSM框架,以MyEclipse10为系统开发工具,MySQL为后台数据库,开发的一个微信小程序校园失物招领。 2.1 Java语言简介 Java是由SUN公司推出,该公司于20…...
iOS 15推出后利用邮件打开率的7种方法
自从苹果在2021年底推出iOS 15以来,邮件打开率就一直是一个让人头疼的指标。 Klaviyo市场情报主管Mindy Regnell表示:“对于启用了Apple邮件隐私保护(MPP)的用户来说,苹果会打开这些邮件并预先下载内容到他们的服务器…...
以太网--TCP/IP协议(一)
概述 以太网是局域网的一种,其他的比如还有令牌环、FDDI。和局域网对应的就是广域网,如Internet,城域网等。 从网络层次看,局域网协议主要偏重于低层(业内一般把物理层、数据链路层归为低层)。以太网协议…...
LeetCode刷题:找到第K大的元素
本题其实就是考察排序算法,为了减低时间复杂度,所以采用堆排序 import java.security.Key; import java.util.Scanner;public class FindKtopElements {public static void main(String[] args) {Scanner scanner new Scanner(System.in);String lin…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
