Search code examples
coldfusioncfmail

Pass queried parameters to ColdFusion file multiple times?


I have an cfmail function set-up in a particular file, email_output.cfm, which requires an ID passed to it to work properly, like email_output.cfm?ID=1. I want to set up a cron job that runs through a query returning the various needed IDs to pass. In testing, I can do the following:

  <cflocation url="email_output.cfm?ID=10" >

But, since cflocation stops all other execution and opens another page, I can't loop through it. How would I pass parameters from a query to a single CF page multiple times?

Thanks - Joe


Solution

  • A custom tag sample implementation of this...

    If this is your first time using a custom tag, it's easiest to put it in the same folder as the page calling it. There are a few options for putting it in a different directory, but let's start simple.

    EmailMembers.cfm

    <cfquery name="GetUIDs">
      select userid from users
    </cfquery>
    
    <cfoutput query="GetUIDs">
      <cf_maileach uid="#userID#">
    </cfoutput>
    

    Notice how I called my tag cf_maileach?

    In the same directory, place maileach.cfm, see how the names match?

    maileach.cfm

    <cfif StructKeyExists(attributes,"uid") and val(attributes.uid) gt 0>
      <cfquery name="getinfo">
        select fname,lname,email
          from users
         where userID = <cfqueryparam cfsqltype="cf_sql_integer" value="#attributes.uid#">
      </cfquery>
    
      <cfmail to="#getinfo.email#" subject="Hi #getinfo.fname#">...</cfmail>
    </cfif>
    

    Notes

    • Depending on your version of cf, and whether you're using application.cfc or not, there are several ways to place a custom tag in an outside directory. There is also <cfmodule>
    • This is a sample only, something this basic is redundant, I was just trying to mimic what asker outlined. In this sample, I'm calling a query that could get all the data, only to use it to query row by row.
    • If you're not familiar with <cfqueryparam>, look it up, use it, love it.

    Edit: While a CFHTTP method can serve this purpose, it suffers a few problems

    • Sessions are not automatically passed (even if the requesting server and destination server are the same.).
    • The page is accessed like a browser request. Application/OnRequestEnd are processed (and since session info is passed as well, this can cause problems trying to access files in secured areas.
    • Because of the above, the page would need to be in a folder with its own Application file to negate any application files above it in the directory hierarchy.
    • To combat 1, 2, and 3, You'd need to code in a layer of security, similar to your application's own security, so that the file is not vulnerable should the url be found.
    • Each call to the file via cfhttp would need to invoke some extra security checking.
    • It is significantly slower. In a very simple test with a zero-content application.cfc, the custom tag method was executing in literally <= 1/100th of the time. As actual function is added to the method, the difference in results would change.

    Here is some sample code to test this yourself.

    Contents of folder "safe":

    Application.cfc

    [ blank file, to negate my testing site's actual application.cfc ]
    

    Testrun.cfm

    <cfoutput><cfset starttick = GetTickCount()>
    <cfloop from="1" to="20" index="i">
      <cfhttp url="http://mysamesite.com/safe/http.cfm?u=#i#" method="get" result="test">
      #test.filecontent#<br>
    </cfloop>
    CFHTTP Execution Time: #(GetTickCount() - starttick)#<br><br>
    
    <cfset starttick = GetTickCount()>
    <cfloop from="1" to="20" index="i">
      <cf_testtag u="#i#"><br>
    </cfloop>
    CustomTag Execution Time: #(GetTickCount() - starttick)#<br><br>
    </cfoutput>
    

    testtag.cfm

    <cfoutput>The ID entered was #attributes.u#</cfoutput>
    

    http.cfm

    <cfoutput>The ID entered was #url.u#</cfoutput>
    

    Results (in milliseconds) Each test was 20 passes at HTTP and 20 Passes at the custom tag.

    CFHTTP  Tag
    661ms   6ms
    1624    5
    616     5
    460     4
    522     6
    816     4