SQL Server Stored Procedure to Send Email - sql

This is my first attempt at writing a stored procedure that emails someone. When trying to execute I get these errors:
Msg 102, Level 15, State 1, Procedure EmailTodaysErrors, Line 14
Incorrect syntax near '#MailServer'.
Msg 137, Level 15, State 2, Procedure EmailTodaysErrors, Line 26
Must declare the scalar variable "#mailserver".
Msg 137, Level 15, State 2, Procedure EmailTodaysErrors, Line 33
Must declare the scalar variable "#Body".
The code that I am using which is causing this is:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE EmailTodaysErrors
#SenderName varchar(100),
#SenderAddress varchar(100),
#RecipientName varchar(100),
#RecipientAddress varchar(100),
#Subject varchar(200),
#Body varchar(8000)
#MailServer varchar(100) = 'localhost'
AS
SET NOCOUNT ON;
declare #oMail int --Object reference
declare #resultcode int
EXEC #resultcode = sp_OACreate 'CDONTS.NewMail', #oMail OUT
if #resultcode = 0
BEGIN
EXEC #resultcode = sp_OASetProperty #oMail, 'RemoteHost', #mailserver
EXEC #resultcode = sp_OASetProperty #oMail, 'FromName', #SenderName
EXEC #resultcode = sp_OASetProperty #oMail, 'FromAddress', #SenderAddress
EXEC #resultcode = sp_OASetProperty #oMail, 'From', #SenderAddress
EXEC #resultcode = sp_OASetProperty #oMail, 'To', #RecipientAddress
EXEC #resultcode = sp_OASetProperty #oMail, 'Subject', #Subject
EXEC #resultcode = sp_OASetProperty #oMail, 'Body', #Body
EXEC #resultcode = sp_OAMethod #oMail, 'Send', NULL
EXEC sp_OADestroy #oMail
END
set nocount off
GO

You're missing a comma after the #body line, which is throwing off your declarations.
Add it here:
#Body varchar(8000), -- HERE
#MailServer varchar(100) = 'localhost'

Don't use sp_oa_family to send mail, there is already a built-in solution with SQL Server: Database Mail. Simply configure Database Mail properly on your server, then call sp_send_dbmail.

There's a comma missing in your parameters :
#Body varchar(8000), ---- HERE
#MailServer varchar(100) = 'localhost'

From my blog post, Create a Database Mail Configuration Using T-SQL Script, published 05 Feb 2018:
--Sending Test Mail
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'TestProfile',
#recipients = 'To Email Here',
#copy_recipients ='CC Email Here', --For CC Email if exists
#blind_copy_recipients= 'BCC Email Here', --For BCC Email if exists
#subject = 'Mail Subject Here',
#body = 'Mail Body Here',
#body_format='HTML',
#importance ='HIGH',
#file_attachments='C:\Test.pdf'; --For Attachments if exists

Related

Why doesn't a SQL trigger have permissions to use e-mail? [duplicate]

