Search code examples
coldfusioncoldfusion-9cfmail

Why is CFMAIL ignoring all but the first row of a query when using CFScript?


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    |  [email protected] |     12
Bill    |  [email protected] |     42
Ann     |  [email protected]  |     100

CFScript:

var mailerService = new mail();

mailerService.setQuery(nameEmailNumberQuery);
mailerService.setTo('[email protected]');
mailerService.setFrom( '[email protected]' );
mailerService.setSubject('Hi');
mailerService.setFailto('[email protected]');
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.


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('[email protected]');
    mailerService.setFrom( '[email protected]' );
    mailerService.setSubject('Hi');
    mailerService.setFailto('[email protected]');
    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.