我在 SQL 2005 机器上运行数据库邮件。有时邮件无法发送,通过查询 msdb.dbo.sysmail_mailitems 表我可以看到有已发送状态为“2”的项目,这是失败的。我可以查询sysmail_faileditems表来列出所有失败的邮件。
无论如何我可以处理/重新发送这些失败的邮件吗?
每天创建一个作业来查询这个表是否合理,通过使用CURSOR来一个一个地重新发送邮件,然后将它们从表中一个一个地删除。
如果您有更好的建议/想法,请告诉我。
非常感谢卡尔
我在 SQL 2005 机器上运行数据库邮件。有时邮件无法发送,通过查询 msdb.dbo.sysmail_mailitems 表我可以看到有已发送状态为“2”的项目,这是失败的。我可以查询sysmail_faileditems表来列出所有失败的邮件。
无论如何我可以处理/重新发送这些失败的邮件吗?
每天创建一个作业来查询这个表是否合理,通过使用CURSOR来一个一个地重新发送邮件,然后将它们从表中一个一个地删除。
如果您有更好的建议/想法,请告诉我。
非常感谢卡尔
首先,我建议您查询 faileditems 以确定您失败的主要原因:
SELECT items.subject ,
items.last_mod_date ,
l.description
FROM dbo.sysmail_faileditems AS items
INNER JOIN dbo.sysmail_event_log AS l ON items.mailitem_id = l.mailitem_id
如果没有什么可以轻松修复,您可以通过循环遍历 sysmail_mailitems 表并根据 faileditems 日志中的故障类型(超时等)重新发送它们 - 此博客建议中的一些很好的示例:http://justgeeks.blogspot.co.uk/2007/05/resending-sysmail-emails.html
我个人最喜欢的:
CREATE PROCEDURE sysmail_resend_timeout
AS
BEGIN
SET NOCOUNT ON
DECLARE SYSMAIL_LOG_RESEND_CURSOR CURSOR READ_ONLY
FOR
SELECT DISTINCT
l.mailitem_id ,
p.name ,
m.recipients ,
m.subject ,
m.body_format ,
m.body
FROM msdb.dbo.sysmail_log l WITH ( NOLOCK )
JOIN msdb.dbo.sysmail_mailitems m WITH ( NOLOCK ) ON m.mailitem_id = l.mailitem_id
JOIN msdb.dbo.sysmail_profile p WITH ( NOLOCK ) ON p.profile_id = m.profile_id
WHERE l.event_type = 3
AND m.sent_status = 2
AND l.description LIKE '%The operation has timed out%'
ORDER BY l.mailitem_id
OPEN SYSMAIL_LOG_RESEND_CURSOR
WHILE ( 1 = 1 )
BEGIN
DECLARE @mailitem_id INT ,
@profile_name NVARCHAR(128) ,
@recipients VARCHAR(MAX) ,
@subject NVARCHAR(255) ,
@body_format VARCHAR(20) ,
@body NVARCHAR(MAX)
FETCH NEXT FROM SYSMAIL_LOG_RESEND_CURSOR INTO @mailitem_id, @profile_name, @recipients, @subject, @body_format, @body
IF NOT @@FETCH_STATUS = 0
BEGIN
BREAK
END
PRINT CONVERT(VARCHAR, GETDATE(), 121) + CHAR(9) + CONVERT(VARCHAR, @mailitem_id) + CHAR(9) + @recipients
EXEC msdb.dbo.sp_send_dbmail
@profile_name = @profile_name ,
@recipients = @recipients ,
@subject = @subject ,
@body_format = @body_format ,
@body = @body
UPDATE msdb.dbo.sysmail_mailitems
SET sent_status = 3
WHERE mailitem_id = @mailitem_id
END
CLOSE SYSMAIL_LOG_RESEND_CURSOR
DEALLOCATE SYSMAIL_LOG_RESEND_CURSOR
END
GO
我知道这并不是您真正想听到的答案,但我总是尝试将邮件功能解耦。如果需要及时发送邮件,我可能会使用触发器来生成外部进程,但我让外部脚本完成发送邮件的实际工作。这样,MTA 会处理瞬时连接错误,我不必担心特殊的簿记算法。