Is there a way to provide access to users in my database to execute msdb.dbo.sp_send_dbmail without needing to add them to the MSDB database and the DatabaseMailUserRole?
I've tried this:
ALTER PROCEDURE [dbo].[_TestSendMail]
(
#To NVARCHAR(1000),
#Subject NVARCHAR(100),
#Body NVARCHAR(MAX)
)
WITH EXECUTE AS OWNER
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail #profile_name = N'myProfile',
#recipients = #To, #subject = #Subject, #body = #Body
END
But I get this error:
The EXECUTE permission was denied on the object 'sp_send_dbmail', database 'msdb', schema 'dbo'.
Thanks!
Your approach is OK, but your wrapper proc must be in the msdb database.
Then, you execute "EXEC msdb.dbo._TestSendMail"
This still leave the issue of permissions on dbo._TestSendMail in msdb.
But public/EXECUTE will be enough: it only exposes the 3 parameters you need.
If in doubt, add WITH ENCRYPTION. This is good enough to stop anyone without sysadmin rights viewing the code
USE msdb
GO
CREATE PROCEDURE [dbo].[_TestSendMail]
(
#To NVARCHAR(1000),
#Subject NVARCHAR(100),
#Body NVARCHAR(MAX)
)
-- not needec WITH EXECUTE AS OWNER
AS
BEGIN
EXEC dbo.sp_send_dbmail #profile_name = N'myProfile',
#recipients = #To, #subject = #Subject, #body = #Body
END
You actually can do it with a certificate signed stored procedure and it doesn't have to be in msdb to do so:
CREATE DATABASE TestDBMail
GO
USE [TestDBMail]
GO
CREATE PROCEDURE [dbo].[TestSendMail]
(
#To NVARCHAR(1000),
#Subject NVARCHAR(100),
#Body NVARCHAR(MAX)
)
WITH EXECUTE AS OWNER
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = N'Database Mail Profile',
#recipients = #To,
#subject = #Subject,
#body = #Body
END
GO
-- This should fail
EXECUTE [dbo].[TestSendMail] 'someemail#domain.com', 'test', 'body'
-- Create a certificate to sign stored procedures with
CREATE CERTIFICATE [DBMailCertificate]
ENCRYPTION BY PASSWORD = '$tr0ngp#$$w0rd'
WITH SUBJECT = 'Certificate for signing TestSendMail Stored Procedure';
GO
-- Backup certificate so it can be create in master database
BACKUP CERTIFICATE [DBMailCertificate]
TO FILE = 'd:\Backup\DBMailCertificate.CER';
GO
-- Add Certificate to Master Database
USE [master]
GO
CREATE CERTIFICATE [DBMailCertificate]
FROM FILE = 'd:\Backup\DBMailCertificate.CER';
GO
-- Create a login from the certificate
CREATE LOGIN [DBMailLogin]
FROM CERTIFICATE [DBMailCertificate];
GO
-- The Login must have Authenticate Sever to access server scoped system tables
-- per http://msdn.microsoft.com/en-us/library/ms190785.aspx
GRANT AUTHENTICATE SERVER TO [DBMailLogin]
GO
-- Create a MSDB User for the Login
USE [msdb]
GO
CREATE USER [DBMailLogin] FROM LOGIN [DBMailLogin]
GO
-- Add msdb login/user to the DatabaseMailUserRole
EXEC msdb.dbo.sp_addrolemember #rolename = 'DatabaseMailUserRole', #membername = 'DBMailLogin';
GO
USE [TestDBMail]
GO
-- Sign the procedure with the certificate's private key
ADD SIGNATURE TO OBJECT::[TestSendMail]
BY CERTIFICATE [DBMailCertificate]
WITH PASSWORD = '$tr0ngp#$$w0rd';
GO
-- This will succeed
EXECUTE [dbo].[TestSendMail] 'someemail#domain.com', 'test', 'body'
/*
-- Cleanup
USE [msdb]
GO
DROP USER [DBMailLogin]
GO
USE [master]
GO
DROP LOGIN [DBMailLogin]
DROP CERTIFICATE [DBMailCertificate]
DROP DATABASE [TestDBMail]
-- Delete the certificate backup from disk
*/
One possible solution is to encapsulate the mailing as a stored procedure e.g. mail_error_as_MAILER (wich you will later call)
and another stored procedure
e.g.
ALTER PROCEDURE [dbo].[mail_error](#error_ID int)
SET NOCOUNT ON
declare #rc int
declare #object int
declare #src varchar(255)
declare #desc varchar(255)
declare #osql_cmd varchar(1000)
-- create shell object
exec #rc = sp_oacreate 'wscript.shell', #object out
if #rc0
begin
exec sp_oageterrorinfo #object, #src out, #desc out
return
END
DECLARE #user VARCHAR(50)
DECLARE #password VARCHAR(50)
DECLARE #database VARCHAR(50)
DECLARE #server VARCHAR(50)
DECLARE #sql varchar(200)
SET #user=MAILER,#password=XXXXXX,#database=XXXXXX,#server=XXXXX
SET #sql= 'EXEC mail_ERROR_as_MAILER #error_ID=' + CAST(#error_id as varchar(10))
set #osql_cmd='osql -U'+#user+' -P'+#password+' -d'+#database+' -S"'+#server+'" -Q"'
+#sql+'"'
exec #rc= sp_oamethod #object, 'run', null, #osql_cmd
--print #rc
if #rc0
begin
exec sp_oageterrorinfo #object, #src out, #desc out
return
end
-- destroy shell object
exec sp_oadestroy #object
But this requires:
* hardcoding password (make sure users cannot view definition of stored procedure ...)
* giving users access to sp_oacreate etc... (opens up other security problems e.g. DOS)
that way they can only use the mail the way you want to without giving them permission to mail other things.
Or safer,
let users put mail in some kind of mail_queue(wich you can control what they can put in) and have an agent acount send these mails periodically
Or: give them permission to mail but take a big club with rusted spikes on abuse

OLE Procedures, query executed succesfully; No File Extracted

I am trying to extract a blob file from SQL Server. I was able to get it to execute successfully but when I look in my Desktop\consol\output directory, the file isn't there (refreshed, still nothing). Here is the code:
SELECT * FROM FileWarehouse
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
DECLARE #SQLIMG VARCHAR(MAX),
#File VARBINARY(MAX),
#OpPath VARCHAR(MAX),
#ObjectToken INT
SELECT #File = StoredFile FROM [dbo].[FileWarehouse] WHERE Id= 157994
SET #OpPath = 'C:\Users\Nick\Desktop\consol\output\marksheet.doc'
EXEC sp_OACreate 'ADODB.Stream', #ObjectToken OUTPUT
EXEC sp_OASetProperty #ObjectToken, 'Type', 1
EXEC sp_OAMethod #ObjectToken, 'Open'
EXEC sp_OAMethod #ObjectToken, 'Write', NULL, #File
EXEC sp_OAMethod #ObjectToken, 'SaveToFile', NULL, #OpPath, 2
EXEC sp_OAMethod #ObjectToken, 'Close'
EXEC sp_OADestroy #ObjectToken
GO
In the SELECT statement, dbo.[FileWarehouse] and StoredFile are both underlined, saying 'Invalid Object Name' and 'Invalid Column Name', respectively. They are definitely valid, so I'm not sure it's saying that. Here is the tutorial I was following https://www.youtube.com/watch?v=8g7_F3Ice6E .
Any help would be greatly appreciated. Thank You.
While Dan's answer is correct (use Powershell or SQL CLR instead), the reason your COM automation isn't working, is that you've failed to capture and inspect the return codes from the extended stored procedures.
Here's an example:
--exec sp_configure 'Show Advanced Options', 1
--reconfigure
--exec sp_configure 'Ole Automation Procedures', 1
--reconfigure
declare #url varchar(2000) = 'http://www.bing.com'
declare #hr int;
declare #win int;
begin try
EXEC #hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',#win OUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win, 'Open',NULL,'GET',#url,'false'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win,'Send'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
declare #status int
EXEC #hr=sp_OAGetProperty #win,'Status', #status out
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
if #status <> 200
begin;
declare #msg varchar(2000) = concat('web request failed ', #status);
throw 60000, #msg, 1;
end;
declare #response table(text nvarchar(max));
insert into #response(text)
EXEC #hr=sp_OAGetProperty #win,'ResponseText';
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
select * from #response;
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
end try
begin catch
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win;
throw;
end catch
The IntelliSense error is erroneous if the script runs.
I suggest you generally avoid the ole automation procs for new development. If you don't really need to use T-SQL to create the file, consider a simple PowerShell script. This is more robust and flexible for ad-hoc needs. Below is an example that uses the standard ADO.NET objects.
$connection = New-Object System.Data.SqlClient.SQLConnection("Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI")
$command = New-Object System.Data.SqlClient.SqlCommand("SELECT StoredFile FROM [dbo].[FileWarehouse] WHERE Id= 157994;", $connection)
$connection.Open()
$blob = $connection.ExecuteScalar()
$connection.Close()
[System.IO.File]::WriteAllBytes("C:\Users\Nick\Desktop\consol\output\marksheet.doc", $blob)

SQL - Create XML - How to set Unicode UTF-8

I have a problem with creating an XML file from inside a SQL PROCEDURE.
The XMLs get created and placed in the correct folder. Although when I open the file in XMLSpy, it says the following error:
Your file contains 3 character(s) that should not be present in a file using the Unicode UTF-8 encoding...
The offending characters are è (0xE8), ü (0xFC), é (0xE9)
When I open the XML file in Notepad++ and check for encoding (via menu Encoding on top), it says it is in ANSI and not in UTF-8.
So my question is: How do I get it to turn into UTF-8? Any suggestions?
The code of my procedure can be found below:
#File VARCHAR(2000) // parameter
AS
BEGIN
DECLARE #OLE INT
DECLARE #FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', #OLE OUT
EXECUTE sp_OAMethod #OLE, 'OpenTextFile', #FileID OUT, #File, 8, 1
DECLARE #Text XML
SET #Text = (SELECT TOP(1) [xml] from VW_WARP_LEVERANCIERS_XML)
EXECUTE sp_OAMethod #FileID, 'WriteLine', Null, #Text
EXECUTE sp_OADestroy #FileID
EXECUTE sp_OADestroy #OLE
END
EDIT 1
Changed my code, exporting to ASCII instead of Unicode (as suggested below by Wolf), but this didn't help too. But here is that part of code:
DECLARE #OLE INT
DECLARE #FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', #OLE OUT
EXECUTE sp_OAMethod #OLE, 'CreateTextFile', #FileID OUT, #File, 2, False
DECLARE #Text XML
SET #Text = (SELECT TOP(1) [xml] from VW_WARP_LEVERANCIERS_XML)
EXECUTE sp_OAMethod #FileID , 'Write', Null, #Text
EXECUTE sp_OAMethod #FileID , 'Close'
EXECUTE sp_OADestroy #FileID
EXECUTE sp_OADestroy #OLE
END
I found a solution via another way. (don't remember which website I found it)
See code below. This code will export my file in UTF-8-BOM encoding.
#File VARCHAR(2000)
AS
BEGIN
DECLARE #OLE INT
EXECUTE sp_OACreate 'ADODB.Stream', #OLE OUTPUT
DECLARE #Text XML
SET #Text = (SELECT TOP(1) [xml] from VW_WARP_LEVERANCIERS_XML)
DECLARE #Converted NVARCHAR(MAX)
SET #Converted = CONVERT(nvarchar(MAX), #Text)
EXECUTE sp_OASetProperty #OLE, 'Type', 2 --1 = binary, 2 = text
EXECUTE sp_OASetProperty #OLE, 'Mode', 3 --0 = not set, 1 read, 2 write, 3 read/write
EXECUTE sp_OASetProperty #OLE, 'Charset', 'UTF-8' --'ISO-8859-1'
EXECUTE sp_OASetProperty #OLE, 'LineSeparator', 'adLF'
EXECUTE sp_OAMethod #OLE, 'Open'
EXECUTE sp_OAMethod #OLE, 'WriteText', NULL, #Converted --text method
--Commit data and close text stream
EXECUTE sp_OAMethod #OLE, 'SaveToFile', NULL, #File, 2 --1 = notexist 2 = overwrite
EXECUTE sp_OAMethod #OLE, 'Close'
EXECUTE sp_OADestroy #OLE
EXECUTE sp_OADestroy #OLE
END
Generally, SQL Server does not support UTF-8 by itself. However, I'm not sure about FSO, maybe it does.
The OpenTextFile documentation states that you can determine the file format, i.e. ASCII or Unicode. Try:
EXECUTE sp_OAMethod #OLE, 'OpenTextFile', #FileID OUT, #File, 8, 0;
This should give you an ASCII file format.

How to email query output

I have a basic query, and i'd like to email the results. How can I do this at the query level? So if my query is:
SELECT
Store_Id, Paid_Out_Amount, Paid_Out_Comment,
Paid_Out_Datetime, Update_UserName
FROM Paid_Out_Tb
WHERE (Store_Id = 1929) OR
(Paid_Out_Amount > 50) AND
(Paid_Out_Datetime BETWEEN
CONVERT(DATETIME, '2012-06-01 00:00:00', 102) AND
CONVERT(DATETIME, '2012-06-30 00:00:00', 102))
How would I email the output? I have a procedure to send email via SMTP and the parameters are #From, #To, #Subject and #body... which works.. How would I make the body the outcome of the query?
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[sp_SQLNotify]
#From varchar(100) ,
#To varchar(100) ,
#Subject varchar(100)=" ",
#Body varchar(4000) = "Test"
/*********************************************************************
This stored procedure takes the above parameters and sends an e-mail.
All of the mail configurations are hard-coded in the stored procedure.
Comments are added to the stored procedure where necessary.
Reference to the CDOSYS objects are at the following MSDN Web site:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_messaging.asp
***********************************************************************/
AS
Declare #iMsg int
Declare #hr int
Declare #source varchar(255)
Declare #description varchar(500)
Declare #output varchar(1000)
--************* Create the CDO.Message Object ************************
EXEC #hr = sp_OACreate 'CDO.Message', #iMsg OUT
--***************Configuring the Message Object ******************
-- This is to configure a remote SMTP server.
-- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_schema_configuration_sendusing.asp
EXEC #hr = sp_OASetProperty #iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value','2'
-- This is to configure the Server Name or IP address.
-- Replace MailServerName by the name or IP of your SMTP Server.
EXEC #hr = sp_OASetProperty #iMsg, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value', '10.1.1.10'
-- Save the configurations to the message object.
EXEC #hr = sp_OAMethod #iMsg, 'Configuration.Fields.Update', null
-- Set the e-mail parameters.
EXEC #hr = sp_OASetProperty #iMsg, 'To', #To
EXEC #hr = sp_OASetProperty #iMsg, 'From', #From
EXEC #hr = sp_OASetProperty #iMsg, 'Subject', #Subject
-- If you are using HTML e-mail, use 'HTMLBody' instead of 'TextBody'.
EXEC #hr = sp_OASetProperty #iMsg, 'TextBody', #Body
EXEC #hr = sp_OAMethod #iMsg, 'Send', NULL
-- Sample error handling.
IF #hr <>0
select #hr
BEGIN
EXEC #hr = sp_OAGetErrorInfo NULL, #source OUT, #description OUT
IF #hr = 0
BEGIN
SELECT #output = ' Source: ' + #source
PRINT #output
SELECT #output = ' Description: ' + #description
PRINT #output
END
ELSE
BEGIN
PRINT ' sp_OAGetErrorInfo failed.'
RETURN
END
END
-- Clean up the objects created.
EXEC #hr = sp_OADestroy #iMsg
PRINT 'Mail Sent!'
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
This is the procedure i'm using to send the mail... which works... I just want to add a spot in it to send the results of the query above it... Can this be done easily within in the procedure?
Use the SQL Server Powershell pack. An example (with detailed explanation) of using it to obtain output is here.
(The above is taken from this SO answer, but to clarify something s/he says: SQL Server 2008 client components is required (Express should be fine), but it can work with SQL Server 2000 databases (source).)
You can also use a variable for a direct loop concatenation. See https://stackoverflow.com/a/4447564/1180926 (although you would use tab and newline delimiters instead of HTML code).
You would then just change your query accordingly, store it in #Body, and you're done!

How to execute sp_send_dbmail while limiting permissions

Is there a way to provide access to users in my database to execute msdb.dbo.sp_send_dbmail without needing to add them to the MSDB database and the DatabaseMailUserRole?
I've tried this:
ALTER PROCEDURE [dbo].[_TestSendMail]
(
#To NVARCHAR(1000),
#Subject NVARCHAR(100),
#Body NVARCHAR(MAX)
)
WITH EXECUTE AS OWNER
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail #profile_name = N'myProfile',
#recipients = #To, #subject = #Subject, #body = #Body
END
But I get this error:
The EXECUTE permission was denied on the object 'sp_send_dbmail', database 'msdb', schema 'dbo'.
Thanks!
Your approach is OK, but your wrapper proc must be in the msdb database.
Then, you execute "EXEC msdb.dbo._TestSendMail"
This still leave the issue of permissions on dbo._TestSendMail in msdb.
But public/EXECUTE will be enough: it only exposes the 3 parameters you need.
If in doubt, add WITH ENCRYPTION. This is good enough to stop anyone without sysadmin rights viewing the code
USE msdb
GO
CREATE PROCEDURE [dbo].[_TestSendMail]
(
#To NVARCHAR(1000),
#Subject NVARCHAR(100),
#Body NVARCHAR(MAX)
)
-- not needec WITH EXECUTE AS OWNER
AS
BEGIN
EXEC dbo.sp_send_dbmail #profile_name = N'myProfile',
#recipients = #To, #subject = #Subject, #body = #Body
END
You actually can do it with a certificate signed stored procedure and it doesn't have to be in msdb to do so:
CREATE DATABASE TestDBMail
GO
USE [TestDBMail]
GO
CREATE PROCEDURE [dbo].[TestSendMail]
(
#To NVARCHAR(1000),
#Subject NVARCHAR(100),
#Body NVARCHAR(MAX)
)
WITH EXECUTE AS OWNER
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = N'Database Mail Profile',
#recipients = #To,
#subject = #Subject,
#body = #Body
END
GO
-- This should fail
EXECUTE [dbo].[TestSendMail] 'someemail#domain.com', 'test', 'body'
-- Create a certificate to sign stored procedures with
CREATE CERTIFICATE [DBMailCertificate]
ENCRYPTION BY PASSWORD = '$tr0ngp#$$w0rd'
WITH SUBJECT = 'Certificate for signing TestSendMail Stored Procedure';
GO
-- Backup certificate so it can be create in master database
BACKUP CERTIFICATE [DBMailCertificate]
TO FILE = 'd:\Backup\DBMailCertificate.CER';
GO
-- Add Certificate to Master Database
USE [master]
GO
CREATE CERTIFICATE [DBMailCertificate]
FROM FILE = 'd:\Backup\DBMailCertificate.CER';
GO
-- Create a login from the certificate
CREATE LOGIN [DBMailLogin]
FROM CERTIFICATE [DBMailCertificate];
GO
-- The Login must have Authenticate Sever to access server scoped system tables
-- per http://msdn.microsoft.com/en-us/library/ms190785.aspx
GRANT AUTHENTICATE SERVER TO [DBMailLogin]
GO
-- Create a MSDB User for the Login
USE [msdb]
GO
CREATE USER [DBMailLogin] FROM LOGIN [DBMailLogin]
GO
-- Add msdb login/user to the DatabaseMailUserRole
EXEC msdb.dbo.sp_addrolemember #rolename = 'DatabaseMailUserRole', #membername = 'DBMailLogin';
GO
USE [TestDBMail]
GO
-- Sign the procedure with the certificate's private key
ADD SIGNATURE TO OBJECT::[TestSendMail]
BY CERTIFICATE [DBMailCertificate]
WITH PASSWORD = '$tr0ngp#$$w0rd';
GO
-- This will succeed
EXECUTE [dbo].[TestSendMail] 'someemail#domain.com', 'test', 'body'
/*
-- Cleanup
USE [msdb]
GO
DROP USER [DBMailLogin]
GO
USE [master]
GO
DROP LOGIN [DBMailLogin]
DROP CERTIFICATE [DBMailCertificate]
DROP DATABASE [TestDBMail]
-- Delete the certificate backup from disk
*/
One possible solution is to encapsulate the mailing as a stored procedure e.g. mail_error_as_MAILER (wich you will later call)
and another stored procedure
e.g.
ALTER PROCEDURE [dbo].[mail_error](#error_ID int)
SET NOCOUNT ON
declare #rc int
declare #object int
declare #src varchar(255)
declare #desc varchar(255)
declare #osql_cmd varchar(1000)
-- create shell object
exec #rc = sp_oacreate 'wscript.shell', #object out
if #rc0
begin
exec sp_oageterrorinfo #object, #src out, #desc out
return
END
DECLARE #user VARCHAR(50)
DECLARE #password VARCHAR(50)
DECLARE #database VARCHAR(50)
DECLARE #server VARCHAR(50)
DECLARE #sql varchar(200)
SET #user=MAILER,#password=XXXXXX,#database=XXXXXX,#server=XXXXX
SET #sql= 'EXEC mail_ERROR_as_MAILER #error_ID=' + CAST(#error_id as varchar(10))
set #osql_cmd='osql -U'+#user+' -P'+#password+' -d'+#database+' -S"'+#server+'" -Q"'
+#sql+'"'
exec #rc= sp_oamethod #object, 'run', null, #osql_cmd
--print #rc
if #rc0
begin
exec sp_oageterrorinfo #object, #src out, #desc out
return
end
-- destroy shell object
exec sp_oadestroy #object
But this requires:
* hardcoding password (make sure users cannot view definition of stored procedure ...)
* giving users access to sp_oacreate etc... (opens up other security problems e.g. DOS)
that way they can only use the mail the way you want to without giving them permission to mail other things.
Or safer,
let users put mail in some kind of mail_queue(wich you can control what they can put in) and have an agent acount send these mails periodically
Or: give them permission to mail but take a big club with rusted spikes on abuse