Question

I'm trying to use CFmail in a CFScript CFC. I want CFMail to iterate through a query, and change values based on the query contents. It does this just fine, as long as the query object only has 1 row. If it has multiple rows (e.g. 5 rows), it will send 5 emails, but each email will contain the values from the first query row. I've tried a few different things. See below:

Query Obj:

Name    |     Email     |   Number
----------------------------------
John    |  john@foo.com |     12
Bill    |  bill@bar.com |     42
Ann     |  ann@bat.com  |     100

CFScript:

var mailerService = new mail();

mailerService.setQuery(nameEmailNumberQuery);
mailerService.setTo('eterps@sendtomefortesting.com');
mailerService.setFrom( 'noReply@example.com' );
mailerService.setSubject('Hi');
mailerService.setFailto('fail@foo.com');
mailerService.setType('html');
mailerService.setSpoolenable(true);

    savecontent variable="mailBody"{ 
    WriteOutput(
        "Hello " & Name & ". Your number is: " & Number & "!"
    );          
}   

mailerService.send(body=mailBody & tmpVariable);

Using the above code, I get three emails. Each email says, "Hello John. Your number is: 12!"

I've also tried:

WriteOutput(
    "Hello " 
     & mailerService.getQuery().Name 
     & ". Your number is: " 
     & mailerService.getQuery().Number 
     & "!"
);

and:

WriteOutput(
    "Hello " 
    & mailerService.getQuery().Name[mailerService.getQuery.CurrentRow] 
    & ". Your number is: " 
    & mailerService.getQuery().Number[mailerService.getQuery.CurrentRow] 
    & "!"
);

EDIT: A couple more things I've tried (One as suggested by @invertedSpear)

Using the Query literal in the email body:

WriteOutput(
    "Hello " 
    & nameEmailNumberQuery.Name 
    & ". Your number is: " 
    & nameEmailNumberQuery.Number
    & "!"
);

Trying to use an incremented counter:

var counter = 1;
...
WriteOutput(
    "Hello " 
    & mailerService.getQuery().Name[counter] 
    & ". Your number is: " 
    & mailerService.getQuery().Number[counter]
    & "!" & evaluate('counter = counter++')
);

With the same result each time - 3 emails, all with 'John' and '12'. Dumping mailerService.getQuery().CurrentRow results in '1' for each email. I am using Coldfusion 9.0.1 on Windows Server 2008 R3.

Was it helpful?

Solution

In this case, you'll need to do the looping yourself, and call the .send() method for each item in the loop. The MailService won't do the looping for you. So you need to do this:

var mailerService = new mail();

mailerService.setTo('eterps@sendtomefortesting.com');
mailerService.setFrom( 'noReply@example.com' );
mailerService.setSubject('Hi');
mailerService.setFailto('fail@foo.com');
mailerService.setType('html');
mailerService.setSpoolenable(true);

for (x = 1; x <= nameEmailNumberQuery.RecordCount; x=x+1) { 
    savecontent variable="mailBody"{ 
        WriteOutput(
            "Hello " & nameEmailNumberQuery.Name[x] & ". Your number is: " & nameEmailNumberQuery.Number[x] & "!"
        );          
    } 
    mailerService.send(body=mailBody & tmpVariable);
}

That will allow you to configure the base email properties once, and then send a separate email for each item in the row. If each email should go to a unique email address, just move the setTo() method into the loop and reference the proper column for the email address.

OTHER TIPS

Im sure that when you send a mail to a query list, its just sending one mail to a big list of people.

Thus you can't change the name in the one email.

If you want to do what your trying to do, you send multiple mails.

loop over the query and do a cfmail for every record, this will generate a seperate mail.

If you're trying to send out one email to each record in the query, I would just write this in tags. Pretty simple if you do it that way

<cfmail query="nameEmailNumberQuery" 
  to="#nameEmailNumberQuery.Email#" from="noReply@example.com" 
  failto="fail@foo.com" subject="Hi" type="html">

  Hello #nameEmailNumberQuery.Name#. Your number is: #nameEmailNumberQuery.Number#!
</cfmail>

In the examples I see for the tag based version of this they reference the query by name. Have you tried:

WriteOutput(
 "Hello " & arguments.engagementQuery.Name & ". Your number is: " & arguments.engagementQuery.Number & "!"
); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top