如何在SSIS脚本任务中为HTML邮件添加多个附件?
SSIS脚本任务:批量添加竖线分隔的邮件附件
你的现有代码仅支持添加单个附件,要实现批量添加竖线分隔的附件列表,只需修改核心逻辑,拆分字符串后循环添加附件即可。以下是修改后的完整代码:
#region Help: Introduction to the script task /* The Script Task allows you to perform virtually any operation that can be accomplished in * a .Net application within the context of an Integration Services control flow. * * Expand the other regions which have "Help" prefixes for examples of specific ways to use * Integration Services features within this script task. */ #endregion #region Namespaces using System; using System.Data; using Microsoft.SqlServer.Dts.Runtime; using System.Windows.Forms; using System.Net; using System.Net.Mail; using System.IO; // 添加IO命名空间,用于文件操作 using System.Linq; // 添加Linq命名空间,用于过滤空路径 #endregion namespace ST_3806baf576ce4ad1ab06519f6706197b { /// <summary> /// ScriptMain is the entry point class of the script. Do not change the name, attributes, /// or parent of this class. /// </summary> [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute] public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase { #region Help: Using Integration Services variables and parameters in a script /* To use a variable in this script, first ensure that the variable has been added to * either the list contained in the ReadOnlyVariables property or the list contained in * the ReadWriteVariables property of this script task, according to whether or not your * code needs to write to the variable. To add the variable, save this script, close this instance of * Visual Studio, and update the ReadOnlyVariables and * ReadWriteVariables properties in the Script Transformation Editor window. * To use a parameter in this script, follow the same steps. Parameters are always read-only. * * Example of reading from a variable: * DateTime startTime = (DateTime) Dts.Variables["System::StartTime"].Value; * * Example of writing to a variable: * Dts.Variables["User::myStringVariable"].Value = "new value"; * * Example of reading from a package parameter: * int batchId = (int) Dts.Variables["$Package::batchId"].Value; * * Example of reading from a project parameter: * int batchId = (int) Dts.Variables["$Project::batchId"].Value; * * Example of reading from a sensitive project parameter: * int batchId = (int) Dts.Variables["$Project::batchId"].GetSensitiveValue(); * */ #endregion #region Help: Firing Integration Services events from a script /* This script task can fire events for logging purposes. * * Example of firing an error event: * Dts.Events.FireError(18, "Process Values", "Bad value", "", 0); * * Example of firing an information event: * Dts.Events.FireInformation(3, "Process Values", "Processing has started", "", 0, ref fireAgain) * * Example of firing a warning event: * Dts.Events.FireWarning(14, "Process Values", "No values received for input", "", 0); * */ #endregion #region Help: Using Integration Services connection managers in a script /* Some types of connection managers can be used in this script task. See the topic * "Working with Connection Managers Programatically" for details. * * Example of using an ADO.Net connection manager: * object rawConnection = Dts.Connections["Sales DB"].AcquireConnection(Dts.Transaction); * SqlConnection myADONETConnection = (SqlConnection)rawConnection; * //Use the connection in some code here, then release the connection * Dts.Connections["Sales DB"].ReleaseConnection(rawConnection); * * Example of using a File connection manager * object rawConnection = Dts.Connections["Prices.zip"].AcquireConnection(Dts.Transaction); * string filePath = (string)rawConnection; * //Use the connection in some code here, then release the connection * Dts.Connections["Prices.zip"].ReleaseConnection(rawConnection); * */ #endregion /// <summary> /// This method is called when this script task executes in the control flow. /// Before returning from this method, set the value of Dts.TaskResult to indicate success or failure. /// To open Help, press F1. /// </summary> public void Main() { string htmlMessageFrom = Dts.Variables["$Package::parFromLine"].Value.ToString(); string htmlMessageTo = Dts.Variables["$Package::parToLine"].Value.ToString(); string htmlMessageSubject = Dts.Variables["$Package::parSubject"].Value.ToString(); string htmlMessageBody = Dts.Variables["$Package::parBody"].Value.ToString(); string smtpServer = "mail.mydomain.com"; SendMailMessage(htmlMessageFrom, htmlMessageTo, htmlMessageSubject, htmlMessageBody, true, smtpServer); Dts.TaskResult = (int)ScriptResults.Success; } private void SendMailMessage(string From, string SendTo, string Subject, string Body, bool IsBodyHtml, string Server) { // 获取附件参数和项目级源文件夹路径 string attachFilesStr = Dts.Variables["$Package::parAttachment"].Value.ToString(); string folderSource = Dts.Variables["$Project::parFolderSource"].Value.ToString(); // 拆分竖线分隔的路径,过滤空字符串和首尾空格 string[] attachPaths = attachFilesStr.Split('|') .Select(path => path.Trim()) .Where(path => !string.IsNullOrEmpty(path)) .ToArray(); // 使用using语句自动释放MailMessage和SmtpClient资源 using (MailMessage htmlMessage = new MailMessage(From, SendTo, Subject, Body)) using (SmtpClient mySmtpClient = new SmtpClient(Server)) { htmlMessage.IsBodyHtml = IsBodyHtml; foreach (string path in attachPaths) { // 拼接完整路径:如果是相对路径,结合项目源文件夹;如果是绝对路径则直接使用 string fullPath = Path.IsPathRooted(path) ? path : Path.Combine(folderSource, path); // 校验文件是否存在,避免发送失败 if (File.Exists(fullPath)) { using (Attachment attachment = new Attachment(fullPath)) { htmlMessage.Attachments.Add(attachment); } } else { // 触发SSIS警告事件,记录不存在的文件路径 Dts.Events.FireWarning(0, "邮件附件处理", $"文件不存在,已跳过:{fullPath}", "", 0); } } mySmtpClient.Credentials = CredentialCache.DefaultNetworkCredentials; mySmtpClient.Send(htmlMessage); } } #region ScriptResults declaration /// <summary> /// This enum provides a convenient shorthand within the scope of this class for setting the /// result of the script. /// /// This code was generated automatically. /// </summary> enum ScriptResults { Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success, Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure }; #endregion } }
关键修改说明
- 添加必要命名空间:引入
System.IO用于文件路径处理、System.Linq用于过滤空路径 - 拆分并清理附件路径:用
Split('|')拆分字符串,通过Trim()去除路径首尾空格,Where过滤空字符串,避免无效路径导致的错误 - 拼接完整路径:结合项目参数
$Project::parFolderSource,自动将相对路径转为完整绝对路径 - 循环添加附件:遍历所有有效路径,创建
Attachment实例并添加到邮件中;使用using确保附件资源正确释放 - 文件存在校验:添加
File.Exists判断,遇到不存在的文件时触发SSIS警告事件,避免整个任务失败
注意事项
- 确保脚本任务的ReadOnlyVariables已包含所有用到的参数:
$Package::parAttachment、$Package::parFromLine、$Package::parToLine、$Package::parSubject、$Package::parBody、$Project::parFolderSource - 确认SSIS执行账户对附件路径有读取权限
- 若不需要相对路径拼接逻辑,可直接使用
fullPath = path替换相关代码
内容的提问来源于stack exchange,提问作者Henrov
相关产品推荐
相关产品推荐

