You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用foreach循环实现C#多附件邮件发送?优化现有硬编码代码

优化C#邮件批量附件处理方案

Hey there! Let's fix that hardcoded attachment issue and make your code clean, scalable, and maintainable. Here's a step-by-step refactor:

1. 重构模型类(核心改进)

首先,我们要把那些重复的AttachmentContect1、AttachmentName1这类硬编码属性替换成一个附件列表,这样不管你要加1个还是10个附件,都不用修改模型结构。

先创建一个单独的附件项类,然后在EmailDetails里添加这个类的集合:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Services.Models {
    public class CommonModel {
        // 新增:单个附件的实体类
        public class AttachmentItem {
            public byte[] Content { get; set; }
            public string FileName { get; set; }
        }

        public class EmailDetails {
            public string ToMailId { get; set; }
            public string Subject { get; set; }
            public string Body { get; set; }
            public string CCList { get; set; }
            // 替换原来的单个附件属性为列表
            public List<AttachmentItem> Attachments { get; set; } = new List<AttachmentItem>();
        }
    }
}

这样修改后,你的模型就具备了处理任意数量附件的能力,不用再每次加新的AttachmentContectN属性了。

2. 重构SendMail发送方法

接下来,把原来硬编码的两个附件判断逻辑,改成遍历附件列表的循环:

public static void SendMail(EmailDetails ObjEmailDtl){
    try {
        SmtpClient client = new SmtpClient();
        client.DeliveryMethod = SmtpDeliveryMethod.Network;
        client.EnableSsl = false;
        string hostName = string.Empty;
        using (eCoreDbEntities db = new eCoreDbEntities()) {
            hostName = db.Parameters.Where(m => m.Name == "SMTP").FirstOrDefault().Value;
        }
        client.Host = hostName;
        client.Port = 25;
        
        // 用using包裹MailMessage,自动释放资源
        using (MailMessage msg = new MailMessage()) {
            msg.From = new MailAddress("contactus@karvyclick.com");

            // 处理收件人(原有逻辑保留)
            if (!string.IsNullOrEmpty(ObjEmailDtl.ToMailId)) {
                string[] arrCC = ObjEmailDtl.ToMailId.Trim().Split(',');
                foreach (var item in arrCC) {
                    msg.To.Add(new MailAddress(item));
                }
            }
            // 处理抄送人(原有逻辑保留)
            if (!string.IsNullOrEmpty(ObjEmailDtl.CCList)) {
                string[] arrCC = ObjEmailDtl.CCList.Trim().Split(',');
                foreach (var item in arrCC) {
                    msg.CC.Add(new MailAddress(item));
                }
            }

            msg.Subject = ObjEmailDtl.Subject;
            msg.IsBodyHtml = true;
            msg.Body = ObjEmailDtl.Body;

            // 批量处理附件(替换原来的两个if判断)
            if (ObjEmailDtl.Attachments != null && ObjEmailDtl.Attachments.Any()) {
                foreach (var attachmentItem in ObjEmailDtl.Attachments) {
                    // 跳过无效的附件(内容为空或文件名缺失)
                    if (attachmentItem.Content == null || string.IsNullOrEmpty(attachmentItem.FileName)) {
                        continue;
                    }
                    Attachment att = new Attachment(new MemoryStream(attachmentItem.Content), attachmentItem.FileName);
                    msg.Attachments.Add(att);
                }
            }

            client.Send(msg);
        }
    } catch (Exception ex) {
        Common.WriteLog("Common-SendMail", "", ex.Message);
    }
}

这里加了空值检查和无效附件跳过逻辑,还用using包裹了MailMessage,避免资源泄漏。

3. 修改调用代码(创建邮件部分)

最后,把原来创建单个附件的代码改成向列表中添加附件项:

byte[] dailyReportContent = Encoding.ASCII.GetBytes(str.ToString());
byte[] orderDetailsContent = Encoding.ASCII.GetBytes(str1.ToString());

EmailDetails objEmail = new EmailDetails();
var tomail = db.Parameters.ToList().Where(m => m.Name == "ToList" && m.Category == "DynamicReport").FirstOrDefault().Value;
objEmail.ToMailId = tomail;

// 添加第一个附件
objEmail.Attachments.Add(new CommonModel.AttachmentItem {
    Content = dailyReportContent,
    FileName = $"katalister_daily_report_{DateTime.Now:yyyyMMddHHmmss}.xls"
});
// 添加第二个附件
objEmail.Attachments.Add(new CommonModel.AttachmentItem {
    Content = orderDetailsContent,
    FileName = "OrderDetails_BD.xls"
});

objEmail.Subject = "Katalister Dynamic Report";
objEmail.Body = "&nbsp; Dear Leader,&lt;br/&gt;&lt;br/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Please find the attached Katalister Daily Report and Order Details Report.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt; Team Karvy";
objEmail.CCList = db.Parameters.ToList().Where(m => m.Name == "CCList" && m.Category == "DynamicReport").FirstOrDefault().Value;

Common.SendMail(objEmail);

我把文件名里的DateTime.Now改成了格式化字符串yyyyMMddHHmmss,避免文件名里出现冒号这类系统不允许的字符。

额外小提示

  • 编码注意:你现在用Encoding.ASCII,如果报表内容包含非ASCII字符(比如中文、特殊符号),会出现乱码,建议改用Encoding.UTF8。
  • 过时API提醒:SmtpClient在.NET Framework中已经被标记为过时,如果你后续升级项目,建议改用更现代的MailKit库,它的API更友好,也支持更多功能。

内容的提问来源于stack exchange,提问作者kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:23:00