home
Send emails from sql server asynchronously
Author Nigel Rivett
Note that none of this is tested (or maybe even compiled).
It was written in response to someone who wanted a guide.
I may get round to completing it one day.
This allows you to place emails in a table on the requesting server and to send them from a centerl email server.
Note the email sending is here implemented in sql server, which is maybe not a good thing.
The main objectives are to prevent the source process being effected by email problems, keep a record of emails sent and to allow emails to be batched or saved for sending later.
To change the sending code just replace xp_sendmail by nr_sendmail in the correct database.
--********************
--**** client objects
--********************
-- Table to hold emails to send
if exists (select * from dbo.sysobjects where id = object_id(N'[nr_Email]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [nr_Email]
GO
create table nr_Email
(
id int identity ,
recipients varchar(256) ,
Subject varchar(256) ,
Message varchar(1000) ,
Copy_Recipients varchar(256) ,
Attachments varchar(1000) ,
Created datetime default getdate() ,
User varchar(128) default system_user() ,
sent datetime
)
go
create unique index ix_nr_Email_01 on nr_Email
(id)
go
if exists (select * from dbo.sysobjects where id = object_id(N'[nr_Email_CommonData]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [nr_Email_CommonData]
GO
create table nr_Email_CommonData
(
id varchar(20) ,
Data varchar(200)
)
go
create unique index ix_nr_Email_CommonData_01 on nr_Email_CommonData
(id)
go
insert nr_Email_CommonData (id, Data) select 'AttachmentPath', 'c:\temp\'
-- Replacement for xp_sendmail
create proc nr_SendMail
@recipients varchar(26) ,
@Subject varchar(256) ,
@Message varchar(1000) ,
@Copy_Recipients varchar(256) ,
@Attachments varchar(1000) ,
@Query varchar(1000)
as
declare @file varchar(1000)
if @Query is not null and retrim(@Query) <> ''
begin
select @file = value from nr_Email_CommonData where id = 'AttachmentPath'
select @file = @file + 'nr_mail_' + convert(varchar(20),@@spid) + '_' + convert(varchar(8),getdate(),112) + '_' + replace(convert(varchar(8),getdate(),108),':','') + '.csv'
exec ('bcp "' + @Query + '" queryout "' + @file + '" -T -c -S' + @@servername)
select @Attachments = coalesce(@Attachments + ';','') + @file
end
insert nr_Email
(
recipients ,
Subject ,
Message ,
Copy_Recipients ,
Attachments
)
select
@recipients ,
@Subject ,
@Message ,
@Copy_Recipients ,
@Attachments
go
create proc nr_EmailLastSent
(id int)
go
insert nr_EmailLastSent select 0
go
Create proc nr_EmailGet
@num int
as
set rowcount @num
select *
from nr_Email
where id > (select id from nr_EmailLastSent)
order by id
go
Create proc nr_EmailMarkSent
@id
as
update nr_EmailLastSent
set id = @id
go
--********************
--**** server objects
--********************
Create proc nr_EmailControl
@server varchar(128) ,
@workDir varchar(128)
as
declare @sql varchar(1000) ,
@id int ,
@maxid int
declare @recipients varchar(256) ,
@Subject varchar(256) ,
@Message varchar(1000) ,
@Copy_Recipients varchar(256) ,
@Attachments varchar(1000)
create table #a
(
id int ,
recipients varchar(256) ,
Subject varchar(256) ,
Message varchar(1000) ,
Copy_Recipients varchar(256) ,
Attachments varchar(1000) ,
Created datetime default getdate() ,
User varchar(128) default system_user() ,
sent datetime
)
select @sql = 'exec ' + @server + '.admin.dbo.nr_EmailGet'
insert #a
exec (@sql)
select @id = 1 , @maxid = max(id) from #a
while @id < @maxid
begin
select @id = min(id) from #a where id > @id
select @recipients = recipients ,
@Subject = Subject ,
@Message = Message ,
@Copy_Recipients = Copy_Recipients ,
@Attachments = Attachments
from #a
where id = @id
if @AttachFile is not null
begin
select @sql = 'xcopy ' + @AttachFileDir + @AttachFileName + ' ' + @workDir
select @AttachFileName = @workDir + @AttachFileName
exec (@sql)
end
exec master..xp_sendmail
@recipients = recipients ,
@Subject = Subject ,
@Message = Message ,
@Copy_Recipients Copy_Recipients
@attachments = @AttachFileName
select @sql = 'exec ' + @server + '.admin.dbo.nr_EmailMarkSEnt ' + convert(varchar(20), @id)
exec (@sql)
end
go
home