web-dev-qa-db-fra.com

sp_send_dbmail exécuté à partir d'un travail échoue avec le résultat de la requête joint en tant que fichier

J'ai rencontré le problème suivant: lorsque vous essayez d'envoyer un courrier électronique avec les résultats d'une requête attachée sous forme de fichier, utilisez sp_send_dbmail en exécutant une requête ordinaire, tout semble fonctionner correctement.

Mais si vous ajoutez le même code dans JobStep et exécutez le travail, il échoue. 

Une erreur dans l'historique des travaux dit 

Erreur lors de la requête de formatage, paramètres probablement non valides [SQLSTATE 42000] (erreur 22050). L'étape a échoué.

Mais lorsque je commente le paramètre qui fait référence au fichier, il commence à fonctionner correctement à nouveau.

exec msdb.dbo.sp_send_dbmail 
    @profile_name = 'profile_name', 
    @recipients  = '[email protected]',
    @body = 'body',
    @subject = 'subj',
    --Parameters that refers to attached file
    @attach_query_result_as_file = 1, 
    @query_result_header = 0,
    @query_result_no_padding = 1,
    @query = 'select 1',
    @query_attachment_filename = 'test.csv'

Aucune suggestion?

16
Paul Kyrejto

Je suis venu pour contourner ce problème. Je ne sais pas pourquoi cela fonctionnerait mais jamais moins. :) Il est définitivement question de sécurité.

J'ai enquêté sur le fait que SQL Agent est exécuté pour le compte d'un utilisateur de domaine, par exemple DOMAIN\User. Il possède un ensemble complet de droits d’administrateur sur le serveur (rôle de serveur 'sysadmin', etc.). SQL Server lui-même est exécuté sous le même utilisateur.

L'étape de travail contenant l'appel à sp_send_dbmail s'exécute sous le même DOMAIN\User.

En outre, j'ai découvert que lors de l'exécution de la partie requête de sp_send_dbmail, le système tente de s'exécuter exec xp_logininfo 'DOMAIN\User' pour vérifier si Active Directory est cet utilisateur. Et surprise: quelque chose ne va vraiment pas. Ce chèque se termine avec:

Msg 15404, Level 16, State 19, Server SQLC002INS02\SQLC002INS02, Line 1
Could not obtain information about Windows NT group/user 'DOMAIN\User.', error code 0x2.

Cela, avec une certaine probabilité, peut signifier que tout ce qui concerne le mot de passe de cet utilisateur est expiré ou que l'utilisateur est verrouillé ou toute autre chose non agréable pour ce type.

J'ai décidé que c'était risqué de changer d'utilisateur pour Agent. Je viens donc d'envoyer des courriers pour le compte de 'sa' qui a le même rôle de serveur 'sysadmin' mais une autorisation SQL et omet cette étape de vérification des AD. 

Cela ressemble à un utilisateur qui prétend être administrateur pour demander au véritable administrateur d'exécuter un code dangereux pour lui :)

Donc le code final de ce travail est la première et la seule étape ressemble à ceci:

execute as login = 'sa'
exec msdb.dbo.sp_send_dbmail 
    @profile_name = 'profile_name', 
    @recipients  = '[email protected]',
    @body = 'body',
    @subject = 'subj',
    --Parameters that refers to attached file
    @attach_query_result_as_file = 1, 
    @query_result_header = 0,
    @query_result_no_padding = 1,
    @query = 'select 1',
    @query_attachment_filename = 'test.csv'
revert
24
Paul Kyrejto

J'ai eu ce problème. J'utilise SQL Server 2008 R2. J'ai reçu l'email envoyé avec plus d'informations sur l'erreur en ajoutant l'option:

@append_query_error = 1,

J'ai reçu l'email avec cette erreur sur les permissions au lieu de ma requête:

   Msg 916, Level 14, State 1, Server SERVER\INST01, 
Procedure GetSalesReport, Line 62
The server principal "CONTROLLEDNETWO\sql.service" is not able 
to access the database "MYDB01" under the current security co
ntext.

