Skip to main content
Inspiring
April 8, 2009
Answered

Customizing e-mail for multiple recipients

  • April 8, 2009
  • 2 replies
  • 1674 views

I have a small app that allows a user to enter a message along with some fields to be personalized. So, when the email comes through it will say "Dear John Doe, Thanks for purchasing our Fitness book", etc. The problem I'm running into is personalizing the content. I can only get it to pull the first record from the recordset, instead of all of them. In other words, if the email goes out to 10 people, all 10 of them get the first and last name associated with the first record.

This is what my code looks like:

<cfoutput query="getFields">

            <cfscript>

               variables.content = ReplaceNoCase(variables.content, "*"&column_name&"*", evaluate("getCustomers."&column_name), "ALL");

            </cfscript>
</cfoutput>

<cfmail from="#attributes.from_address#" to="#trim(emailaddress)#" subject="#attributes.title#" query="getCustomers" type="HTML">
#variables.content#
</cfmail>

This is what the source of the email looks like:

Dear *fname* *lname*, Thanks for purchasing our *bookTitle*

How can I make cfmail merge each row's value? Am I forced to loop over the recordset and call cfmail each time? This seems really inefficient.

TIA

    This topic has been closed for replies.
    Correct answer ilssac

    Ok that isn't going to work....

    Maybe this... you need to replace the place holders with variables and evaluate the variable inside the loop.  Again...if I could I would rework this.

    <cfoutput query="getFields">

                <cfscript>

                  variables.content = ReplaceNoCase(variables.content, "*"&column_name&"*", "##getCustomers.column_name[getCustomers.currentRow]##"), "ALL");

                </cfscript>
    </cfoutput>

    <!---

    You want virables.content to look literally like this:

    First Name: #getCustomer.firstName[getCustomer.currentRow]#

    Last Name: #getCustomer.lastName[getCustomer.currentRow]#

    --->

    <cfmail from="#attributes.from_address#" to="#trim(emailaddress)#" subject="#attributes.title#" query="getCustomers" type="HTML">
    #evaluate(de(variables.content))#

    The evaluate(de()) function combo will evaluate the internal variables of the variables.content string before evaluation variables.content itself.

    </cfmail>

    2 replies

    ilssac
    Inspiring
    April 9, 2009

    Balance wrote:

                <cfscript>

                   variables.content = ReplaceNoCase(variables.content, "*"&column_name&"*", evaluate("getCustomers."&column_name), "ALL");

                </cfscript>

    Your evaluate expression is always going to reference the first row of the getCustomers record set.  A fully referenced record set variable is in the form of query.column[row] OR query['column'][row].

    So your evaluate would need to look like this: evaluate("getCustomers." & column_name & '[' & row & ']')

    Or better yet, without the evaluate function: replaceNoCase(variable.content, "*" & column_name & "*", getCustomer[column_name][row], "All").

    Now you have to decide where does that "row" value come from, my first guess would be the auto generated currentRow.

    <cfscript>

          variables.content = ReplaceNoCase(variables.content, "*"&column_name&"*", getCustomer[column_name][getCustomer.currentRow], "ALL");

    </cfscript>

    Message was edited by: Ian Skinner

    BalanceAuthor
    Inspiring
    April 9, 2009

    Thanks, but this also doesn't work. It's still only picking up the first record in the dataset since the replace() happens outside of the CFMail tag.

    Here's what the variables.content variable looks like:

    fname = *fname*

    lname = *lname*

    emailaddress = *emailaddress*


    Then, I have this:

    <cfscript>
          variables.content = ReplaceNoCase(variables.content, *&column_name&*, getCustomer[column_name][getCustomer.currentRow], ALL);
    </cfscript>
    <cfmail from="#attributes.from_address#" to="#trim(emailaddress)#" subject="#attributes.title#" query="getCustomers" type="HTML">
    <p>Embedded in cfmail: emailaddress = #emailaddress#</p>END<br />
    #variables.content#
    </cfmail>

    The "embedded in cfmail" line works fine (it's personalized accurately), but #variables.content# it's still only grabbing that first record.

    Thoughts?

    Thanks

    April 9, 2009

    Anything that you want to be customized on a user by user basis must be done inside the cfmail tag. Just treat it like a cfoutput, and you're good to go.

    Dan

    April 9, 2009

    Treat the cfmail just like a cfoutput.

    <cfmail from="#attributes.from_address#" to="#trim(emailaddress)#" subject="#attributes.title#" query="getCustomers" type="HTML">
    Dear #fName# #lName, thank you for purchasing #bookTitle#

    #variables.content#
    </cfmail>

    Dan

    BalanceAuthor
    Inspiring
    April 9, 2009

    Dan,

    I understand what you're saying, but the problem is that the variable that holds the references to fields is the actual content that needs to be sent. In other words, variables.content is equal to: #fname# #lname#, thanks for purchasing #bookTitle#.

    I tried wrapping variables.content within an evaluate function but that yields an error (presumably b/c of the pound signs in the fields being included in variables.content). Hope that clarifies it.

    Thanks again.

    BalanceAuthor
    Inspiring
    April 9, 2009

    Anyone else?

    thnx