"EXECUTE msdb.dbo.sp_send_dbmail" runs in SSMS 2008R2 via Query but fails as stored procedure job.

  • Environment: SQL Server 2008R2.

    Problem: "EXECUTE msdb.dbo.sp_send_dbmail" runs via SSMS 2008R2 via Query but fails as stored procedure job.

    The following query:

    -- Execute usp_MyStoredProcedure stored procedure in Master database.

    Declare

    @profilename sysname,

    @RecipientsProxy VARCHAR(MAX),

    @SendEmailOnly BIT,

    @Debug BIT

    SET @ProfileName = 'My Profile Name'

    SET @SendEmailOnly = 0

    SET @RecipientsProxy = 'me@mydomain.com'

    SET @Debug = 0

    EXECUTE Master.[dbo].[usp_MyStoredProcedure ]

    @ProfileName,

    @RecipientsProxy,

    @SendEmailOnly,

    @Debug

    runs just fine in SQL Server Management Studio when run as Query but when run as a SSQL Server Agenct Job it failed with the following error:

    Error formatting query, probably invalid parameters (SQLSTATE 42000][Error 22050] DBCC execution completed. If DBCC printed error messages, contact your system administrator. [SQLSTATE 01000][Error 2528]

    I did not include the entire stored procedure as it appears to run okay via SSMS query. I can include it if someone needs to see it. I did not write the stored procedure.

    I have seen several postings relating to this type of issue but have not found any answers.

    I know that the stored procedure fails with "EXECUTE msdb.dbo.sp_send_dbmail". When this part of the stored procedure is commented out the SQL Server Agent job run just fine.

    Any help on resolving this issue will be greatly appreciated.

    Thanks,

    Howard

  • Post the entire proc please.

    Jason...AKA CirqueDeSQLeil
    _______________________________________________
    I have given a name to my pain...MCM SQL Server, MVP
    SQL RNNR
    Posting Performance Based Questions - Gail Shaw[/url]
    Learn Extended Events

  • I did not write this proc. I had found it on the internet and it appears to be available to anyone who wishes to use it.

    USE Master

    GO

    IF OBJECT_ID('dbo.usp_MyStoredProcedure', 'P') IS NOT NULL DROP PROCEDURE dbo.usp_MyStoredProcedure

    GO

    CREATE PROCEDURE dbo.usp_MyStoredProcedure

    @ProfileNameSYSNAME = NULL,-- Valid DB Mail Profile

    @RecipientsProxyVARCHAR(MAX) = NULL,-- semicolon-delimited list of e-mail addresses

    @SendEmailOnlyBIT= 0,-- So we can send email of existing records in

    -- the [Master].[dbo].[DBCCCheckDBOutput] table

    @DebugBIT= 0-- Show or hide verbose output

    AS

    SET NOCOUNT ON;

    DECLARE

    @BatchDateDATETIME,

    @DBNameSYSNAME,

    @MachineNameSYSNAME,

    @InstanceNameSYSNAME,

    @pkTINYINT,

    @SQLVARCHAR(8000),

    @SQLServerInstanceNameSYSNAME,

    @yesBIT,

    -- Error message vars

    @ErrorMessageNVARCHAR(4000),

    @ErrorNumberINT,

    @ErrorSeverityINT,

    @ErrorStateINT,

    @ErrorLineINT,

    @ErrorProcedureNVARCHAR(200),

    -- DB Mail Variables

    @AttachQueryResultAsFileProxyBIT,

    @BodyNVARCHAR(MAX),

    @BodyProxyNVARCHAR(MAX),

    @NOBIT,

    @QueryVARCHAR(MAX),

    @QueryProxyVARCHAR(MAX),

    @RecipientsVARCHAR(MAX),

    @SubjectNVARCHAR(255),

    @SubjectProxyNVARCHAR(255)

    -- Ephemeral Work tables

    DECLARE @t TABLE

    (

    PKTINYINT IDENTITY,

    DBNameSYSNAME

    )

    -- Defint Constants

    SET @yes= 1

    SET @NO= 0

    -- Set DBMail variables

    SET @AttachQueryResultAsFileProxy= @yes

    -- Variables

    SET @BatchDate= GETDATE()

    SET @InstanceName= CAST(SERVERPROPERTY('InstanceName') AS SYSNAME)

    SET @MachineName= CAST(SERVERPROPERTY('MachineName') AS SYSNAME)

    IF @InstanceName IS NULL

    SET @SQLServerInstanceName = @MachineName

    ELSE

    SET @SQLServerInstanceName = @MachineName + '\' + @InstanceName

    SET @SubjectProxy= @SQLServerInstanceName + ': DBCC CheckDB Results'

    SET @BodyProxy= 'Here are the summary DBCC CHECKDB output lines.'

    SET @QueryProxy= 'SET NOCOUNT ON;SELECT CAST(DBName AS VARCHAR(25)) AS DBName, DTStamp, LEFT(MessageText, 200) MessageText FROM Membership.dbo.DBCCCheckDBOutput WHERE IsSummaryLine = 1 AND DTSTamp = ( SELECT MAX(DTStamp) FROM Master.dbo.DBCCCheckDBOutput ) ORDER BY DBName;'

    -- 1) Parameter validation

    -- Parameter existence check:

    IF @ProfileName IS NULL

    BEGIN

    RAISERROR( 'Please provide a DB Mail Profile Name', 16, 1 )

    RETURN

    END

    IF @RecipientsProxy IS NULL

    BEGIN

    RAISERROR( 'Please provide a receipent email address', 16, 1 )

    RETURN

    END

    -- Profile name validity check

    BEGIN TRY

    EXEC msdb.dbo.sysmail_help_profile_sp @profile_name = @ProfileName

    END TRY

    BEGIN CATCH

    SELECT

    @ErrorNumber= ERROR_NUMBER(),

    @ErrorSeverity= ERROR_SEVERITY(),

    @ErrorState= ERROR_STATE(),

    @ErrorLine= ERROR_LINE(),

    @ErrorProcedure= ISNULL(ERROR_PROCEDURE(), '-');

    RAISERROR

    (

    @ErrorMessage,

    @ErrorSeverity,

    1,

    @ErrorNumber, -- parameter: original error number.

    @ErrorSeverity, -- parameter: original error severity.

    @ErrorState, -- parameter: original error state.

    @ErrorProcedure, -- parameter: original error procedure name.

    @ErrorLine -- parameter: original error line number.

    );

    RETURN

    END CATCH

    IF @SendEmailOnly = @NO

    BEGIN

    -- 2) Create or maintain work table

    IF OBJECT_ID(N'Master.dbo.DBCCCheckDBOutput', N'U') IS NOT NULL

    TRUNCATE TABLE Master.dbo.DBCCCheckDBOutput

    ELSE

    BEGIN

    CREATE TABLE dbo.DBCCCheckDBOutput

    (

    PK INT IDENTITY CONSTRAINT PK_DBCCCheckDBOutput PRIMARY KEY,

    ServerNameSYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NULL,

    DBNameSYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NULL,

    ErrorINT NULL,

    [Level]INT NULL,

    [State]INT NULL,

    MessageTextVARCHAR(7000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,

    RepairLevelINT NULL,

    [Status]INT NULL,

    [DbID]INT NULL,

    IDINT NULL,

    IndIDINTNULL,

    PartitionIDINT NULL,

    AllocUnitIDINT NULL,

    [File]INT NULL,

    PageINT NULL,

    SlotINT NULL,

    RefFileINT NULL,

    RefPageINT NULL,

    RefSlotINT NULL,

    AllocationINT NULL,

    DTStampDATETIME NULL,

    IsSummaryLineBIT CONSTRAINT DF_DBCCCheckDBOutput_IsSummaryLine DEFAULT (0)

    )

    END

    -- 3) Create a loop to perform DBCC CHECKDB against all databases other than TempDB

    INSERT @t( DBName )

    SELECT name

    FROM master.sys.databases

    WHERE database_id <> 2

    WHILE EXISTS ( SELECT TOP 1 1 FROM @t )

    BEGIN

    SELECT TOP 1 @pk = PK, @DBName = DBName FROM @t

    SET @SQL = 'SET NOCOUNT ON;DBCC CHECKDB(' + @DBName + ') WITH TABLERESULTS, ALL_ERRORMSGS;'

    IF @Debug = @yes SELECT @SQL;

    INSERT INTO [Master].[dbo].[DBCCCheckDBOutput]

    (

    [Error]

    ,[Level]

    ,[State]

    ,[MessageText]

    ,[RepairLevel]

    ,[Status]

    ,[DbID]

    ,[ID]

    ,[IndID]

    ,[PartitionID]

    ,[AllocUnitID]

    ,[File]

    ,[Page]

    ,[Slot]

    ,[RefFile]

    ,[RefPage]

    ,[RefSlot]

    ,[Allocation]

    )

    EXEC (@SQL)

    -- Update BatchDate, ServerName, and DBName

    UPDATE Master.dbo.DBCCCheckDBOutput

    SET

    DTStamp= @BatchDate,

    ServerName= @SQLServerInstanceName,

    DBName= @DBName

    WHERE ServerName IS NULL AND DBName IS NULL

    -- Mark summary line for given database for email since we can't use local variables for the email session

    UPDATE Master.dbo.DBCCCheckDBOutput

    SET IsSummaryLine = @yes

    WHERE PK = ( SELECT MAX(PK) FROM Master.dbo.DBCCCheckDBOutput WHERE DBName = @DBName )

    -- Remove record from work table

    DELETE @t WHERE PK = @pk;

    END

    END

    -- 4) Send email having summary lines of DBCC CHECKDB

    BEGIN TRY

    IF @Debug = @yes SELECT @QueryProxy

    EXECUTE msdb.dbo.sp_send_dbmail

    @profile_name= @ProfileName,

    @Recipients= @RecipientsProxy,

    @Subject= @SubjectProxy,

    @Body= @BodyProxy,

    @body_format= 'TEXT',

    @query_result_header= @yes,

    @Query= @QueryProxy,

    @attach_query_result_as_file= @AttachQueryResultAsFileProxy,

    @query_result_width= 1000

    END TRY

    BEGIN CATCH

    SELECT

    @ErrorNumber= ERROR_NUMBER(),

    @ErrorSeverity= ERROR_SEVERITY(),

    @ErrorState= ERROR_STATE(),

    @ErrorLine= ERROR_LINE(),

    @ErrorProcedure= ISNULL(ERROR_PROCEDURE(), '-');

    RAISERROR

    (

    @ErrorMessage,

    @ErrorSeverity,

    1,

    @ErrorNumber, -- parameter: original error number.

    @ErrorSeverity, -- parameter: original error severity.

    @ErrorState, -- parameter: original error state.

    @ErrorProcedure, -- parameter: original error procedure name.

    @ErrorLine -- parameter: original error line number.

    );

    END CATCH

  • i didn't se the specific error , just the "it fails" part even though it's set up right elsewhere;

    typically that's due to permissions.

    whever calls the sp_send_dbmail needs to be a member of the DatabaseMailUserRole in the msdb database;

    it works via s cript when you run it, because as a sysadmin, you of course bypass the required security.

    But when bob from accounting or some scheduled job calls the proc as a normal user, their credentials fail when the cross database call to msdb tries to send the mail.

    to fix the issue, you would probab ly want to add a windows group to the msdb database as a user, and then put that group in the DatabaseMailUserRole role. I'd avoid being lazy and adding the public role to the same role, but that's a possbility.

    you could also use EXECUTE AS on the proc so it runs under the context of a user that has access in both databases as well.;

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • Lowell:

    Thank you for your response.

    I believe that you are correct in that it is a permission problem.

    I tried adding the With Execute As 'sysadmin' and got the following error:

    Msg 15151, Level 16, State 1, Procedure usp_GetDBCCCHECKDBOutput, Line 305

    Cannot execute as the user 'sysadmin', because it does not exist or you do not have permission.

    I then tried adding the With Execute As 'myuser' where myuser has sysadmin rights. The procedure created without a problem but the email was still not sent.

    As you suggested I probably need to add a windows group to the msdb database as a user and then put that group in the DatabaseMailUserRole. My problem is that I have never done this before and therefore I do know how to go about this.

    Prior to this, using SSMS, I went to the msdb database > Security > Roles > Database Roles > DatabaseMailUserRole and on the General section I checked db_owner. That did not help but now I cannot uncheck db_owner. The check box is grayed out. Any idea as to how I can uncheck this?

    Any further help will be greatly appreciated.

    Howard

Viewing 5 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic. Login to reply