Ma requête tentait d'accéder à certaines tables sur lesquelles SQL Agent ne disposait d'aucune autorisation (dans mon cas, il n'y avait même pas accès).

Je l'ai corrigé via SQLSMS en ajoutant un nouvel utilisateur "CONTROLLEDNETWO\sql.service" à la base de données "MYDB01" et en accordant des autorisations à "select".

7
Rafa
EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'Main Profile',
    @recipients = '[email protected]',
    @subject = 'Test',
    @body = 'this is a test',
    @execute_query_database = 'myTargetDatabase_mscrm',
    @query = N'SELECT * from myTargetDatabase_mscrm.dbo.SystemUserBase',
    @attach_query_result_as_file = 1,
    @query_attachment_filename = 'Test.txt'

Pour référence, cela a échoué à plusieurs reprises indiquant qu'il était appelé en tant qu'administrateur de domaine, mais s'exécutait en tant que local\sqladmin. Après avoir désactivé les variables et tenté de donner des autorisations, j'ai vu dans le script du travail qu'il utilisait toujours la base de données master. J'ai trouvé le décor me regarder dans les yeux. C'est dans la configuration de l'étape. Je l'ai changé en msdb et cela a fonctionné. N'oubliez pas que j'ai modifié l'option select from myTable pour sélectionner myDatabase.dbo.myTable en fonction de certaines publications. Cela peut avoir contribué ou non à résoudre le problème. J'ai également utilisé @execute_query_database pour m'assurer que la requête est exécutée au bon endroit. Encore une fois, cela n'aurait peut-être pas été nécessaire.

Peu importe ce qui le rend finalement heureux, cela n’a rien à voir avec le fait qu’il soit attaché ou non.

1
Eric Hula

Tout cela a été utile, merci. Je voulais partager ce que j'essayais de faire avec la pièce jointe Excel (xls) qui contenait les résultats en colonnes. Cela a fonctionné pour moi en ajoutant le query_result_no_padding = 1 et query_result_separator = ','. (c'est un onglet, onglet dans les ticks)

@query_result_header= 1,
@attach_query_result_as_file = 1,
@query_result_no_padding = 1,
@query_attachment_filename = 'TestPriceFlingerReport.xls',
@query_result_separator= '  ,   ',
@profile_name = 'Test Exchange Server'
0
Dan Pullman

J'ai eu ce problème aussi, et l'ai résolu en deux parties en utilisant une grande partie des conseils donnés ici. 

1) Cliquez avec le bouton droit de la souris sur 'Afficher l'historique' sur le travail pour afficher les détails de l'échec. L'avis d'échec a donné le nom de l'utilisateur sous lequel le travail a été exécuté. J'ai donc donné à cet utilisateur un accès en lecture seule à ma base de données.

2) J'avais oublié de spécifier DBName.dbo . MyTableName et n'utilisais que MyTableName. 

Incidemment, les emails allaient tous dans mon dossier de courrier indésirable.

0
Resource

Je pense que ce problème était dû à une modification implémentée dans SQL 2008 et versions ultérieures concernant le verrouillage de la sécurité uniquement pour sp_send_dbmail . Cela ne se produit que si vous transmettez un qry à send_dbmail pour qu'il s'exécute et que les résultats soient renvoyés par courrier électronique. Le problème est que le message d'erreur est trompeur et non approprié .. Une bonne solution consiste à créer un utilisateur SQL avec uniquement les autorisations minimales nécessaires pour exécuter cette requête. Par exemple, db_reader ou db_writer et db_owner si cela est absolument nécessaire. Et faire de cet utilisateur le propriétaire. Vous pouvez également créer des informations d'identification SQL et configurer ce travail SQL pour qu'il s'exécute sous ces informations d'identification SQL.

0
user2238156

Lorsque vous exécutez manuellement votre requête, VOS identifiants sont utilisés. Lorsque SQL Agent exécute la même requête, les informations d'identification du compte de service SQL Agent sont utilisées. Par défaut, SQL Server Agent utilisera les informations d'identification du compte LocalSystem. Un moyen de résoudre le problème consiste à changer l'utilisateur sous lequel le service Agent SQL Server est exécuté avec un utilisateur ayant accès à votre répertoire\fichier csv.

0
David Brabant

dans ma situation, il n'a pas pu identifier la table appartenant à la base de données. Une fois que le fichier database.dbo.table était ajouté à la requête, cela fonctionnait.

0
SQLguest