微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件

简介: 原文:微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件开篇介绍 大多数情况下我们的 SSIS 包都会配置在 SQL Agent Job 中周期性的按计划执行,比如每天晚上调用 SSIS 包刷新数据,处理 Cube 等。
原文: 微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件

开篇介绍

大多数情况下我们的 SSIS 包都会配置在 SQL Agent Job 中周期性的按计划执行,比如每天晚上调用 SSIS 包刷新数据,处理 Cube 等。一旦 SSIS 包中出现任何异常,报错,那么配置在 SQL Agent Job 中的通知,邮件提醒就会把这些错误信息发邮件到指定的用户或者系统维护者,这样就起到了一个错误监控的作用。

但是在有的情况下,有一些自定义的 SSIS 调度框架的计划调度都不是通过 SQL Agent Job 配置来完成的。比如我以前在一个小项目中设计过一个 SSIS 调度框架,只有一个主包配置在 SQL Agent Job 中,所有子包的上线不由 SQL Agent Job 支配。每次新增的子包要上线,只需要将相应的信息以及调度计划注册到相应的表中即可,不需要打开 SQL Agent Job 调整各个子包的执行顺序等等。那么在这种情况下,就只能在 SSIS 内部使用发送邮件的功能来发送错误信息,因为所有的子包和 SQL Agent Job 都是没有直接关系的。

在 SSIS 中我们可以通过 Send Mail Task 或者 Script Task 来发送邮件,当然还有第三种方式就是写存储过程调用发送邮件存储过程.

Send Mail Task 发送邮件

Send Mail Task 的使用其实非常的简单,配置的步骤也并不多,但是在使用它的时候有几个限制:

  1. 只能发送普通的文本格式的邮件,也就是说不支持 HTML 格式的邮件。
  2. 连接 SMTP Server 时不支持用户填写用户名和密码,也就是说用户要么在域环境下 SMTP Server 对用户进行 Windows 方式验证,要么就是访问的 SMTP Server 支持匿名访问,不需要提供用户名和密码。
  3. SMTP Server 的端口号使用默认的,也就是说如果在域中的 SMTP Server 端口号不是默认的话 Send Mail Task 就无法使用了。 

这里是我常用的一个测试服务器地址 http://www.yopmail.com/en/ ,免费的并支持匿名访问,可以通过它来进行邮件发送的测试。关于 Send Mail Task 的使用方式就不在这里演示了,在非域和非 Windows 验证方式下用我提到的可匿名访问的 Yop Mail 一试便知,主要是讲 Script Task 发送邮件的方式。

Script Task 发送邮件

新建一个包并首先创建一个 SMTP 连接 - New Connection。

选择 SMTP 连接管理器。

以我的邮箱为例子 BIWORK@126.com 发送邮箱服务器是 smtp.126.com,这个可以在网易邮箱配置页面查到。但是非常遗憾!在这里仍然是没有地方可以配置用户名和密码的,默认的情况下仍然是只支持 Windows 验证或者匿名访问。

所以说,如果想要在 SMTP Connection 里自己动手配置用户名和密码是不可能的,那么像这种 163,126等等很多很多邮箱直接通过 SMTP Connection 是肯定无法完成发送邮件操作的。

看下图时一定要理解一点:几乎每一个 SSIS 控件的属性都是可配置的,也是可获取的,这是我们在 SSIS ETL 的学习过程中解决很多很多问题的最关键的地方!

新建一些常用的变量,发件人,收件人,抄送,邮件标题,内容,附件地址,还有用户名和密码等。

PS:关于这个密码有一个故事,以前在公司里有一个管机房管电脑的同事,他的网络下载速度最快也没人管,他的电脑里有各种游戏,高清蓝光和 1024。每次大家伙要点东西像挤牙膏似的,大家都在想办法搞他的密码,直到后来大家有意无意记了并试出了密码 - 大概就是 lowformat1MBD!! 类似于这样的!看了密码之后我们都一致认为这个密码确实很符合他的职业,不过貌似苦大仇深啊!

其中 PV_CONTENT 变量描述的是邮件发送的 HTML 格式的内容,注意是字符串类型的因此需要双引号。

"<h1>Hi BIWORK!</h1>
<p>
This is a test email from the test SSIS package of BIWORK!
</p>
<p>Server Name - "+ @[System::MachineName] +"</p>
<p>Package Name - "+ @[System::PackageName] +"</p>
<p>Package Start Time - "+ (DT_WSTR, 12) ( DT_DBDATE) @[System::StartTime] +"</p>
<p></br>Thanks and Regards!</p>
<p>Simon</p>"

系统变量的信息也通过表达式嵌入到邮件正文中。

编辑 Script Task 并引入这些变量,Script Task 中的代码 -

using System.Net.Mail; // BIWORK Added
using System.Text.RegularExpressions; // BIWORK Added

