23

I am trying to develop a mail trigger. Could someone assist on how this could be achieved so that when a use inserts a record it check the "speed" field such that when the inserted value exceeds 100, a mail is send to the specified address.

Binod Kalathil
  • 1,939
  • 1
  • 30
  • 43
James Obuhuma
  • 397
  • 3
  • 8
  • 20
  • You also need to GRANT EXECUTE to the user for msdb.dbo.sp_send_dbmail if it is running in an app for example. – smoore4 May 19 '17 at 17:35

1 Answers1

52

First you need to set up database mail - if you haven't done so, this question might help:

Then you need a trigger:

CREATE TRIGGER dbo.whatever
ON dbo.wherever
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS (SELECT 1 FROM inserted WHERE speed > 100)
    BEGIN
        EXEC msdb.dbo.sp_send_dbmail
          @recipients = 'whoever@yourcompany.com', 
          @profile_name = 'default',
          @subject = 'Someone was speeding', 
          @body = 'Yep, they sure were.';
    END
END
GO

Now, you're probably going to say you want data from the insert to be actually be included in the e-mail. And your first inclination is going to be to declare some local variables and assign them from inserted - this doesn't work because your trigger could be responding to a multi-row insert. So the right way to do this is:

CREATE TRIGGER dbo.whatever
ON dbo.wherever
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @body NVARCHAR(MAX) = N'';

    SELECT @body += CHAR(13) + CHAR(10) + RTRIM(some_col) FROM inserted;

    IF EXISTS (SELECT 1 FROM inserted WHERE speed > 100)
    BEGIN
        EXEC msdb.dbo.sp_send_dbmail
          @recipients = 'whoever@yourcompany.com', 
          @profile_name = 'default',
          @subject = 'At least one person was speeding', 
          @body = @body;
    END
END
GO

That all said, I am not a big fan of sending e-mail from a trigger. Even though database mail uses service broker and so is asynchronous, I would be much more inclined to populate a queue table, and have a background thread that comes around and sends all of the appropriate e-mails. The twothree nice things about this are:

  1. you minimize the potential delays in committing the outer transaction that fired the trigger - the more complicated your logic in the trigger, the slower you make that process.
  2. since it is probably not essential that the e-mail is sent the microsecond the row is inserted, you can easily fluctuate the timing of the background process - this avoids having to check the table very minute, all day, when very few times it will ever have to actually do anything.
  3. As @goodeye pointed out, keeping this process separate can prevent errors in the e-mail part of the process from interfering with the original DML (in their case, an invalid parameter to sp_send_dbmail - which I inadvertently suggested - prevented the insert).
Community
  • 1
  • 1
Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
  • Thanks for the feedback. How do I setup the database mail. – James Obuhuma May 25 '12 at 13:47
  • It's been a lot of years since I've done this, but isn't that exactly what calling sp_send_dbmail does? It puts it into a queue, right? – MojoFilter Feb 08 '13 at 18:56
  • @MojoFilter yes, but it's put immediately put on the queue, and you have no control over the mechanics in sp_send_dbmail. I'd rather control the mail flow myself. Again, a preference. You want to send mail inside the trigger, by all means, go ahead. – Aaron Bertrand Feb 08 '13 at 19:30
  • In my 2008 R2, The sp_send_dbmail has `@recipients` parameter, not a `@to` parameter. Chasing this made your point about separating processes - the insert didn't happen because of this error. – goodeye Jun 18 '14 at 15:30
  • Sorry to be late but I would ask a precisation about that solution. Is send mail procedure blocking? Could be a good solution to let trigger to put data For email sending in another table that can be processed by a scheduled job? – gipinani Oct 17 '15 at 21:41
  • Instead of checking every minute, what's another good poll interval to check, how often to check ? – Whirl Mind Feb 07 '20 at 08:18
  • @WhirlMind Are you asking me what is an acceptable maximum delay for an e-mail to be sent, according to your business / users? I can't answer that question. If you don't want to get questions about why an e-mail takes longer than `` minutes to arrive, make the delay at most `` minutes. – Aaron Bertrand Feb 07 '20 at 16:41
  • @AaronBertrand : No. From a technical view, how much polling is too much polling, before it becomes an overload on the server. Of course, wud depend on the server, but what's a typical poll interval in standard environments, if there is any such thing. – Whirl Mind Feb 08 '20 at 18:11