SQL mail ------DATABASE MAIL - sql

Dear all,
I am using SQL Server 2008.
I am facing a scenario where I have to send mail to single or multiple user depending on the query. I tried this stmt to send mail to multiple recipients
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'imran' ,
#recipients= 'imran.khan#bbraun.com;amol.puranik#bbraun.com',
#subject = 'Test mail'
It succesfully sent mail.
Now I want to send mail depending on query. With single employee it is no issue, but if it is more then one employee how can I mail to multiple recipients.
That is my question is in this sp to send multiple recipients one has to separate addresses with ; . How can I arrange recipients so that the ; comes in between.
Thank you.

Unfortunately, you're not giving us a lot to go on - you don't show us the query to select your employees, you're not telling us anything about what the Employee table looks like, so all we can do is guessing - at best.
So here's my guess: you want to somehow select multiple employees, and their e-mail addresses should be concatenated together, separated by a semicolon (;), and then used for your sp_send_dbmail call.
One method to do this could be this:
DECLARE #recipients VARCHAR(4000)
SELECT
#recipients = STUFF((SELECT ';' + EMail
FROM dbo.Employees
WHERE (some condition here to find the right employees)
FOR XML PATH('')
), 1, 1, '')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'imran',
#recipients,
#subject = 'Test mail'

Use a function like this -
CREATE FUNCTION coltocsv
(
--your input parameters
)
RETURNS nvarchar(3000)
AS
BEGIN
-- Declare the return variable here
declare #keywords nvarchar(3000)
--Build your csv string of keywords
Select #keywords = null
SELECT #Keywords = Coalesce(#Keywords + '; ', '') +
ColumnName
from Table
where <some condition>
--- Return the result of the function
RETURN #keywords
END

for the recipients, you can seggregate the miultiple email id's by [];
declare #ccmailid varchar(2000);
select #ccmailid = stuff((select '],['+ mailid from table_name
order by '],['+ mailid
for xml path('')),1,2,'')+']'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'imran' ,
#recipients= #ccmailid,
#subject = 'Test mail'

Related

SQL Mail to send emails to users specified in a query only

