SQL Server 2005数据库邮件失败

时间:2012-04-10 15:38:41

标签: sql sql-server sql-server-2005 sqlmail

我在SQL 2005框上运行数据库邮件。偶尔邮件无法发送,通过查询msdb.dbo.sysmail_mailitems表,我可以看到有一个sent_status为“2”的项目,这是失败的。我可以查询 sysmail_faileditems 表,列出所有失败的邮件。

无论如何我可以处理/重新发送这些失败的邮件吗?

通过使用 CURSOR 逐个重新发送邮件来创建每日作业来查询此表是否合理,然后逐个从表中删除它们。< / p>

如果您有更好的建议/想法,请告诉我。

非常感谢Karl

2 个答案:

答案 0 :(得分:1)

首先,我建议您查询失败项目以确定失败的主要原因:

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 

答案 1 :(得分:0)

我知道这不是你想要听到的答案,但我总是尝试解耦邮件功能。如果邮件发送需要及时,我可能会使用触发器来生成外部进程,但我让外部脚本完成发送邮件的实际工作。这样,瞬态连接错误由MTA处理,我不必担心特殊的簿记算法。