Stored Procedure sends two emails - sql

EDIT
My previous posting on this subject involved specific transactions within the procedure which are no longer used and the error now only seems to occur in a very specific set of circumstances when I use an invalid user name to our companies email address badname#ourcompany.co.uk
The agent runs a stored procedure every ten minutes to send out emails. If it finds a new record then it sends a mail.
Noticed some strange behavior - if the TO field is correct but the BCC is an invalid email address but uses our valid company domain name (e.g. rubbishPart#ourcompany.co.uk) then the stored procedure sends out two emails to the TO. The domain name needs to be our company's domain name to get this behavior ...if I change the domain to gmail.com then only one mail goes out.
Why is this happening?
How do I change this behavior?
Is the Catch in this procedure redundant?
Here is the procedure:
BEGIN TRY
DECLARE #Exit TINYINT = 0
WHILE #Exit = 0
BEGIN
DECLARE #MailIdFound INT =
(
SELECT CASE
WHEN MIN(EmailId) IS NULL THEN 0
ELSE MIN(EmailId)
END
FROM WH.dbo.EmailQueue
WHERE DateEmailKey IS NULL
)
IF #MailIdFound = 0
BEGIN SET #Exit = 1 END --exit here as
ELSE
BEGIN --send the mail here
DECLARE #DateEmailKey INT
DECLARE #EmailBCC NVARCHAR(1000)
DECLARE #EmailTO NVARCHAR(1000)
DECLARE #EmailCC NVARCHAR(1000)
DECLARE #EmailBody NVARCHAR(MAX)
DECLARE #EmailImportance VARCHAR(6)
DECLARE #EmailSubject NVARCHAR(1000);
WITH myMostUrgentMail_cte
AS
(
SELECT TOP 1
DateEmailKey,
EmailBCC,
EmailTO,
EmailCC,
EmailBody,
EmailImportance,
EmailSubject
FROM WH.dbo.EmailQueue
WHERE EmailId = #MailIdFound
)
SELECT #DateEmailKey = DateEmailKey,
#EmailTO = EmailTO,
#EmailCC = EmailCC,
#EmailBCC = EmailBCC,
#EmailBody = EmailBody,
#EmailSubject = EmailSubject
FROM myMostUrgentMail_cte;
SET #EmailBody = #EmailBody + '<html>

<span style=''font-size:11.0pt;font-family:"Calibri","sans-serif"; color:black''><p><b>blah blah</b></p></span></html>'
EXEC msdb..sp_send_dbmail
#recipients = #EmailTO,
#copy_recipients = #EmailCC,
#blind_copy_recipients = #EmailBCC,
#subject = #EmailSubject,
#Importance = #EmailImportance,
#body_format = 'html',
#body = #EmailBody
UPDATE x
SET x.DateEmailKey = (CONVERT(CHAR(8),GETDATE(),(112))),
x.DateEmailTime = (CONVERT([time](7),left(CONVERT([char](12),GETDATE(),(114)),(8)),(0)))
FROM WH.dbo.EmailQueue x
WHERE x.EmailId = #MailIdFound
END
END
END TRY
BEGIN CATCH
-- handle error here
EXEC msdb..sp_send_dbmail
#recipients = 'ME#ME.com;'
, #subject = 'ERROR OCCURED DURING EMAIL CREATION'
, #body_format = 'html'
, #body = 'ERROR OCCURED'
UPDATE x
SET x.ErrorOccured = 1
FROM WH.dbo.EmailQueue x
WHERE x.EmailId = #MailIdFound
END CATCH;

Related

Delete a row from a table in SQL Server and set message for every condition

I have set #message var, and I want to set those message as per conditions but whenever I execute this code it only returns one message which I set
#Message = 'Please provide Topic Name and Topic ID'
Please help me - thanks in advance
ALTER PROCEDURE DeleteTopicNameWebAPI
#InstituteID bigint = 0 ,
#SubjectID bigint = 0,
#TopicName nvarchar(200) = null,
#TopicID bigint = 0
AS
BEGIN
DECLARE #Message nvarchar(200)
IF EXISTS (SELECT 1 FROM TopicMaster
WHERE TopicID = #TopicID AND TopicName = #TopicName AND InstituteID = #InstituteID)
BEGIN
SET #Message = 'Topic name is present in a system'
END
ELSE
BEGIN
SET #Message='Topic Name is not present in a system with Topic ID :'+' '+ Convert(nvarchar (20),#TopicID) + ' And Topic Name :' +' '+#TopicName;
END
IF #TopicID = 0 AND #TopicName IS NULL
BEGIN
DELETE FROM TopicMaster
WHERE InstituteID = #InstituteID
AND CategoryID = #SubjectID
AND TopicName = #TopicName
AND TopicID = #TopicID;
SET #Message ='Done'
END
ELSE
BEGIN
SET #Message = 'Please Provide Topic Name and Topic ID. '
END
SELECT #Message AS [Message]
END
You're overwriting the message. You should append to it instead:
declare #message nvarchar(max) = '';
set #message += 'Now hear this.';
set #message += 'I am hungry.';
Then probably print it out if successful or throw it if not. Don't select it:
print (#message); // or
throw 50000, #message, 1;

Stored procedure for Login Application

I have a table with the user details like
id
fname
lname
role
branch
email
password
I have a stored procedure for the login validation which takes the values of email and password, validates and send out the success message.
The validation is working now. I need to fetch the values of fname, lname, role and branch too.
Here is the code:
USE [Project]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[usp_loginuser]
(#Email varchar(100),
#password varchar(100)
)
AS
BEGIN
DECLARE #msg nvarchar(2048)
SET NOCOUNT ON
--select * from dbo.userdetails where email=#userEmail and pwd=#password
BEGIN TRY
Declare #flag bit
SET #flag = 0
IF EXISTS(Select * from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
AND isactive = 1)
BEGIN
SET #flag =1;
END
ELSE
BEGIN
SET #flag =0;
END
SELECT #flag [IsSuccess]
END TRY
BEGIN CATCH
SET #msg = error_message()
RAISERROR (#msg, 16, 1)
END CATCH
SET NOCOUNT OFF
END
Here is the code
ALTER Procedure [dbo].[usp_loginuser]
(#Email varchar(100),
#password varchar(100),
#fname varchar(100) output,
#lname varchar(100) output
)
AS
BEGIN
DECLARE #msg nvarchar(2048)
SET NOCOUNT ON
BEGIN TRY
Declare #flag bit
SET #flag = 0
IF EXISTS(Select #fname = fname, #lname = lname from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
AND isactive = 1)
BEGIN
SET #flag =1;
END
ELSE
BEGIN
SET #flag =0;
END
SELECT #flag [IsSuccess], #fname, #lname
END TRY
BEGIN CATCH
SET #msg = error_message()
RAISERROR (#msg, 16, 1)
END CATCH
SET NOCOUNT OFF
END
BEGIN TRY
Declare #flag bit
SET #flag = 0
IF EXISTS(Select * from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
AND isactive = 1)
BEGIN
SET #flag =1;
END
ELSE
BEGIN
SET #flag =0;
END
SELECT fname, lname, role, branch from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
END TRY
If you get an empty data set, its a failure else success

Must declare the scalar variable error for stored procedure

I have following stored procedure:
CREATE procedure validateLogin
(
#password varchar(200),
#username varchar(100),
#IpAddress varchar(100)
)
AS
BEGIN
Declare #qry varchar(max), #LockedIp varchar(max), #LockedTime DateTime, #TimeDifference int;
set #qry = 'select IdUser, UserName, FirstName, LastName, idOrg, Users.idRole, Roles.Title as [Role], Allowed_IP from Users, Roles where Users.idRole = Roles.idRole
and lower(UserName) = #username and [password] = #password' ;
select
#LockedIp = isnull(Allowed_IP,''),
#LockedTime = isnull(LockedTime, getDate())
from Users
where UserName = ISNULL(#username,'');
SELECT
#TimeDifference = DATEDIFF(MINUTE, #LockedTime, GETDATE())
IF exists(select * from Users where UserName = #username AND Password = #password AND Active = 1)
BEGIN
IF exists(select * from Users where UserName = #username AND isnull(IsLocked, 0) = 1)
BEGIN -- BE1
IF(#LockedIp = #IpAddress)
BEGIN --BE2
IF (#TimeDifference >5)
BEGIN --BE5
UPDATE Users
SET IsLocked = 0, LockedTime = null
WHERE UserName = ISNULL(#username,'')
exec(#qry);
END --BE5
ELSE
BEGIN
select 'Your Account has been Locked.Try after some time' as Error
END
END --BE2
Else IF(#LockedIp!=#IpAddress)
BEGIN --BE4
UPDATE Users
SET IsLocked = 0, LockedTime = null
WHERE UserName = isnull(#username,'')
exec(#qry);
END --BE4
END -- BE1
Else
BEGIN --BE3
exec(#qry);
END -- BE3
END
END
Go
When I execute this through:
exec validateLogin '|161|217|4|51','admin','127.0.0.1'
I get following error:
Msg 137, Level 15, State 2, Line 3
Must declare the scalar variable "#username".
I have declared this variable in my parameter list, then also error is showing up.
Please help me.
How can I resolve this?
EXEC() will execute in a different scope, so your parameters are not found. You should use sp_executesql and add your parameters that way:
DECLARE #qry NVARCHAR(MAX);
SET #qry = N'select IdUser,UserName,FirstName,LastName,idOrg,Users.idRole,Roles.Title as [Role],Allowed_IP
from Users,Roles
where Users.idRole=Roles.idRole
and lower(UserName)=#username
and [password]=#password' ;
EXECUTE sp_executesql #qry,
N'#username varchar(100), #password varchar(200)',
#Username,
#Password;

Why is this procedure generating two Emails?

The following stored procedure is run by our agent every 5 mins - it scans the table Control_EmailQueue by using this proc to see if there are any new e-mails to send out.
I wanted to test how the proc behaves when incorrect email information is entered into the table Control_EmailQueue. Two tests and their results are detailed below.
TEST1
I add a record to Control_EmailQueue which has NULL entries in all 3 fields EmailTO/EmailCC and EmailBCC. This works fine i.e and error is trapped and the code within CATCH is executed so I receive an email titled 'ERROR OCCURED DURING EMAIL CREATION'
TEST2
I add a record to Control_EmailQueue. In the field EmailTO I enter this string 'me#me.co.uk; xxxxxxx#xxxxx' i.e. the first email address is valid but the second email address is not valid. When the procedure is run by the agent an email is received by me#me.co.uk but then half a second later another identical email is received by me#me.co.uk. The CATCH code is not executed in this test as the email titled 'ERROR OCCURED DURING EMAIL CREATION' is not received.
BEGIN TRY
DECLARE #Exit TINYINT = 0
WHILE #Exit = 0
BEGIN
BEGIN TRANSACTION
DECLARE #MailIdFound INT =
(
SELECT
CASE
WHEN MIN([EmailId]) IS NULL THEN 0
ELSE MIN([EmailId])
END
FROM [xxx].[console].[Control_EmailQueue]
WHERE
[DateInsertKey] IS NOT NULL
AND
( --the following gives option to re-run past mails by updating DateEmailKey to NULL
[DateEmailKey] IS NULL
OR
[DateEmailKey] < [DateInsertKey]
)
AND
ErrorOccured = 0
AND
EmailActive = 1
)
IF #MailIdFound = 0
BEGIN SET #Exit = 1 END --exit here as
ELSE
BEGIN --send the mail here
--DECLARE #EmailId INT
DECLARE #DateInsertKey INT
DECLARE #DateEmailKey INT
DECLARE #CallingReportName NVARCHAR(1000)
DECLARE #EmailBCC NVARCHAR(1000)
DECLARE #EmailTO NVARCHAR(1000)
DECLARE #EmailCC NVARCHAR(1000)
DECLARE #EmailBody NVARCHAR(MAX)
DECLARE #EmailAttachmentPath NVARCHAR(1000)
DECLARE #EmailImportance VARCHAR(6)
DECLARE #EmailSubject NVARCHAR(1000)
;WITH myMostUrgentMail_cte
AS
(
SELECT
TOP 1
--[EmailId],
[DateInsertKey],
[DateEmailKey],
[CallingReportName],
[EmailBCC],
[EmailTO],
[EmailCC],
[EmailBody],
[EmailAttachmentPath],
[EmailImportance],
[EmailSubject]
FROM [xxx].[console].[Control_EmailQueue]
WHERE [EmailId] = #MailIdFound
)
SELECT
#DateInsertKey = [DateInsertKey],
#DateEmailKey = [DateEmailKey],
#CallingReportName = [CallingReportName],
#EmailTO = [EmailTO],
#EmailCC = [EmailCC],
#EmailBCC = [EmailBCC],
#EmailBody = [EmailBody],
#EmailAttachmentPath = [EmailAttachmentPath],
#EmailImportance = CASE
WHEN [EmailImportance] = 0 THEN 'Low'
WHEN [EmailImportance] = 1 THEN 'Normal'
WHEN [EmailImportance] = 2 THEN 'High'
END,
#EmailSubject = [EmailSubject]
FROM myMostUrgentMail_cte
SET #EmailBody = #EmailBody + '<b>Please contact us with any questions</b></p></span></html>'
EXEC msdb..sp_send_dbmail
#recipients = #EmailTO,
#copy_recipients = #EmailCC,
#blind_copy_recipients = #EmailBCC,
#subject = #EmailSubject,
#file_attachments = #EmailAttachmentPath,
#Importance = #EmailImportance,
#body_format = 'html',
#body = #EmailBody
UPDATE x
SET
x.[DateEmailKey] = (CONVERT(CHAR(8),GETDATE(),(112))),
x.[DateEmailTime] = (CONVERT([time](7),left(CONVERT([char](12),GETDATE(),(114)),(8)),(0)))
FROM [xxx].[console].[Control_EmailQueue] x
WHERE x.[EmailId] = #MailIdFound
END
COMMIT TRANSACTION
END
END TRY
BEGIN CATCH
IF ##trancount>0
BEGIN
ROLLBACK TRANSACTION
END
-- handle error here
DECLARE #ErrorMessage VARCHAR(100) = '<html><p>Error occured during creation of EmailId: ' + CONVERT(VARCHAR(10),#MailIdFound) + '</p><p>xxx.console.Control_EmailQueue</p></html>'
EXEC msdb..sp_send_dbmail
#recipients = 'me#me.co.uk;'
, #subject = 'ERROR OCCURED DURING EMAIL CREATION'
, #body_format = 'html'
, #body = #ErrorMessage
UPDATE x
SET x.ErrorOccured = 1
FROM [xxx].[console].[Control_EmailQueue] x
WHERE x.[EmailId] = #MailIdFound
END CATCH;
END
The problem appears to be related to timing with the transaction. By adding a delay after the commit, the transaction is able to complete and commit prior to the next loop being executed.
One thing you should probably do is get the mailitem_id from sp_send_dbmail. Perhaps you are correct and it is failing, but not erroring, but that shouldn't impact the transaction. The only thing I can think is that you are getting dirty or phantom reads because the transaction isn't actually committed yet, so the small delay allows the data to actually be committed.

SQL Server 2008 DBMail

Could anyone help on the below stored procedure? I am getting error
Incorrect syntax near '#profile_name'" SELECT distinct(EmailAddress)
as RECIPIENTS, #body = Replace(#bodypre, "$Approver", Forename) FROM
[STAS].[dbo].[NotifictationEmailID_View]
in the query
SELECT distinct(EmailAddress) as RECIPIENTS,
#body = Replace(#bodypre, "$Approver", Forename)
FROM [STAS].[dbo].[NotifictationEmailID_View]
which is part of this stored procedure:
ALTER proc [dbo].[test]
as
begin
DECLARE #subject VARCHAR(500)
Declare #bodypre varchar(5000)
DECLARE #ProgramName VARCHAR(50)
DECLARE #FirstName VARCHAR(50)
DECLARE #body VARCHAR(5000)
DECLARE #email VARCHAR(500)
declare #recipients VARCHAR(5000)
DECLARE #CurrentRec AS INT
DECLARE #RecCount AS INT
Declare #emailStop as int
SET #CurrentRec = 1
SET #RecCount = 0
select #subject=EmailMessageSubject,
#bodypre = EmailMessageBody,
#emailStop = EmailStop_Flag
from STAS.dbo.MC_STAS_EmailMessage where TimeSheetStatusID = 3
SELECT #RecCount = COUNT(EmailAddress) FROM [STAS].[dbo].[NotifictationEmailID_View]
if (#emailStop <> 1 AND #RecCount > 0)
WHILE #RecCount >= #CurrentRec
begin
EXEC msdb.dbo.sp_send_dbmail
SELECT distinct(EmailAddress) as RECIPIENTS ,#body =Replace(#bodypre,"$Approver",Forename) from [STAS].[dbo].[NotifictationEmailID_View]
#profile_name = "STAS Email User",
#recipients = #RECIPIENTS,
#subject = #SUBJECT,
#body = #body
SET #CurrentRec = #CurrentRec + 1
end
end
Thanks,
Try this:
SELECT DISTINCT
EmailAddress as RECIPIENTS,
#body = Replace(#bodypre, "$Approver", Forename)
FROM [STAS].[dbo].[NotifictationEmailID_View]
DISTINCT is not a function that you can call like you did - it's a SQL keyword.