sp_send_dbmail is not working - sql-server

I am trying (unsuccessfully) to use sp_send_dbmail (Transact-SQL).
The #recipients value is said to be a semicolon-delimited list of e-mail addresses to send the message to.
So, in my data table's Email column, all I should have to do is update the row to send to multiple recipients:
Old: JoeP#jp2code.net
New: JoeP#jp2code.net; personB#jp2code.net
There are no errors, but then there is no email going out.
The code I use to call sp_send_dbmail is unchanged in my stored procedure:
IF (0 < (SELECT COUNT(ID) FROM #Email)) BEGIN
SELECT TOP 1 #ID=ID, #email=Email FROM #Email
EXEC msdb.dbo.sp_send_dbmail #recipients=#email, #subject=#subj, #body=#html, #body_format='HTML', #from_address='no-reply#jp2code.net', #reply_to=#email;
DELETE #Email WHERE #email=Email
END
So, what is wrong?

I may have found the issue...
#reply_to=#email;
[ #reply_to= ] 'reply_to'
Is the value of the 'reply to address' of the email message. It accepts only one email address as a valid value. This is an optional parameter used to override the settings in the mail profile. This parameter is of type varchar(MAX). SMTP secuirty settings determine if these overrides are accepted. If no parameter is specified, the default is NULL.
This explains why it worked with a single address, but doesn't work with multiple addresses.

Stupid mistake.
Take a closer look at the SQL:
IF (0 < (SELECT COUNT(ID) FROM #Email)) BEGIN
SELECT TOP 1 #ID=ID, #email=Email FROM #Email
EXEC msdb.dbo.sp_send_dbmail
#recipients=#email,
#subject=#subj,
#body=#html,
#body_format='HTML',
#from_address='no-reply#jp2code.net',
#reply_to=#email;
DELETE #Email WHERE #email=Email
END
Does everyone see the problem now?
Hint: Look at the reply_to field.

Related

How to send an email on finding bad data in a table in sql server

I have below EmployeeData table and due to some known reasons BAD data is getting inserted and i am working on code fix, but meanwhile i want to check for bad data until the fix is deployed. If you observe John has 1 for both Active and IsEmpTermed columns.
Currently i am running the below query to check for Bad data manually in SQL Server. I want to automate this task and send an email to me if it finds bad data i.e. Active =1 and IsEmpTermed =1. What and How to do it?
select * from EmployeeData Where Active=1 and IsEmpTermed = 1;
Thanks in advance.
Quick way would be use the #query argument with sp_send_dbmail and put that code in a SQL Server Agent Job.
Here's a simple example of what that sp_send_dbmail looks like:
EXEC msdb.dbo.sp_send_dbmail
#profile_name = '' --This is specific to your setup
,#recipients = 'your#email.com'
,#subject = 'This is the subject'
,#query = 'select EmpID, FirstName, LastName from EmployeeData Where Active=1 and IsEmpTermed = 1' --The query
,#execute_query_database = '' --The name of your database goes here where the query should be executed
That will basically execute the query you specified in #query, dump the results into an email and send it to whomever is in #recipients
If you don't know what the #profile_name is for your server configuration you can run
EXEC msdb.dbo.sysmail_help_profileaccount_sp;
That will return a list of the mail profiles configured on your server. You will use the value from the "profile_name" column. If there are multiples, this is something I can't tell you as it is specific to your server configuration.
Once you have all that defined and working by manually running it in SSMS, go create a SQL Server Agent Job with a T-SQL step and add the "EXEC msdb.dbo.sp_send_dbmail" code. Defined a schedule at whatever frequency you would like it to run.
A lot of times I'll code it to check if the data issue exists before sending an email, so it will only send an email when the data issue exists so it won't keep spamming me if there are no issues, something like this
--The IF EXISTS checks if the data issue exists before sending an email
IF EXISTS(SELECT TOP 1 'x' FROM dbname.dbo.EmployeeData Where Active=1 and IsEmpTermed = 1)
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = '' --This is specifc to your setup
,#recipients = 'your#email.com'
,#subject = 'This is the subject'
,#query = 'select EmpID, FirstName, LastName from EmployeeData Where Active=1 and IsEmpTermed = 1' --The query
,#execute_query_database = '' --The name of your database goes here
END

Using SQL to send emails based on new entries in tables

I'm looking for a way to send emails (or reminders/confirmations) to users who create a new record in a web application, which is then inserted into a table. Basically a dynamic way of sending emails.
I've been reading online about Triggers and DB mail and there seems to be alot of disadvantages going with this approach.
Does anyone have any recommendations on the best way to achieve this?
Flow: New Record Inserted into DB Table ->>> At this point the email address of the user who created the record in the application should receive a mail (basically a confirmation mail).
What I've tried already:
DB mail is already configured and working.
I've made the below Trigger (very basic) but from reading online using a trigger in this way will lead to load/performance issues of my DB.
But I'm on unsure on how to generate the emails and last record inserted.
CREATE TRIGGER [dbo].[INSERT_Trigger] ON [dbo].[Entity]
FOR INSERT
AS
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DBMail',
#recipients = 'admni#domain.com', ####Here I would need dyncamic emails based on what user enters the new record which are stored in the same table
#query = 'Select Description From Entity where 'Last inserted record'####Here I would need the last record for that user entered
#subject = 'Subject' ,
#Body = 'Message Body',
#importance = 'High',
IMHO this approach is a design flaw: the DB tier is something that should be one of the leaves of the tier tree. The fact that the MS SQL Server is actually an application server and has support for such things is a legacy, but I don't think that it should be used.
At first look:
you might need to switch to another RDBMS
your production environment might not support SMTP for any reason
your attempt to send the mail could fail for various reasons - resulting in user not being notified and never trying it again
Yes, indeed, you can use SQL Server even as a message bus but would not be an efficient one. This concept is actually dispatching events of "notification needed" kind. The event is implemented as insert and the trigger is the consumer. But the event is produced inside your application, in a higher tier. Why not reacting to it there? Or, use the database only as a queue: store the details there, but process them in a way where you have more control.
You have not told us about the application you are creating, but I would create a separate background task (the implementation could vary depending on the application design - can be an OS-level scheduled task, windows service, or a background worker in your application) that checks periodically for mails not yet sent, and tries to send them, storing the result in the record. Things might get of course more complicated depending on load. But this way you can retry, and you are certainly taking load of the DB server, but at least you have the possibility to do so.
I have a trigger that works as u asked
First insert records in temporary table from inserted table
Second, declare parameters that you need
Third, add a cursor in your trigger and get parameters that u need in cursor from temporary table
Inside trigger you can declare recipients as u needed to be, query, and other stuffs
CREATE TRIGGER Trigger ON [Entity]
FOR INSERT
not for replication
AS
select ins.* into #temp from inserted ins
declare #Param1 integer, #Param2 integer
declare cursor forward only for
select Col1, Col2 from #temp order by Col1
open cursor
fetch next from cursor into #Param1, #Param2
while ##fetch status = 0
begin
declare #recipients varchar (max), #query varchar(max)
select #recipient = Col1 -- or whatever col contains the recipient address
from #temp
where Col1 = #Param1
select #query = description
from #temp
where Col2 = #Param2 -- or whatever condition give u the description for parameter
exec sp_send_dbmail
#profile_name = 'profile',
#recipients = #recipient
#subject = 'Subject' ,
#Body = #query,
#importance = 'High'
fetch next from cursor into #Param1, #Param2
end
close cursor
deallocate cursor
drop table #temp
--- note that the body can be formatted in html format, like bellow
declare #body varchar(max)
select #body = '<html><body>'
select #body = #body+'Hello'+'<b><b>'
select #body = #body+'Here is the description:'+#query+'<b><b>'
select #body = #body+'Regards'
select #body = #body+'</body></html>'

How do you send email with TSQL using a Agent Operator instead of an email address?

I have some custom audit processes that send emails with sp_send_mail. I discovered recently that testing was sending out emails to everybody because the recipient address was hard coded as a variable value. I'd rather use an Operator so I don't have to alter code moving from one environment to the next. I've googled but this doesn't seem to be a thing unless I'm just using the wrong key words.
What is the proper #recipients value to use an Operator or should I be using a different proc all together?
You're definitely on the right track but you just need to retrieve the email address of the operator based on the name of the operator like this:
DECLARE #OperatorName sysname = N'OnCallDBAs';
DECLARE #OperatorEmailAddress nvarchar(100)
= (SELECT email_address
FROM msdb.dbo.sysoperators
WHERE [name] = #OperatorName);
IF #OperatorEmailAddress IS NOT NULL
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'Adventure Works Administrator',
#recipients = #OperatorEmailAddress,
#body = 'The stored procedure finished successfully.',
#subject = 'Automated Success Message';
END;
Hope that helps.

How does sp_send_dbmail convert the query into text in the email body

I'm trying to add a "signature" at the bottom of a stored procedure to show what job ran it, what server it was run on, and the stored procedure name (I have the code figured out). But if I try to insert the signature, it is placed above the query result in the email. I was trying to capture that text result to manually add it to the email body so I can place the signature underneath it.
How does SQL Server convert a query into the text displayed in an email using EXEC msdb.dbo.sp_send_dbmail?
Furthermore, is there a way I can capture that text into a local variable?
If you examine the sp_send_dbmail stored procedure, you can see what it's doing. The short version is that it
runs the query and stores the results in a system table (sysmail_mailitems), along with all the other message details
sends the message to the mail queue
an external mail service actually constructs and sends the message to the recipients
The point is that there is no easy way to customize how the email message is assembled. You'll be better off designing some sort of external process of your own to construct and send the email.
I believe in the past I have build out the email as HTML, and injected the query results into the message body variable (rather than using the #query param) - this required, or at least i used, some "FOR XML PATH" functionality to build out an html table within the body.
Forgive the terribleness, I don't have dbmail set up at home so i can't give this a test with the actual sp, but it should get the point across - and yes it's kind of messy, but it DOES work :P
declare #body varchar(max)
set #body = 'Hello world<br /><br />'
declare #temp table (
id int primary key identity(1,1) ,
name varchar(50) ,
isAwesome bit default 0
)
insert into #temp (name, isAwesome)
select 'turtle', 1
union all select 'popsicles', 0
union all select 'bees', 0
declare #xml xml = (
select name as td, isAwesome as td
from #temp
for xml raw ('tr'), elements
)
set #body = #body + '<table>'
set #body = #body + convert(varchar(max), #xml)
set #body = #body + '</table>'
set #body = #body + '
<br /><br />
Signature'
select #body

Update website when data in SQL Server changes?

I am stuck in a problem. There is an application that adds data to database, which is a closed source.
I am creating its web interface. The functionality I want is, that, if a value of some Field in a column is greater than a value in another field in a column, SQL server should http post a message to my site.
Is it possible in Microsoft SQL?
and if yes, How?
Ok, if another software is doing the inserts, you could do it like this...
ALTER TRIGGER [dbo].[ABCD] ON [dbo].[XXX]
FOR INSERT
AS
Declare #A -- from column 1 in INSERT
Declare #B -- from column 2 in INSERT
if (#A > #b)
begin
EXEC msdb.dbo.sp_send_dbmail
#recipients = #email,
#body = #message,
#subject = 'Latest record has column value A greater than column value B'
end
else
begin
--do whatever
end
Ps. sp_send_dbmail is a stored procedure that sends email or messages

Resources