ptg 434 CHAPTER 15 Database Mail If the test fails, click Troubleshoot, and SMSS opens the “Troubleshooting Database Mail” Books Online topic, which provides a solid set of troubleshooting steps to get you started. If the mail is sent by SQL Server and successfully received in your client software’s inbox, you can proceed to the next section to learn how to use the sp_send_dbmail stored proce- dure to send email from T-SQL. Otherwise, look for more troubleshooting help in the “Related Views and Procedures” section of this chapter. Sending and Receiving with Database Mail If you’re building client applications that rely heavily on Database Mail, it’s crucial to gain an in-depth understanding of its underlying architecture. The following sections provide detailed information on its inner workings. The Service Broker Architecture As noted earlier, SQL Server relies on Service Broker (SSB) to activate the Database Mail process (DatabaseMail.exe) used to send mail. DatabaseMail.exe uses ADO.NET to connect to SQL Server and to read from and write to SSB queues (found in msdb) that hold send requests and send statuses in the form of typed SSB messages. You can view these queues (InternalMailQueue and ExternalMailQueue) in the Object Browser by selecting Service Broker and then the Queues folder. If you look a bit further in the Object Browser, you see how the mail transmission architecture is implemented (in part) as an SSB application, as you find the corresponding internal and external Database Mail SSB services (InternalMailService and ExternalMailService), SSB message types (SendMail and SendMailStatus), and a single SSB contract (SendMail/v1.0). SSB’s involvement with Database Mail works like this: 1. sp_send_dbmail (as the SSB initiator) is invoked and returns immediately. Under the covers, this adds an SSB message of type SendMail to the SSB mail queue, activating the undocumented internal stored procedure sp_ExternalMailQueueListener. Note that the mail message itself is saved to one or more of the msdb tables (such as sysmail_unsentitems and sysmail_attachments) if there are any attachments. 2. SSB launches DatabaseMail.exe (running under the credentials of the SQL Server service), which, in turn, connects back to SQL Server, using Windows Authentication. 3. DatabaseMail.exe reads the queued SSB send message, retrieves the mail message data, sends the email, and, finally (acting as the SSB target), places a message of type SendMailStatus in the mail status queue, reporting on the mail sending success or failure. 4. When there’s nothing left to be sent in the outbound queue, and the maximum process idle time has been reached, DatabaseMail.exe exits. Download from www.wowebook.com ptg 435 Sending and Receiving with Database Mail 15 By using SSB, Database Mail inherits the reliability of the SSB message transmission archi- tecture. If you want to learn more about Service Broker and how its constructs work, consult Chapter 49 (on the CD) for full details. Sending Email The SSB queues that Database Mail uses must first be enabled before you can send mail from a session. You do this by executing the msdb stored procedure sysmail_start_sp. This procedure is similar to its predecessor, xp_startmail (as it must be called before sending), except that it has no parameters and, of course, has nothing to do with MAPI. It returns 0 or 1, indicating success or failure. If you don’t call this procedure, you receive this error message: Mail not queued. Database Mail is stopped. Use sysmail_start_sp to start Database Mail. To temporarily disable SSB’s activation of the mail process, you execute sysmail_stop_sp (also with no parameters), which returns 0 or 1. If you send mail from code after this disabling this process, these messages will be queued. The external process is not started until sysmail_start_sp is called again. To check on the status of Database Mail, you can execute sysmail_help_status_sp (with no parameters). To check on the status of the queues, you execute sysmail_help_queues_sp. After you execute sysmail_start_sp, you’re ready to begin sending mail using the sp_send_dbmail stored procedure. It has 21 parameters, most of which are optional. As the query engine will tell you if you try to execute it with no or too few parameters, at least one of the following parameters must be specified: @body, @query, @file_attachments, or @subject. You also must specify one of the following: @recipients, @copy_recipients, or @blind_copy_recipients. NOTE For the following T-SQL examples to work, you must first configure a default profile using either the Database Mail Configuration Wizard or Database Mail stored proce- dures, as detailed earlier. A minimally parameterized test call might look like the following: exec msdb.dbo.sp_send_dbmail @body=’Testing ’, @subject=’A Test’, @recipients=’test@samspublishing.com’ go Mail Queued. Table 15.2 describes the parameters, their types, and the xp_sendmail parameters to which they may correspond, to help you along in converting your existing T-SQL code. Download from www.wowebook.com ptg 436 CHAPTER 15 Database Mail TABLE 15.2 Parameters for Database Mail Stored Procedure sp_send_dbmail Parameter Description xp_sendmail Parameter to Which It Corresponds @profile_name The sysname of the profile whose SMTP accounts will be used to send. Not available in xp_sendmail. @recipients A varchar(max) semicolon-delim- ited list of the recipients’ email addresses. Same as xp_sendmail. @copy_recipients A varchar(max) semicolon-delim- ited list of the carbon copy recipi- ents’ email addresses. Same as xp_sendmail. @blind_copy_recipients A varchar(max) semicolon-delim- ited list of the blind carbon copy recipients’ email addresses. Same as xp_sendmail. @subject The nvarchar(255) email subject. Same as xp_sendmail. @body The nvarchar(max) email body. Was @message in xp_sendmail. @body_format One of the two varchar (20) email format type strings, either ’HTML’ or ’TEXT’ (the default). Not available in xp_sendmail. @importance One of the three varchar (6) email importance strings, either ’Low’, ’Normal’ (the default), or ’High’. Not available in xp_sendmail. @sensitivity One of the four varchar (12) email sensitivity strings, either ’Normal’ (the default), ’Personal’, ’Private’,or ’Confidential’. Not available in xp_sendmail. @file_attachments An nvarchar(max) semicolon- delimited list of absolute paths to files to attach. Was @attachments in xp_sendmail. Download from www.wowebook.com ptg 437 Sending and Receiving with Database Mail 15 TABLE 15.2 Parameters for Database Mail Stored Procedure sp_send_dbmail Parameter Description xp_sendmail Parameter to Which It Corresponds @query An nvarchar(max) T-SQL code string to be executed when the message is sent. The code is executed in a different session than the calling session, so vari- able scope is a consideration. Same as xp_sendmail. @execute_query_database The sysname of the database in which the T-SQL in query is to be executed. Was @dbuse in xp_sendmail. @attach_query_result_as_file A bit value indicating whether the results of the T-SQL in query should be an attachment (1) or appended to the body (0; the default). Was @attach_results in xp_sendmail. @query_attachment_filename The nvarchar(255) filename for the attached query results (as per @query and @attach_query_result_as_file). If not specified, the generated file- name is arbitrary (usually QueryResults [some number].txt) In xp_sendmail, the first filename in @attachments was used. @query_result_header A bit value indicating whether the query result (1; the default) should include the column headers. Was @no_header in xp_sendmail. @query_result_width An int value (defaulting to 256; you specify a number between 10 and 32767) indicating how wide a line in the query results should be before line wrapping occurs. Was @width in xp_sendmail. @query_result_separator A char(1) value (defaulting to a space) that indicates the query results column separator. Was @separator in xp_sendmail. Download from www.wowebook.com ptg 438 CHAPTER 15 Database Mail TABLE 15.2 Parameters for Database Mail Stored Procedure sp_send_dbmail Parameter Description xp_sendmail Parameter to Which It Corresponds @exclude_query_output A bit value that indicates whether to suppress the query output (such as rowcounts, print statements, and so forth) from being printed on the query console. 0 (do not suppress) is the default. Was @no_output in xp_sendmail. @append_query_error A bit value that indicates whether to send the email if the query to be executed raises an error. If set to 1, the error message is appended to the query output, and the query window for the session also displays the error (“A severe error occurred on the current command. The results, if any, should be discarded.”). If set to 0 (the default), the message is not sent, and sp_send_dbmail returns 1. Not available in xp_sendmail, but similar to @echo_error. @query_no_truncate A bit value that indicates whether to truncate query results having long values (such as varchar(max), text, xml, and so on) greater than 256. It defaults to 0 (off). Microsoft warns that using this can slow things down, but it is the only way to properly send these types. Not available in xp_sendmail. @mailitem_id An output parameter, an int value indicating the unique mailitem_id of the message. You see this as a column in the views discussed in the section “Related Views and Procedures,” later in this chapter. Not available in xp_sendmail. Note that the @type and @set_user parameters for xp_sendmail are not available. @type, of course, is obsolete because it is MAPI specific. @set_user is also obsolete because the content of the T-SQL to be executed may contain an EXECUTE AS statement. Download from www.wowebook.com ptg 439 Sending and Receiving with Database Mail 15 Now that you’re familiar with the flurry of mail sending options, let’s look at a few exam- ples and then examine how to track your sent messages by using the system views. Both of the following examples rely on sending via the default profile of the current user context. If the user has a default private profile assigned, it is used. If not, the default public profile is used (as in these examples). If there is no default public profile, an error is raised. The example shown in Listing 15.1 sends an email containing an xml result to a recipient as an attached Extensible Application Markup Language (XAML) document, retrieved from the AdventureWorks2008.Production.Illustration column. LISTING 15.1 Sending XML as an Attachment with Database Mail USE AdventureWorks2008 GO DECLARE @subject nvarchar(255), @body varchar(max), @query nvarchar(max), @IllustrationId int, @query_attachment_filename nvarchar(255), @mailitem_id int SELECT @IllustrationId = pi.IllustrationId, @subject = ‘XAML for “‘ + pm.Name + ‘“ attached. ‘ FROM Production.Illustration pi JOIN Production.ProductModelIllustration pmi ON pmi.IllustrationId = pi.IllustrationId JOIN Production.ProductModel pm ON pm.ProductModelID = pmi.ProductModelID SELECT @body = N’Attached, please find the XAML diagram for illustration #’ + CAST(@IllustrationId as nvarchar(10)) + ‘. A XAML browser plug-in is required to view this file.’ SELECT @query = N’SELECT Diagram FROM Production.Illustration WHERE IllustrationId = ‘ + CAST(@IllustrationId as nvarchar(10)) SELECT @query_attachment_filename = N’PM_’ + CAST(@IllustrationId as nvarchar(10)) + ‘.xaml’ Download from www.wowebook.com ptg 440 CHAPTER 15 Database Mail exec msdb.dbo.sp_send_dbmail @subject=@subject, @body=@body, @recipients=’test@samspublishing.com’, @query=@query, @execute_query_database=’AdventureWorks2008’, @attach_query_result_as_file=1, @query_attachment_filename=@query_attachment_filename, @query_no_truncate=1, @exclude_query_output=1, @query_result_width=32767, @mailitem_id=@mailitem_id OUTPUT SELECT sent_status, sent_date FROM msdb.dbo.sysmail_allitems WHERE mailitem_id = @mailitem_id GO sent_status sent_date —————- ————- unsent NULL (1 row(s) affected) Note that you must set @query_no_truncate to 1 and @query_result_width to the maximum (to be safe) value for the attached query results to contain consistently well- formed XML. In addition, you should not include any carriage returns or line feeds in the body of the message, or the SMTP servers may not be able to send it. The example in Listing 15.2 sends some query results as a comma-separated value (CSV) file that can be imported into programs such as Microsoft Excel. (You need to use the Get External Data command to accomplish this with Excel 9.) LISTING 15.2 Sending CSV Data as an Attachment with Database Mail USE AdventureWorks2008 GO DECLARE @mailitem_id int, @tab char(1) SET @tab = char(13) exec msdb.dbo.sp_send_dbmail @subject=’D. Margheim, Contact Info’, @body=’Attached is Diane Margheim’’s contact info, in CSV format.’, @recipients=’test@samspublishing.com’, @query=N’SELECT BusinessEntityID, Title, FirstName, MiddleName, LastName FROM Person.Person WHERE BusinessEntityId = 8’, @execute_query_database=’AdventureWorks2008’, Download from www.wowebook.com ptg 441 Using SQL Server Agent Mail 15 @attach_query_result_as_file=1, @query_attachment_filename=’DMargheim.csv’, @exclude_query_output=1, @query_result_separator=’,’, @mailitem_id=@mailitem_id OUTPUT SELECT sent_status, sent_date FROM msdb.dbo.sysmail_allitems WHERE mailitem_id = @mailitem_id GO sent_status sent_date —————- ————- unsent NULL (1 row(s) affected) Notice that in both of these code listings, the values selected from the sent_status and sent_date columns of sysmail_allitems indicate that the mail has not yet been sent. The reason is that mail sending (like all other SSB messaging) is asynchronous: The message is immediately queued, and the Mail process later picks it up and sends it. To find out more about system views such as sysmail_allitems, see the section “Related Views and Procedures,” later in this chapter. Receiving Email The only way for SQL Server 2008 to receive email is by using the legacy stored proce- dures, such as sp_processmail, with SQL Mail. Database Mail does not support receiving incoming messages because there is no IMAP or POP3 support. This may have something to do with the fact that receiving email can represent a major security risk. Imagine what a denial-of-service attack on a database cluster could do to an organization. Or consider the danger of an incoming email request resulting in the execution of a query such as DROP DATABASE X. Most SQL Server data is too precious to jeopardize in this manner. Microsoft has also made it clear that SQL Mail will be phased out in the next release of SQL Server. Plus, there are many better alternatives to using this methodology, such as using native Web services (as discussed in Chapter 48, “SQL Server Web Services”), using .NET CLR-integrated assembly code (as discussed in Chapter 45, “SQL Server and the .NET Framework”), or building a dedicated Service Broker application (as discussed in Chapter 49). Using SQL Server Agent Mail As with SQL Server 2000, SQL Server 2008’s Agent has the capability to send email notifi- cations. They may be triggered by alerts or scheduled task completions, such as jobs. SQL Server 2008 provides the option of using either SQL Mail or Database Mail to do the sending, but SQL Mail will soon be phased out, and Database Mail is by far the more robust choice. As with Database Mail, SQL Server Agent Mail is turned off by default, and you must configure it via SMSS or T-SQL, as described in the following sections. Download from www.wowebook.com ptg 442 CHAPTER 15 Database Mail Job Mail Notifications The following sections show an example in which you create a SQL Server Agent Mail operator that SQL Server Agent will notify when a job completes. Creating an Operator First, you need to create an operator. To do so, using the Object Browser, you expand the SQL Server Agent node and then right-click the Operators folder and select New Operator. Then you should name this new operator Test Database Mail Operator and provide an email address for testing purposes in the Email Name text box. You can use any valid email address you can access with your email client software. You click OK to save the new operator. Enabling SQL Agent Mail Next, you need to enable SQL Server Agent to use Database Mail. You right-click the SQL Server Agent node and then select Properties. On the left side of the Properties dialog that appears (see Figure 15.2), you click the Alert System link. Under the Mail Session group, you check the Enable Mail Profile check box. In the Mail System drop-down list, you select Database Mail (this is also the place where you can choose SQL Mail, if you desire). In the Mail Profile drop-down list, you select the default SQL 2008 profile you created earlier and then click OK. By doing this, you are telling SQL Server Agent to use the SMTP servers in your default profile to send email. You need to restart SQL Server Agent by using the right-click menu. FIGURE 15.2 Using the SQL Server Agent Properties dialog to configure Database Mail. Download from www.wowebook.com ptg 443 Using SQL Server Agent Mail 15 Creating the Job Next, you need to create the job. You begin by right-clicking the Jobs folder and then selecting New Job. You should name the job Database Mail Test Job and select an owner. Then you should check the Enabled check box near the bottom of the dialog and click the Steps link on the left side of the dialog. Next, you click the New button and add a step named Test Mail Step 1. You should leave the type as Transact-SQL and then change the database selection to AdventureWorks2008. In the Command text box, you enter the following code: RAISERROR(‘This is simply a test job.’, 10, 1) Next, you click the Advanced link on the left side of the dialog, and in the On Success Action drop-down list, you select Quit the Job Reporting Success. Then you click the Notifications link on the left side of the dialog. Next, under Actions to Perform When the Job Completes, you check the Email check box and select the operator you just created. From the drop-down to the right, you select When the Job Completes and then click OK to save the job. Testing the Job-Completion Notification To test the email configuration and notification you just set up, you right-click the job name under the Jobs folder and then select Start Job. If everything is set up properly, an email message appears in your inbox, indicating the job’s successful completion. Its body text might look something like this: JOB RUN: ‘Database Mail Test Job’ was run on 5/7/2009 at 8:37:22 PM DURATION: 0 hours, 0 minutes, 0 seconds STATUS: Succeeded MESSAGES: The job succeeded. The Job was invoked by User [TestUser]. The last step to run was step 1 (Test Mail Step 1). Alert Mail Notifications As another example, in the following sections, you’ll create a simple user-defined alert that you can trigger directly from T-SQL script. Creating an Alert You start by creating an alert. To do this, you use the Object Browser to expand the SQL Server Agent node; then you right-click the Alerts node and select New Alert. In the Alert Properties dialog that appears (see Figure 15.3), you name the new alert Database Mail Test Alert and make sure the Enabled check box is checked. For the Event type, you leave the selection on SQL Server Event Alert. Under Event Alert Definition, select AdventureWorks2008 from the Database Name drop-down list, and then click the Severity option button and choose 010 - Information. Next, check the Raise Alert When Message Contains check box and type the phrase This is a Test in the Message Text text box. Download from www.wowebook.com . dedicated Service Broker application (as discussed in Chapter 49). Using SQL Server Agent Mail As with SQL Server 2000, SQL Server 2008 s Agent has the capability to send email notifi- cations. They. DATABASE X. Most SQL Server data is too precious to jeopardize in this manner. Microsoft has also made it clear that SQL Mail will be phased out in the next release of SQL Server. Plus, there. or scheduled task completions, such as jobs. SQL Server 2008 provides the option of using either SQL Mail or Database Mail to do the sending, but SQL Mail will soon be phased out, and Database