如何查找SQL Server数据库邮件生成的特定消息的来源
SQL Server Database Mail 未知发件源排查思路
- 补全邮件元数据维度排查
不要仅依赖msdb.dbo.sysmail_allitems的send_request_user字段,关联查询msdb.dbo.sysmail_mailitems、msdb.dbo.sysmail_log两张表,按已知的发送时间、主题、收件人定位到对应mailitem_id,重点提取以下字段:- 发信时的
client_app_name、host_name、suser_sname上下文信息(部分版本会在日志表中留存) - 邮件头原始信息,看有没有带X-Sender类的来源标识
- 如果
send_request_user是SQL服务运行账号、SQL代理服务账号,说明发信逻辑大概率不在用户自定义的普通数据库对象中
- 发信时的
- 补查SQL侧容易遗漏的发信逻辑载体
你之前排查了作业、存储过程、触发器、VS部署包,还需要覆盖以下容易漏的对象:- SSISDB目录下部署的所有SSIS包、SQL Server维护计划(维护计划本质是自动生成的SSIS包,对应的作业名通常带随机字符后缀,很容易被忽略)
- 服务器级触发器、Service Broker队列绑定的激活存储过程、数据库内注册的CLR程序集(CLR程序集可能内嵌发信逻辑,普通的模块定义检索扫不到)
- 不要手动逐个翻对象,执行全库范围的定义检索,避免漏检:
EXEC sp_MSforeachdb ' USE [?]; SELECT ''?'' AS 所属数据库, o.name AS 对象名, o.type_desc AS 对象类型 FROM sys.sql_modules m INNER JOIN sys.objects o ON m.object_id = o.object_id WHERE m.definition LIKE ''%sp_send_dbmail%'' ' - 跨实例链接服务器的反向排查:检查其他SQL实例有没有通过链接服务器调用本实例
sp_send_dbmail的作业或逻辑
- 实时抓包定位调用源
如果邮件是固定周期发送,不要只查历史存量对象,直接在实例上开扩展事件会话监控sp_send_dbmail的调用:- 新建扩展事件会话,捕获
rpc_starting、sp_statement_starting事件 - 过滤条件设为调用的存储过程名包含
sp_send_dbmail - 事件触发时自动记录对应的
client_app_name、client_hostname、nt_username、session_id,可以直接定位到发信请求来自哪台机器、哪个进程
如果发信频率很低,可以换成服务器级审计规则长期监控,不用一直开事件会话占用资源
- 新建扩展事件会话,捕获
- 排查非SQL托管的调度逻辑
- 检查数据库服务器本地的Windows任务计划程序,排查所有定时执行的PowerShell、bat、vbs脚本,很多运维写的轻量告警脚本不会注册成SQL代理作业,直接通过任务计划调度连库发信
- 结合扩展事件抓到的客户端主机名,排查对应机器上部署的应用服务、定时任务,很多业务系统会直接调用数据库的
sp_send_dbmail发业务通知,逻辑不会存在数据库侧的对象里
内容的提问来源于stack exchange,提问作者K r
相关产品推荐
相关产品推荐