Main 中的代码包括处理优先级,多个收件人的处理,用户名和密码,添加附件的方式等等。

public void Main()
        {
            // Default Priority and SMTP Server Port
            int iPriority = 1;
            int smtpPort = 25;
             
            //User::PV_ATTACHED_FILE,User::PV_CONTENT,User::PV_MAIL_FROM,
            //User::PV_MAIL_TO,User::PV_MAIL_TO_CC,User::PV_TITLE
            String mailFrom = Dts.Variables["User::PV_MAIL_FROM"].Value.ToString();
            String mailTo = Dts.Variables["User::PV_MAIL_TO"].Value.ToString();
            String mailToCC = Dts.Variables["User::PV_MAIL_TO_CC"].Value.ToString();
            String mailTitle = Dts.Variables["User::PV_TITLE"].Value.ToString();
            String mailContent = Dts.Variables["User::PV_CONTENT"].Value.ToString();
            String mailAttachedFilePath = Dts.Variables["User::PV_ATTACHED_FILE"].Value.ToString();
            
            // User Information
            String loginUser = Dts.Variables["User::PV_LOGIN_USER"].Value.ToString();
            String loginPwd = Dts.Variables["User::PV_LOGIN_PWD"].Value.ToString();

            // Get SMTP Server Information from Connection Manager
            String smtpServer = Dts.Connections["CM_SMTP_126"].Properties["SmtpServer"].GetValue(Dts.Connections["CM_SMTP_126"]).ToString();

            try
            {
                SmtpClient smtpClient = new SmtpClient();
                MailMessage message = new MailMessage(); 
                MailAddress fromAddress = new MailAddress(mailFrom, "BIWORKTEST");

                string[] sEmailTo = Regex.Split(mailTo, ";");
                string[] sEmailToCC = Regex.Split(mailToCC, ";");

                smtpClient.Host = smtpServer;
                smtpClient.Port = smtpPort;

                // Login information
                System.Net.NetworkCredential myCredentials =
                   new System.Net.NetworkCredential(loginUser, loginPwd);
                smtpClient.Credentials = myCredentials;

                // Attachment 
                System.Net.Mail.Attachment attachment;
                attachment = new System.Net.Mail.Attachment(mailAttachedFilePath);
                message.Attachments.Add(attachment);
                 
                message.From = fromAddress;  

                // Multiple email to address
                if (sEmailTo != null)
                {
                    for (int i = 0; i < sEmailTo.Length; ++i)
                    {
                        if (sEmailTo[i] != null && sEmailTo[i] != "")
                        {
                            message.To.Add(sEmailTo[i]);
                        }
                    }
                }

                // Multiple cc address
                if (sEmailToCC != null)
                {
                    for (int i = 0; i < sEmailToCC.Length; ++i)
                    {
                        if (sEmailToCC[i] != null && sEmailToCC[i] != "")
                        {
                            message.To.Add(sEmailToCC[i]);
                        }
                    }
                }

                // Email priority
                switch (iPriority)
                {
                    case 1:
                        message.Priority = MailPriority.High;
                        break;
                    case 3:
                        message.Priority = MailPriority.Low;
                        break;
                    default:
                        message.Priority = MailPriority.Normal;
                        break;
                }

                message.Subject = mailTitle;
                message.IsBodyHtml = true;
                message.Body = mailContent;

                smtpClient.Send(message);
            }catch (Exception ex)
            {
                Dts.TaskResult = (int)ScriptResults.Failure;
            }
            // Close Script Task with success 
            Dts.TaskResult = (int)ScriptResults.Success; 
        }

保存并执行 SSIS 包,执行成功!

优先级别,标题,发送人等信息 -

附件信息和内容都可以看的到,包括在抄送栏中抄送给了自己,Package Start Time 的时间是来自虚机的时间,我虚机的时间还是 28日,这个是正确的 -

总结

从中可以看出,虽然在 SSIS 中提供了 SMTP 的连接方式,但是实际上它还是默认只允许通过 Windows 验证或者匿名访问的方式来访问。但是我们通过 Script Task 在 Script 中关联到了 SMTP 服务器,并同时写入用户名和密码,这样就实现了在 SSIS 中访问非域环境下第三方的 SMTP 服务器并通过身份验证且发送邮件的效果。

当然,这种方式在实际项目中可能用的并不是很多,因为项目中的邮件肯定是通过域验证的方式去访问更安全一些,毕竟系统信息的传递只能限制在域中。

在项目中使用邮件通知如是 Windows 验证的方式,有这几个点需要注意:

  1. 在开发与测试过程中,手动执行 SSIS Package 的这个用户要有域中发送邮件的权限,能够通过 Windows 验证。
  2. 当包部署到 SQL Agent Job 中后,执行 SQL Agent Job 的账号要有域发送邮件的权限,也必须能通过 Windows 验证。
  3. 如果不需要部署到 SQL Agent Job,那么就直接使用 Send Mail Task 通过 Windows 验证也可以直接发送错误消息提醒。

