Sending Emails in SQL Server for Beginners

A very powerful, but often overlooked feature of SQL Server is the ability to send emails in T-SQL. This feature has the ability to send to multiple recipients, as well as attach data simply by just providing a query and the name you want for the file. Although it sounds simple, the setup and the built-in MS stored procedure can be both hard and intimidating to understand. The goal of this article is to provide a simple overview of how to set up the email feature as well as sending a simple email and attaching data as a text file.

Step 1: Setting up the Email Client

Before you can send emails in T-SQL, the server needs to know what account you are going to be sending from e.g. your email address.

To set this up, open SQL Server Management Studio (SSMS), expand the “Management” Tree folder, and right click on “Database Mail” and select “Configure Database Mail”.
When you get to the configuration wizard, do the following:

  1. Click next on the welcome page (if applicable)
  2. Choose the “Set up Database Mail by performing the following tasks” radio button and click next
  3. you might be prompted that the database mail feature was not configured and you need to do so. If that message pops up, click yes
  4. For the profile name, enter a name that you will remember to associate with your email address…think of this as a nickname e.g. “mattsEmail”
  5. Under the section of the window for SMTP accounts, click the “Add” button to the right
  6. Under the various fields in the next page, enter all your information needed.
    • Note: To find out your SMTP server address, goto your email host page, and it should be listed in settings. If its hard to find, do a simple google search for “SMTP server for Gmail” or “SMTP Server for outlook” depending on who your provider is
  7. Once you have finished entering your profile information, click OK
  8. Click next on the main wizard to bring you to the Public profiles page
  9. On the public profiles page, check the “public” box if you want your profile to be accessible by other users on the server that are not sysadmins
    • Note: You can also select “Yes” on the “Default Profile” drop-down box if you want this to be the default email account to send emails from
  10. Click next and you will be on the final configuration page. On this page, you can specify file extensions to exclude as attachments and the max file attachment size.
    • Note: The default maximum file size is 1 MB, which is pretty small. I usually add an extra 0 to the max file size line to bump it to 10 MB
  11. Once you are done configuring the extras, click Next and Finish

Step 2: Testing the email profile/account
Once you have gone through this setup, it’s time to run a test email to ensure the account is setup correctly. To do this, right click on the “Database Mail” item on the explorer tree in SSMS and click “Send Test E-mail…” You will be presented with a very simple pop-up asking you for the address you want to send the test email to. Enter an address you can check and then click the “Send Test E-Mail” button.
The SQL Server email function is pretty quick and you should see your email get sent and received in no less than a minute. If you received the email, you are all set and are ready to go to the last step in this article. If you have not received an email in 2 minutes, right click on the database mail folder and go back to the configuration. Odds are an SMTP server is not correct, or the authentication mechanism chosen is not correct.
Step 3: Sending an Email in T-SQL

The procedure to send an email is “msdb.dbo.sp_send_dbmail”. This procedure contains all the parameters needed to provide an email TO, CC, & BCC list, as well as set the email subject, body, and attach data by providing a query. What really makes this powerful is the parameterization of all the inputs…Think about it! You can automate you stored procedures to send specific data to distribution lists, alert users when a long running job has finished processing, and offload the constant emails and phone calls you get asking when a report will be ready.

Before we get into the examples, we will break down the sp_send_dbmail procedure and go over the parameters that are relevant for this exercise.

sp_send_dbmail parameters (relevant ones)

  1. @profile
    • This is the profile name you set up in step 1 above when configuring the email client. If you have multiple email addresses that you would want to send from, you can use the profile to function as a nickname for your different email accounts e.g. “work_profile”, “dev_alerts_profile”.
  2. @recipients
    • This is your “TO” list. You supply email addresses and separate multiple email addresses using a semi-colon e.g. “;”
  3. @copy_recipients
    • This is your “CC” list. You supply email addresses the same way you would in the TO list
  4. @blind_copy_recipients
    • This is your “BCC” list. Same rules apply like the recipients and blind copy recipients
  5. @subject
    • This is the email subject.
  6. @body
    • Your email message
  7. @attach_query_result_as_file
    • Flag indicating if you want to attach a query output as an attachment
  8. @query
    • The query you want to attach
  9. @query_result_header
    • Flag indicating if you want to include column headers in the attachment
  10. @query_attachment_filename
    • The name you want the attachment to be e.g. “sls_rpt.txt”
  11. @query_result_separator
    • This is the column delimiter

To illustrate how to use the sp_send_dbmail procedure, we will provide 2 examples. The first one sends to a simple distribution list, just formatting the email subject and body. The second example takes it a step further and attaches a query results-set as a file.

Example 1: Sending a simple email

EXEC msdb.dbo.sp_send_dbmail

@recipients = ';'
,@subject = 'Daily Report'
,@body = '
Good morning,
Please note that today's report will be delayed.'

In this example above, you separate multiple recipients using a semi-colon. Other than that, the other parameters are pretty straight-forward

Example 2: Sending an email and attaching data

EXEC msdb.dbo.sp_send_dbmail

@recipients = ''
,@subject = 'test email'
,@body = 'test email message'
,@attach_query_result_as_file = 1
,@query = 'select top 10 * from AdventureWorks2014.person.address'
,@query_result_header = 1
,@query_attachment_filename = 'test.txt'
,@query_result_separator = '|'

In this second example, we queries 10 rows from the adventureworks database, called the attachment “test.txt”, indicated we wanted to include headers, and we wanted the delimiter to be a pipe.

Sending Emails in SQL Server for Beginners

Getting Real Time Feedback in SQL Stored Procedures

SQL Stored Procedures can be tough to debug sometimes. In typical scenarios, you have written a procedure that has been running fine for a few weeks, then all the sudden, it’s slower than molasses going up hill. How do you know which part of the procedure is the bottleneck? You could put a bunch of print statements between each section of the procedure, but the problem is that print statements do not show up until the procedure finishes.

Luckily, SQL Server has a nifty function called raiserror. Wait…raiserror?? “I Don’t want to raise an error”. Don’t worry! Raiserror can raise event messages that are not considered errors and instead act as print statements, but in real time!

To send back real time feedback in the middle of a procedure, simply write:

raiserror('This is the message I want to show up in real time!', 0, 1) with NOWAIT

The 0 and the 1 following the message report the error and severity, which in this case we want to report as 0 for the error since it’s not really an error we are reporting. The NOWAIT argument tells SQL Server to flush the buffer immediately and show the statement.

This statement can be extended further though to give you timestamps while you fire messages back to the client during a procedure run. Below is a simple stored procedure called “sp_Feedback” which takes a message and then runs the raiserror function to fire back a formatted message to the user. This procedure has helped me find bottlenecks quickly, and allowed me to re-tweak the sections of the procedure that need it, and then re-publish the procedure and get it back on the fast-fast-fast path. Have fun!

CREATE proc [dbo].[sp_Feedback]
	 @msg varchar(8000)
	,@row_cnt bigint = null
	set @msg = concat(format(getdate(),'yyyy-MM-dd hh:mm:ss'),' -> ',@msg)
	if @row_cnt is not null
		set @msg = concat(@msg,' | rows affected: ',format(@row_cnt,'#,###'))
	raiserror(@msg,0,1) with nowait;

	-- exec sp_Feedback 'test'
	-- exec sp_Feedback 'test2', 50000


Getting Real Time Feedback in SQL Stored Procedures