Delete Database Mail Messages from the msdb Database in SQL Server (T-SQL)

When you use Database Mail to send emails from SQL Server, email messages and their attachments are stored in the msdb database. You should periodically delete these messages to prevent the database from growing to large.

To delete these messages with T-SQL, use the sysmail_delete_mailitems_sp stored procedure.

You can delete mail messages based on their send request date (i.e. before a certain date) or based on their status. You can also delete all mail messages by using the current date as the request date.

View All Messages

First, let’s see what messages are in the msdb database.

SELECT 
    mailitem_id,
    sent_status,
    send_request_date
FROM msdb.dbo.sysmail_allitems;

Result:

+---------------+---------------+-------------------------+
| mailitem_id   | sent_status   | send_request_date       |
|---------------+---------------+-------------------------|
| 1             | failed        | 2020-08-24 02:40:48.093 |
| 2             | failed        | 2020-08-24 02:47:40.833 |
| 3             | sent          | 2020-08-24 03:58:57.887 |
| 4             | sent          | 2020-08-24 04:11:19.300 |
| 5             | failed        | 2020-08-29 03:28:53.873 |
| 6             | sent          | 2020-08-29 04:00:01.460 |
| 7             | failed        | 2020-08-29 04:44:54.720 |
| 8             | sent          | 2020-08-29 04:45:08.080 |
| 1006          | sent          | 2020-08-30 23:01:20.437 |
+---------------+---------------+-------------------------+

I didn’t return all columns for this view, as there would’ve been too much data to present here.

Delete Old Messages

To delete all messages that were sent before a certain date, use the @sent_before argument.

EXECUTE msdb.dbo.sysmail_delete_mailitems_sp   
    @sent_before = '2020-08-25';

Result:

(4 rows affected)

Note that the sysmail_delete_mailitems_sp procedure actually deletes emails based on the send_request_date rather than the sent_date. That’s why I’m using send_request_date when viewing the email messages.

View All Messages Again

Now when I query the sysmail_allitems view, the first four rows have disappeared.

SELECT 
    mailitem_id,
    sent_status,
    send_request_date
FROM msdb.dbo.sysmail_allitems;

Result:

+---------------+---------------+-------------------------+
| mailitem_id   | sent_status   | send_request_date       |
|---------------+---------------+-------------------------|
| 5             | failed        | 2020-08-29 03:28:53.873 |
| 6             | sent          | 2020-08-29 04:00:01.460 |
| 7             | failed        | 2020-08-29 04:44:54.720 |
| 8             | sent          | 2020-08-29 04:45:08.080 |
| 1006          | sent          | 2020-08-30 23:01:20.437 |
+---------------+---------------+-------------------------+

Delete Failed Messages

To delete all messages of a certain status, use the @sent_status argument.

Here’s an example of deleting all failed mail messages.

EXECUTE msdb.dbo.sysmail_delete_mailitems_sp   
    @sent_status = 'failed';

Result:

(2 rows affected)

View All Messages Again

Let’s check the sysmail_allitems view again.

SELECT 
    mailitem_id,
    sent_status,
    send_request_date
FROM msdb.dbo.sysmail_allitems;

Result:

+---------------+---------------+-------------------------+
| mailitem_id   | sent_status   | send_request_date       |
|---------------+---------------+-------------------------|
| 6             | sent          | 2020-08-29 04:00:01.460 |
| 8             | sent          | 2020-08-29 04:45:08.080 |
| 1006          | sent          | 2020-08-30 23:01:20.437 |
+---------------+---------------+-------------------------+

Delete All Messages

To delete all messages, use the @sent_date argument with a date value of GETDATE().

DECLARE @GETDATE datetime  
SET @GETDATE = GETDATE();
EXECUTE msdb.dbo.sysmail_delete_mailitems_sp
    @sent_before = @GETDATE;

Result:

(3 rows affected)

View All Messages Again

Let’s check the sysmail_allitems view again.

SELECT 
    mailitem_id,
    sent_status,
    send_request_date
FROM msdb.dbo.sysmail_allitems;

Result:

(0 rows affected)

Delete Events from the Database Mail Log

Note that sysmail_delete_mailitems_sp does not delete the corresponding entries in the Database Mail log. Use sysmail_delete_log_sp to delete events from the Database Mail log.