0
votes

I am setting up a group of emails, and start by extracting information from a MySql table

<cfoutput>
<cfset headls ='PersonFn,PersonLn,PersonEmail1'>
<cfquery name = "sord" datasource = "whatever">
  select distinct PersonID,#headls# from PersonRepDb        
</cfquery>
</cfoutput>

This produces the correct output. I then loop through the results of the query, sending an email to each person.

  <cfset sordlen = sord.recordcount>
  <cfloop from = "1" to = "#sordlen#" index = 'j'> 
  <cfmail 
          from     = "#session.user#"  
          to       = "#sord['PersonEmail1'][j]#"          
          password = "#session.password#"
          username = "#session.user#"             
          server   = "localhost"                            
          replyto  = "#txt['replyto']#"
          subject  = "#txt['repsubject']#"               
          type     = "html"   >     

     ...stuff
 </cfmail>
 </cfloop>

When I try to run this program I get an error message: "One of the following attributes must be defined [to, cc, bcc]". Obviously the "to" is there, and if I replace the variable with a specific email like "[email protected]" the error message goes away. So apparently the variable after 'to' is not being decoded.

I tried splitting up the variable sord['PersonEmail1'][j] into the parts before and after the @

<cfset preml = GetToken("#sord['PersonEmail1'][j]#",1,'@')>
<cfset posml = GetToken("#sord['PersonEmail1'][j]#",2,'@')>

and then setting up the to as

 to = "#preml#@#posml#" 

but that did not help.

Can anyone tell me how to fix this?

1
What version of CF? - Shawn
And do you need to use dynamic column names? Any time you have a dynamic SQL statement, you run a risk of injection. If you have multiple columns that you may need, you might be better off just selecting all of the columns you need and filtering them later. - Shawn
There doesn't appear to be anything wrong with your code. Are your other variables returning what you expect? Also, you don't need a cfloop, you can specify a query="sord" attribute, and it will step through your query results for you. Then you'd just use .....to=sord.PersonEmail1...... - Shawn
I would prefer cfoutput query = 'sord' , but the output tag seems to cause problems with the cfmail tag. Do you know that I can use that with a cfmail tag? I have multiple people and each must receive his/her own cfmail tag, because the email has dynamic content. You are right that my variable was not returning what I thought. Things seem to be working now. - Betty Mock
So what's the actual value of #sord['PersonEmail1'][j]# when the error occurs? Obviously sanitize the name and domain. - SOS

1 Answers

2
votes

This should be all you need to do. If you're trying to make the list of columns from the DB dynamic, that's probably not needed. Just validate that the contents of the email column is a valid email format before sending.

<cfquery name="sord" datasource="whatever">
    select distinct 
        PersonID,
        PersonFn,
        PersonLn,
        PersonEmail1
    from 
        PersonRepDb        
</cfquery>

<cfloop query="sord">
    <cfif isValid("email", sord.PersonEmail1)>
        <cfmail 
            from     = "#session.user#"
            to       = "#sord.PersonEmail1#"
            password = "#session.password#"
            username = "#session.user#"
            server   = "localhost"
            replyto  = "#txt['replyto']#"
            subject  = "#txt['repsubject']#"
            type     = "html">

        ...stuff
    </cfmail>
</cfloop>