USP_ADDRESSPROCESS_EMAILS

Returns email addresses according to email processing and preferences.

Parameters

Parameter Parameter Type Mode Description
@MAILTYPE tinyint IN
@PARAMETERSETID uniqueidentifier IN
@CONSTITUENTIDSETTABLENAME nvarchar(128) IN
@CONSTITUENTIDSETJOINCOLUMNNAME nvarchar(128) IN
@IGNORECHANNELPREFERENCEFORSUPPRESSION bit IN

Definition

Copy


CREATE procedure dbo.[USP_ADDRESSPROCESS_EMAILS]
(
  @MAILTYPE tinyint,
  @PARAMETERSETID uniqueidentifier,
  @CONSTITUENTIDSETTABLENAME nvarchar(128),       --Table or view that contains constituent IDs

  @CONSTITUENTIDSETJOINCOLUMNNAME nvarchar(128),  --Column to use when joining to the table or view

  @IGNORECHANNELPREFERENCEFORSUPPRESSION bit = 0  --0=Respect channel preferences when suppressing email addresses, 1=Ignore channel preferences and do not let other channels (ie: mail) cause email addresses to be suppressed

)
as
  set nocount on;

  --Returns results in the following temp table named #TEMP_ADDRESSPROCESS_EMAILS.  This temp table must exist

  --outside of this stored procedure.  Use the statement below to create the temp table before calling this stored

  --procedure.  The temp table will be indexed on the CONSTITUENTID column.

  --

  --create table #TEMP_ADDRESSPROCESS_EMAILS (

  --  [CONSTITUENTID] uniqueidentifier not null,

  --  [EMAILADDRESS] nvarchar(100) collate database_default,

  --  [CONTACTID] uniqueidentifier

  --);



  declare @CORRESPONDENCECODEID uniqueidentifier;
  declare @EVENTCATEGORYCODEID uniqueidentifier;
  declare @EVENTSITEIDS table ([ID] uniqueidentifier primary key);
  declare @APPEALBUSINESSUNITCODEIDS table ([ID] uniqueidentifier primary key);
  declare @APPEALCATEGORYCODEID uniqueidentifier;
  declare @APPEALSITEID uniqueidentifier;

  declare @OBJID int;
  declare @ISTEMPTABLE bit;
  declare @SQL nvarchar(max);

  --Debug only

  --declare @STARTDATE datetime;

  --declare @STATUS nvarchar(100);



  begin try
    --Validate the required results temp table exists and that it does not have indexes defined on it...

    set @OBJID = object_id('tempdb..#TEMP_ADDRESSPROCESS_EMAILS');
    if @OBJID is null
      raiserror('The temp table #TEMP_ADDRESSPROCESS_EMAILS is required to hold the results of this stored procedure but it does not exist.  Please create the temp table before calling this stored procedure.', 13, 1);
    if exists(select * from tempdb.sys.indexes where object_id = @OBJID and type = 2)  --only concerned with nonclustered indexes

      raiserror('The temp table #TEMP_ADDRESSPROCESS_EMAILS already has indexes defined on it.  Please remove these indexes before calling this stored procedure.', 13, 1);

    --Validate that none of the temp tables used in this stored procedure exist already...

    if object_id('tempdb..#TEMPCONSTITUENT') is not null
      raiserror('The temp table #TEMPCONSTITUENT is used by this stored procedure but it already exists in this session.  Please make sure the temp table does not exist before calling this stored procedure.', 13, 1);
    if object_id('tempdb..#TEMPPRIMARYEMAILADDRESS') is not null
      raiserror('The temp table #TEMPPRIMARYEMAILADDRESS is used by this stored procedure but it already exists in this session.  Please make sure the temp table does not exist before calling this stored procedure.', 13, 1);
    if object_id('tempdb..#TEMPMAILPREFERENCEEMAILADDRESS') is not null
      raiserror('The temp table #TEMPMAILPREFERENCEEMAILADDRESS is used by this stored procedure but it already exists in this session.  Please make sure the temp table does not exist before calling this stored procedure.', 13, 1);
    if object_id('tempdb..#TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS') is not null
      raiserror('The temp table #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS is used by this stored procedure but it already exists in this session.  Please make sure the temp table does not exist before calling this stored procedure.', 13, 1);

    --Validate the constituent IDSet table exists and is defined appropriately...

    if len(@CONSTITUENTIDSETTABLENAME) = 0 or len(@CONSTITUENTIDSETJOINCOLUMNNAME) = 0
      raiserror('The parameters @CONSTITUENTIDSETTABLENAME and @CONSTITUENTIDSETJOINCOLUMNNAME are required to execute this stored procedure.', 13, 1);
    set @ISTEMPTABLE = (case when left(@CONSTITUENTIDSETTABLENAME, 1) = '#' then 1 else 0 end);
    set @OBJID = object_id((case when @ISTEMPTABLE = 1 then 'tempdb..' else 'dbo.' end) + '[' + @CONSTITUENTIDSETTABLENAME + ']');
    if @OBJID is null
      raiserror('The constituent IDSet table specified in the @CONSTITUENTIDSETTABLENAME parameter does not exist.', 13, 1);
    if (@ISTEMPTABLE = 1 and not exists(select * from tempdb.sys.columns c where c.[object_id] = @OBJID and c.[name] = @CONSTITUENTIDSETJOINCOLUMNNAME and c.[system_type_id] = (select t.[system_type_id] from tempdb.sys.types t where t.[name] = 'uniqueidentifier'))) or
       (@ISTEMPTABLE = 0 and not exists(select * from sys.columns c where c.[object_id] = @OBJID and c.[name] = @CONSTITUENTIDSETJOINCOLUMNNAME and c.[system_type_id] = (select t.[system_type_id] from sys.types t where t.[name] = 'uniqueidentifier')))
      raiserror('The constituent IDSet join column specified in the @CONSTITUENTIDSETJOINCOLUMNNAME parameter does not exist or is not defined properly as a uniqueidentifier.', 13, 1);

    if @IGNORECHANNELPREFERENCEFORSUPPRESSION is null
      set @IGNORECHANNELPREFERENCEFORSUPPRESSION = 0;



    --Get some info for different mail types...

    --0 = Revenue Acknowledgements

    --1 = Appeals

    --2 = Events

    --3 = General Correspondence

    --4 = Reminders

    --5 = Receipts

    --6 = Planned Gift Acknowledgements

    --7 = Tribute Acknowledgements

    --8 = Stewardship


    if @MAILTYPE = 1
      begin
        select
          @APPEALCATEGORYCODEID = APPEALCATEGORYCODEID,
          @APPEALSITEID = SITEID
        from dbo.APPEAL
        where ID = @PARAMETERSETID;

        insert into @APPEALBUSINESSUNITCODEIDS ([ID])
          select BUSINESSUNITCODEID
          from dbo.APPEALBUSINESSUNIT
          where APPEALID = @PARAMETERSETID;
      end
    else if @MAILTYPE = 2
      begin
        select
          @EVENTCATEGORYCODEID = E.EVENTCATEGORYCODEID
        from dbo.EVENT E
        inner join dbo.INVITATION I on E.ID = I.EVENTID
        where I.ID = @PARAMETERSETID;

        insert into @EVENTSITEIDS ([ID])
          select E.SITEID
          from dbo.EVENTSITE E
          inner join dbo.INVITATION I on E.EVENTID = I.EVENTID
          where I.ID = @PARAMETERSETID;
      end
    else if @MAILTYPE = 3
      select
        @CORRESPONDENCECODEID = CORRESPONDENCECODEID
      from dbo.CORRESPONDENCEPROCESS
      where ID = @PARAMETERSETID;





    /****************************************************/
    /* Constituents                                     */
    /****************************************************/
    --Debug only

    --raiserror('Constituents...', 0, 1) with nowait;

    --set @STARTDATE = getdate();


    create table #TEMPCONSTITUENT (
      [ID] uniqueidentifier not null
    );

    set @SQL = 'insert into #TEMPCONSTITUENT ([ID])' + char(13) +
               '  select ' + quotename(@CONSTITUENTIDSETJOINCOLUMNNAME) + char(13) +
               '  from dbo.' + quotename(@CONSTITUENTIDSETTABLENAME);

    exec sp_executesql @SQL;

    --Create an index on the temp table...

    create nonclustered index [IX_TEMPCONSTITUENTS_ID] on #TEMPCONSTITUENT ([ID]);

    --Debug only

    --set @STATUS = 'Constituents... ' + cast((select count(*) from #TEMPCONSTITUENT) as nvarchar(10)) + ' rows... ' + cast(datediff(s, @STARTDATE, getdate()) as nvarchar(10)) + ' seconds';

    --raiserror(@STATUS, 0, 1) with nowait;







    /****************************************************/
    /* Mail Preference Email Addresses                  */
    /****************************************************/
    --Debug only

    --raiserror('Mail Preference Email Addresses...', 0, 1) with nowait;

    --set @STARTDATE = getdate();


    create table #TEMPMAILPREFERENCEEMAILADDRESS (
      [CONSTITUENTID] uniqueidentifier not null,
      [EMAILADDRESS] nvarchar(100) collate database_default,
      [CONTACTID] uniqueidentifier
    );

    insert into #TEMPMAILPREFERENCEEMAILADDRESS ([CONSTITUENTID], [EMAILADDRESS], [CONTACTID])
      select
        E.[CONSTITUENTID],
        E.[EMAILADDRESS],
        E.[CONTACTID]
      from #TEMPCONSTITUENT C
      inner join dbo.[UFN_ADDRESSPROCESS_EMAILPREFERENCES](@MAILTYPE, @PARAMETERSETID) E on E.[CONSTITUENTID] = C.[ID];

    --Create an index on the temp table...

    create nonclustered index [IX_TEMPMAILPREFERENCEEMAILADDRESS_CONSTITUENTID] on #TEMPMAILPREFERENCEEMAILADDRESS ([CONSTITUENTID])
      include ([EMAILADDRESS], [CONTACTID]);

    --Debug only

    --set @STATUS = 'Mail Preference Email Addresses... ' + cast((select count(*) from #TEMPMAILPREFERENCEEMAILADDRESS) as nvarchar(10)) + ' rows... ' + cast(datediff(s, @STARTDATE, getdate()) as nvarchar(10)) + ' seconds';

    --raiserror(@STATUS, 0, 1) with nowait;






    /*****************************************************/
    /* Orgs With No Preference - Contact Email Addresses */
    /*****************************************************/
    --Debug only

    --raiserror('Orgs With No Preference - Contact Email Addresses...', 0, 1) with nowait;

    --set @STARTDATE = getdate();


    create table #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS (
      [CONSTITUENTID] uniqueidentifier not null,
      [EMAILADDRESS] nvarchar(100) collate database_default,
      [CONTACTID] uniqueidentifier
    );

    --For all organizations that do not have any mail preferences specified, or were excluded from above...

    --Since we don't have "email address" processing options to specify whether or not to use the contact's email (like we do for "mail" addresses),

    --we automatically assume we need to pull the contact emails for all organizations that don't have a preference above.  We also pull the

    --organization's valid primary email since we don't know if we should split out the contacts or not.  It will be the caller's responsibility

    --to join to the resulting temp table correctly on the CONSTITUENTID and CONTACTID fields (remember CONTACTID can be null).  Pull the email address

    --off all the contact records and consider this the contact's "primary email" (instead of their personal email) (we'll still need to check the

    --"Do not email" flag).  We do this instead of showing the contact with the organization's valid primary email or the contact's personal email.

    with [ORG_NO_PREF] ([ID]) as
    (
      --All orgs with no preferences (or they do have a preference - either different preference criteria or the email is not valid)

      select C.[ID]
      from #TEMPCONSTITUENT C
      inner join dbo.[CONSTITUENT] as [ORG] on [ORG].[ID] = C.[ID]
      where [ORG].[ISORGANIZATION] = 1
      and not exists(select * from #TEMPMAILPREFERENCEEMAILADDRESS where [CONSTITUENTID] = C.[ID])
    )
    insert into #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS ([CONSTITUENTID], [EMAILADDRESS], [CONTACTID])
      --All orgs with no preference and a valid primary email

      select
        [ORG_NO_PREF].[ID],
        E.[EMAILADDRESS],
        null
      from [ORG_NO_PREF]
      inner join dbo.[EMAILADDRESS] as E on E.[CONSTITUENTID] = [ORG_NO_PREF].[ID]
      where E.[ISPRIMARY] = 1  --only constits with a primary email

      and E.[DONOTEMAIL] = 0  --only constits with a valid email

      union all
      --All contacts with a valid email of orgs with no preference

      select
        [ORG_NO_PREF].[ID],
        [CA].[EMAILADDRESS],
        [CA].[CONSTITUENTID]
      from [ORG_NO_PREF]
      inner join dbo.[RELATIONSHIP] on [RELATIONSHIP].[RELATIONSHIPCONSTITUENTID] = [ORG_NO_PREF].[ID]
      inner join dbo.[EMAILADDRESS] as [CA] on [CA].[RELATIONSHIPID] = [RELATIONSHIP].[ID]
      where [RELATIONSHIP].[ISCONTACT] = 1
      and [CA].[DONOTEMAIL] = 0;  --only contacts with a valid email


    --Create an index on the temp table...

    create nonclustered index [IX_TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS_CONSTITUENTID] on #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS ([CONSTITUENTID])
      include ([EMAILADDRESS], [CONTACTID]);

    --Debug only

    --set @STATUS = 'Orgs With No Preference - Contact Email Addresses... ' + cast((select count(*) from #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS) as nvarchar(10)) + ' rows... ' + cast(datediff(s, @STARTDATE, getdate()) as nvarchar(10)) + ' seconds';

    --raiserror(@STATUS, 0, 1) with nowait;







    /****************************************************/
    /* Valid Primary Email Addresses                    */
    /****************************************************/
    --Debug only

    --raiserror('Valid Primary Email Addresses...', 0, 1) with nowait;

    --set @STARTDATE = getdate();


    create table #TEMPPRIMARYEMAILADDRESS (
      [CONSTITUENTID] uniqueidentifier not null,
      [EMAILADDRESS] nvarchar(100) collate database_default
    );

    --Since we don't have email address processing options to specify whether or not to use the primary email (like we do for mail addresses),

    --we automatically assume we need to pull the primary emails for all people that don't have a preference above.

    insert into #TEMPPRIMARYEMAILADDRESS ([CONSTITUENTID], [EMAILADDRESS])
      select
        E.[CONSTITUENTID],
        E.[EMAILADDRESS]
      from #TEMPCONSTITUENT as C
      inner join dbo.[EMAILADDRESS] as E on E.[CONSTITUENTID] = C.[ID]
      where E.[ISPRIMARY] = 1  --only constits with a primary email

      and E.[DONOTEMAIL] = 0  --only constits with a valid email

      and not exists(select * from #TEMPMAILPREFERENCEEMAILADDRESS where [CONSTITUENTID] = E.[CONSTITUENTID])
      and not exists(select * from #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS where [CONSTITUENTID] = E.[CONSTITUENTID]);

    --Create some indexes on the temp table...

    create nonclustered index [IX_TEMPPRIMARYEMAILADDRESS_CONSTITUENTID] on #TEMPPRIMARYEMAILADDRESS ([CONSTITUENTID])
      include ([EMAILADDRESS]);

    --Debug only

    --set @STATUS = 'Valid Primary Email Addresses... ' + cast((select count(*) from #TEMPPRIMARYEMAILADDRESS) as nvarchar(10)) + ' rows... ' + cast(datediff(s, @STARTDATE, getdate()) as nvarchar(10)) + ' seconds';

    --raiserror(@STATUS, 0, 1) with nowait;








    /****************************************************/
    /* BasicDev only                                    */
    /****************************************************/
    declare @USEDONOTSENDOTHERCHANNEL bit;

    set @USEDONOTSENDOTHERCHANNEL = (
      case when exists(
        select * 
        from dbo.[INSTALLEDPRODUCTLIST] 
        where [ID] = '42c15648-749e-4859-a56d-3a6474814cc7' 
        and ([EXPIREDATE] = '' or [EXPIREDATE] >= getdate()))
      then 1 else 0 end);


    /****************************************************/
    /* Return the final email addresses                 */
    /****************************************************/
    --Debug only

    --raiserror('Return the final email addresses...', 0, 1) with nowait;

    --set @STARTDATE = getdate();


    with [EMAILS] ([CONSTITUENTID], [EMAILADDRESS], [CONTACTID]) as
    (
        select [CONSTITUENTID], [EMAILADDRESS], [CONTACTID] from #TEMPMAILPREFERENCEEMAILADDRESS
        union all
        select [CONSTITUENTID], [EMAILADDRESS], [CONTACTID] from #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS
        union all
        select [CONSTITUENTID], [EMAILADDRESS], null from #TEMPPRIMARYEMAILADDRESS
    )
    insert into #TEMP_ADDRESSPROCESS_EMAILS ([CONSTITUENTID], [EMAILADDRESS], [CONTACTID])
      select
        [EMAILS].[CONSTITUENTID],
        [EMAILS].[EMAILADDRESS],
        [EMAILS].[CONTACTID]
      from [EMAILS]
      where
      (
        --Verify that the comm prefs allow the user to receive mailings

        isnull((
        select SUPPRESSMAILING from 
        (
          select top 1
  case when (SENDMAIL = 0 or (@IGNORECHANNELPREFERENCEFORSUPPRESSION = 0 and SENDMAIL = 1 and DELIVERYMETHODCODE = 0 and (@USEDONOTSENDOTHERCHANNEL = 0 or (@USEDONOTSENDOTHERCHANNEL = 1 and DONOTSENDOTHERCHANNEL = 1)))) then 1 else 0 end SUPPRESSMAILING,
            case
              --Revenue acknowledgements

              when @MAILTYPE = 0 and (ACKNOWLEDGEMENTID is not null) then 1
              --Appeals

              when @MAILTYPE = 1 and (SITEID is not null and BUSINESSUNITCODEID is not null and CATEGORYCODEID is not null) then 3
              when @MAILTYPE = 1 and (SITEID is not null and BUSINESSUNITCODEID is not null) then 2
              when @MAILTYPE = 1 and (SITEID is not null and CATEGORYCODEID is not null) then 2
              when @MAILTYPE = 1 and (BUSINESSUNITCODEID is not null and CATEGORYCODEID is not null) then 2
              when @MAILTYPE = 1 and (SITEID is not null or BUSINESSUNITCODEID is not null or CATEGORYCODEID is not null) then 1
              --Events

              when @MAILTYPE = 2 and (EVENTCATEGORYCODEID is not null and SITEID is not null) then 2
              when @MAILTYPE = 2 and (EVENTCATEGORYCODEID is not null or SITEID is not null) then 1
              --Correspondence

              when @MAILTYPE = 3 and (CORRESPONDENCECODEID is not null and CORRESPONDENCEID is not null) then 2
              when @MAILTYPE = 3 and (CORRESPONDENCECODEID is not null or CORRESPONDENCEID is not null) then 1
              --Reminders

              when @MAILTYPE = 4 and (PLEDGEREMINDERID is not null) then 1
              --Stewardship

              when @MAILTYPE = 8 and (PURPOSEID is not null) then 1
              else 0
            end as CRITERIAMATCHSCORE
          from dbo.MAILPREFERENCE
          where CONSTITUENTID = [EMAILS].[CONSTITUENTID]
          and MAILTYPECODE = @MAILTYPE
          and
          (
            (case @MAILTYPE
              when 0 then ACKNOWLEDGEMENTID
              when 3 then CORRESPONDENCEID
              when 4 then PLEDGEREMINDERID
              when 8 then PURPOSEID
              else null
              end) = @PARAMETERSETID
            or 
            (case @MAILTYPE
              when 0 then ACKNOWLEDGEMENTID
              when 3 then CORRESPONDENCEID
              when 4 then PLEDGEREMINDERID
              when 8 then PURPOSEID
              else null
             end) is null
          )
          and ((CORRESPONDENCECODEID is null) or (@MAILTYPE = 3 and CORRESPONDENCECODEID = @CORRESPONDENCECODEID))
          and ((EVENTCATEGORYCODEID is null) or (@MAILTYPE = 2 and EVENTCATEGORYCODEID = @EVENTCATEGORYCODEID))
          and
          (
            (SITEID is null) or 
            (@MAILTYPE = 1 and SITEID = @APPEALSITEID) or
            (@MAILTYPE = 2 and SITEID in (select [ID] from @EVENTSITEIDS))
          )
          and ((PURPOSEID is null) or (@MAILTYPE = 8 and PURPOSEID = @PARAMETERSETID))
          and ((BUSINESSUNITCODEID is null) or (@MAILTYPE = 1 and BUSINESSUNITCODEID in (select [ID] from @APPEALBUSINESSUNITCODEIDS)))
          and ((CATEGORYCODEID is null) or (@MAILTYPE = 1 and CATEGORYCODEID = @APPEALCATEGORYCODEID))
          order by CRITERIAMATCHSCORE desc, SUPPRESSMAILING desc
        ) as MATCHEDPREFERENCES
        ), 0) = 0
      );

    --Create indexes on the final email address results...

    create nonclustered index [IX_TEMP_ADDRESSPROCESS_EMAILS_CONSTITUENTID] on #TEMP_ADDRESSPROCESS_EMAILS ([CONSTITUENTID])
      include ([EMAILADDRESS], [CONTACTID]);

    --Debug only

    --set @STATUS = 'Return the final email addresses... ' + cast((select count(*) from #TEMP_ADDRESSPROCESS_EMAILS) as nvarchar(10)) + ' rows... ' + cast(datediff(s, @STARTDATE, getdate()) as nvarchar(10)) + ' seconds';

    --raiserror(@STATUS, 0, 1) with nowait;






    /****************************************************/
    /* Clean up                                         */
    /****************************************************/
    drop table #TEMPCONSTITUENT;
    drop table #TEMPMAILPREFERENCEEMAILADDRESS;
    drop table #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS;
    drop table #TEMPPRIMARYEMAILADDRESS;
  end try

  begin catch
    exec dbo.[USP_RAISE_ERROR];

    if object_id('tempdb..#TEMPCONSTITUENT') is not null
      drop table #TEMPCONSTITUENT;
    if object_id('tempdb..#TEMPMAILPREFERENCEEMAILADDRESS') is not null
      drop table #TEMPMAILPREFERENCEEMAILADDRESS;
    if object_id('tempdb..#TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS') is not null
      drop table #TEMPORGANIZATIONNOPREFERENCEEMAILADDRESS;
    if object_id('tempdb..#TEMPPRIMARYEMAILADDRESS') is not null
      drop table #TEMPPRIMARYEMAILADDRESS;

    return 1;
  end catch

  return 0;