I've about 1 month of experience when it comes to SQL and I wanted to send emails to customers based on query criteria. The challange I have is that the emails should only go to users emails that show up in the query. Below is an example of the data. I have no idea what I should do to setup the auto emailing based on a query. Any help is greatly appreciated!
My query would look like this,
select *
from [Tbl]
where [Date Certificate is Expiring]
Between getdate()-372 AND getdate()-371
OUTPUT:
USER ID | Email | Date Certificate is Expiring
NOTE: I do not have access to Visual Basic, SSRS, SSIS, or any other tool than Database Engine and dbMail
Please create DB mail profile first, then put it into below query:
DECLARE #MailRecipients NVARCHAR(MAX);
SELECT #MailRecipients = STUFF((
SELECT DISTINCT ';' + t.Email
FROM [Tbl] t
WHERE t.[Date Certificate is Expiring] BETWEEN GETDATE()-372 AND GETDATE()-371
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'')
;
IF COALESCE(#MailRecipients,'') <> ''
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#profile_name = ..., -- <-- you have to create DBMailProfile first
#recipients = #MailRecipients,
#subject = 'Email about expiring stuff',
#body_format = 'HTML',
#body = 'Hi there, your something is expired',
#importance = 'Normal'
END

Send Email to each recipient stored into a table

I'm trying to send an email using the sql server email option, I already can send an email, but now I'm trying to send that email to dynamic recipients, for example... I have the following table:
ID | Email
..1| example#example.com
..2| example2#example.com
With my code I need to do the following thing:
#recipients = 'example#example.com; example2#example.com;'
What I want to do is to select that emails from a table, so if I edit one email I dont have to change anything about my code, just update the information from my table.
I'm thinking maybe do it by using a var, something like:
Declare #emails nvarchar(max)
set #email = query
then do something like a foreach (foreach email in #emails) or something like that (in T-SQL of course...)
Is this possible? Or what another solution can I try?
Recipients has the option to add more than one email in the same line, so maybe the easier way to solve your problem is select all the emails and then join them separated with a ;. If you thing that this is a good option you should try this code:
Declare #Emails nvarchar(MAX)
Select #Emails = coalesce(#Emails + ';', '') + Email from yourTable
//Your output should be: example#example.com;example2#example.com
Then all you need to do this:
#recipients = #Emails
You should use a cursor for that
DECLARE #email nvarchar(max)
set #email = ''
DECLARE #cursorName CURSOR FOR
SELECT emailColumn FROM tableName
OPEN #cursorName
Then you use a loop to concatenate each email
FETCH NEXT FROM #cursorName INTO #email
WHILE ##FETCH_STATUS = 0
BEGIN
set #email = #email+#cursorName+'; '
END
You need to concatenate the strings in the column, so something like this should work:
CREATE TABLE dbo.exampleTable (
id int,
email varchar(200)
)
INSERT INTO dbo.exampleTable VALUES (1,'a#a'),(2,'b#b')
SELECT stuff( (SELECT ';'+email
FROM dbo.exampleTable
FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
,1,1,'')
There are also some other ways to do it: https://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
The result of the query you build or use can be used to set your #email variable.

Insert only trigger in SQL Server

I'm trying to create a trigger that sends an email ONLY when there's an insert. I currently get an email whether there's an insert or not and I WANT to get an email ONLY when there's an insert in the table. Here's how the trigger currently looks like
ALTER TRIGGER [dbo].[myTriggerName]
ON [dbo].[myTableName]
AFTER INSERT
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'MyRecipients',
#profile_name = 'DBAdmins',
#subject = 'MySubject',
#body = 'Body';
END
I would be extremely careful to put extensive processing or things like sending e-mails directly into a trigger.
The trigger executes in the context of the calling transaction, and thus delays the completion of that transaction until it is done.
If you have external dependencies (like a SMTP server), you can quickly get into situations where you have timeouts etc.
A trigger should be extremely nimble, small and fast.
My recommendation would be:
make a note into a separate table EmailToSend with all the necessary information you need (recipient, subject, body, date stored)
CREATE TRIGGER trgYourTableInsert
ON dbo.YourTable
AFTER INSERT
AS
INSERT INTO dbo.EmailToSend(Recipient, Subject, Body)
VALUES('john.doe#acme.org', 'Hello there', '.......')
have a separate process (e.g. a scheduled stored procedure that runs once every hour) checking that table and doing the actual sending of the e-mails (without blocking any other processes / transactions) - something along the lines of:
SELECT (list of columns)
FROM dbo.EmailToSend
WHERE DateSent IS NULL
or something like that - it really heavily depends on what exactly you're putting into that table and how you want to handle this ....
CREATE TRIGGER dbo.trg_I_tbl
ON dbo.tbl
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #text NVARCHAR(MAX)
SELECT #text = STUFF((
SELECT ', ' + col
FROM INSERTED
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'your_account#gmail.com',
#subject = 'caption',
#body = #text
END
GO

Stored procedure using sp_send_dbmail to send emails to multiple recipients queried from database

Like the title says, I'm trying to make a stored procedure used to send emails to addresses stored in the database, often including multiple recipients. I've tried a few approaches to this, but I think I'm hitting a wall and would appreciate any input anyone has. The main issue I've had is querying the database for the addresses and passing that to sp_send_dbmail in a way that works.
The address table is pretty simple, looks something like this, but much larger. Both columns are varchars:
idNumber | email
__________________________
a123 | steve#test.com
a123 | carol#test.com
1-100 | mary#test.com
So if we're sending to ID number "a123", an email needs to go to both Steve and Carol.
Here's a super simple procedure. It's not verbatim since this is all on my work computer, but more of a skeletal gist of what I'm going after.
CREATE PROCEDURE sendMail
#idNumber varchar(MAX),
#subject varchar(MAX),
#body varchar(MAX)
EXEC msdb.dbo.sp_send_dbmail
#recipients = "EXEC SELECT email FROM emailTable WHERE idNumber = " + #idNumber + "';",
#subject = #subject,
#body = #body;
It throws and error; it doesn't seem to like concatenating the ID parameter into the query. I tried making a separate procedure to query emails, but passing the ID parameter to the procedure didn't seem to work either. Even if I did successfully pass the parameter and get the query to execute successfully, I'd still need to join the two results in a single string and delimit them with semicolons so they'll play nice with sp_send_dbmail. I think?
SQL wizards, how would you approach this? I'm not wildly experienced, so is there something simple and syntactic I'm doing wrong? Is my approach flawed fundamentally?
I appreciate your input. Thank you.
EDIT: Here's Kritner's working solution! Thanks a bunch!
CREATE PROCEDURE testMail2
#idNumber varchar(MAX)
AS
BEGIN
DECLARE #recipientList varchar(MAX)
SET #recipientList = (STUFF((SELECT ';' + email FROM emailTable WHERE idNumber = #idNumber FOR XML PATH(' ')),1,1,''))
EXEC msdb..sp_send_dbmail
#recipients=#recipientList,
#subject='Subject Line',
#body='Body Text'
END
You can do a query and assign the values to a variable as such:
DECLARE #myRecipientList varchar(max)
SET #myRecipientList = (STUFF((SELECT ';' + emailaddress FROM table FOR XML PATH('')),1,1,''))
This will set your #myRecipientLIst to a ";" delimited list of the recipients specified your query.
You could also do the same sort of idea with a SP, just throw them into a temp/variable table and stuff into a semi colon separated list.
EDIT:
Finally to send the mail you could do:
EXEC msdb.dbo.sp_send_dbmail
#recipients = #recipientList,
#subject = #subject,
#body = #body // ........
COMMENT EDIT:
based on your original query, your stuff query should look something like this:
DECLARE #myRecipientList varchar(max)
SET #myRecipientList = STUFF((SELECT ';' + email FROM emailTable WHERE idNumber = #idNumber FOR XML PATH('')),1,1,'')
The idea behind this is - for every email found in the email table append to #myrecipientList the email found and a semi colon.

Must pass parameter number 4 and subsequent parameter as '#name =value'

I've got the following stored procedure that runs perfectly in SSMS.
Create Store Proc MyTT
SELECT
MAX(TableName) as TableName,
aco_code,acc_code,
ctr_id,cte_id,usr_code,
-- convert(datetime,convert(varchar,current_timestamp,112),112)
Cast(DATEPART(hour,current_timestamp) as varchar(3))+':'+ CAST(DATEPART(minute,current_timestamp) as varchar(3))as [Time]
INTO #AB
FROM
(
SELECT 'TM_ACO_Account_Comment'as TableName,
a.aco_code,
a.acc_code,
a.ctr_id,
a.cte_id,
a.usr_code
FROM
TM_ACO_Account_Comment a with(NOLOCK)
UNION ALL
SELECT 'TM_ACO_Account_Comment'as TableName,
b.aco_code,
b.acc_code,
b.ctr_id,
b.cte_id,
b.usr_code
FROM
[172.17.14.77].[IS_ND_BLAKE].[dbo].[TM_ACO_Account_Comment] b with(NOLOCK)
)zzz
GROUP BY aco_code,
acc_code,
ctr_id,
cte_id,
usr_code
HAVING COUNT(*) = 1
ORDER BY
aco_code
SELECT *
FROM
#AB
DROP TABLE #AB
But when I try to include the procedure in a query to send out mail, I get the following error:
Must pass parameter number 4
My Mail Query looks like this.
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'DBMail',
#recipients = 'mitch#domain.com',
#query = 'exec SP,`MYTT`
#execute_query_database = 'MYDB',
#subject = 'Work Order Count',
#attach_query_result_as_file = 1 ;
In your EXEC msdb.dbo.sp_send_dbmail command, you seem to have not closed the string literal in this line properly:
#query = 'exec SP,`MYTT`
It is missing a closing ', as well as a comma to separate this argument from the next one:
#query = 'exec SP,`MYTT`',
However, the passed query itself looks a bit strange. Your stored procedure is called MyTT and if you meant it to be called in the query you are passing to msdb.dbo.sp_send_dbmail, you specified the exec statement incorrectly. It should probably be simply like this:
#query = 'exec MyTT',
Although it might be a good idea to specify the database and the schema too:
#query = 'exec YourDBName.YourSchema.MyTT',
I have slightly corrected the name proper to match the one in your definition exactly. If your server's default collation is case-insensitive (which is likely), that may be unnecessary, but it would not harm to be consistent in such matters.