疑问

在这个例子中的代码是不是一定要像这样去访问 SMTP Server 的连接信息,感觉是不是多此一举? - 可以不用这样访问,其实很多 SMTP 的配置信息最为方便的是配置成变量,通过变量传递给 Script Task 就可以了。这里通过这样的一种方式来表示在 Script Task 中如何获取连接管理器的属性信息的,因为很多时候我们只知道如何去获取变量信息,这一点体现了 C# Script 的灵活性,我们在 Script 中可以做非常多的事情。包括这些访问 SMTP Server 如何使用 smtpClient 发送邮件的代码可以在网上找到现成的很多很多示例,而我们要做的事情就是大胆的灵活运用它们来解决我们的问题。

在我的这些文章中也提到了邮件处理相关的内容

微软BI 之SSRS 系列 - 报表邮件订阅中 SMTP 服务器匿名访问与 Windows验证, 以及如何成功订阅报表的实例

更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。

目录
相关文章
|
18天前
|
运维 监控 安全
宝塔Windows面板:轻松管理服务器的图形化神器
宝塔Windows面板是一款专为Windows服务器用户设计的图形化管理工具,旨在简化IIS配置、环境搭建与安全管理等复杂操作。它支持一键部署全栈运行环境(如IIS/Apache、PHP、MySQL等),提供可视化站点管理、安全防护与监控功能,并拥有丰富的插件生态。无论是个人站长、开发者还是中小企业,都能通过这款免费工具快速搭建网站、优化性能并强化安全性。尽管在高版本IIS兼容性和插件丰富度上略逊于Linux版,但其零门槛操作和全面功能仍使其成为理想的入门级服务器管理解决方案。
72 5
|
3月前
|
存储 Java 数据库
windows server2016搭建AD域服务器
windows server2016搭建AD域服务器
200 72
|
1月前
|
安全 数据库 Windows
解决Windows云服务器带宽和CPU利用率高的问题
本文针对Windows Server 2019 ×64系统,介绍如何排查云服务器带宽和CPU利用率过高的问题。通过任务管理器、性能监视器等工具定位高资源占用的进程,并根据进程是否正常采取相应措施。对于正常进程,建议优化或升级配置;对于异常进程,建议关闭进程并进行系统备份或还原。详细步骤包括使用“perfmon -res”查看资源使用情况,结合PID查找具体进程,分析处理后台任务、杀毒软件及应用程序的影响。
85 1
|
1月前
|
Linux 虚拟化 Docker
Linux服务器部署docker windows
在当今软件开发中,Docker成为流行的虚拟化技术,支持在Linux服务器上运行Windows容器。流程包括:1) 安装Docker;2) 配置支持Windows容器;3) 获取Windows镜像;4) 运行Windows容器;5) 验证容器状态。通过这些步骤,你可以在Linux环境中顺利部署和管理Windows应用,提高开发和运维效率。
190 1
|
1月前
|
Windows
Windows系统云服务器配置多用户登录
本教程介绍了在Windows云服务器上配置远程桌面服务的详细步骤,包括安装桌面会话主机和远程桌面授权、允许多用户远程连接以及配置新用户并加入远程桌面用户组。通过添加角色和功能、设置组策略以及管理用户权限,实现多用户同时登录和远程访问。按照指引操作,可顺利完成服务器的远程访问配置,提升管理和使用效率。
135 0
|
5月前
|
Android开发 数据安全/隐私保护 虚拟化
安卓手机远程连接登录Windows服务器教程
安卓手机远程连接登录Windows服务器教程
939 4
|
5月前
|
NoSQL Linux PHP
如何在不同操作系统上安装 Redis 服务器,包括 Linux 和 Windows 的具体步骤
本文介绍了如何在不同操作系统上安装 Redis 服务器,包括 Linux 和 Windows 的具体步骤。接着,对比了两种常用的 PHP Redis 客户端扩展:PhpRedis 和 Predis,详细说明了它们的安装方法及优缺点。最后,提供了使用 PhpRedis 和 Predis 在 PHP 中连接 Redis 服务器及进行字符串、列表、集合和哈希等数据类型的基本操作示例。
280 4
|
5月前
|
C# Windows
【Azure App Service】在App Service for Windows上验证能占用的内存最大值
根据以上测验,当使用App Service内存没有达到预期的值,且应用异常日志出现OutOfMemory时,就需要检查Platform的设置是否位64bit。
88 11
|
6月前
|
Apache 数据中心 Windows
将网站迁移到阿里云Windows系统云服务器,访问该站点提示连接被拒绝,如何处理?
将网站迁移到阿里云Windows系统云服务器,访问该站点提示连接被拒绝,如何处理?
|
6月前
|
域名解析 缓存 网络协议
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
下一篇
oss创建bucket