ColdFusion Try Catch on loop through mail function - coldfusion

I've got a list of email addresses that an email is sent to. The mail function loops through the list from the database but if it encounters a malformed email address, it halts and breaks out of the loop. I've tried using try/catch to catch the error and was hoping it'd continue through the loop but it's not worked as I'd hoped. The code is below. If anyone has any ideas, or maybe a regex that I can sift through the email addresses before the loop to filter out bad ones, that'd be awesome.
Thanks.
<!---Try to send the mail(s)--->
<cftry>
<cfmail to="<#Auctioneer.email#>" from="#emailSite#" subject="#Email.subject#" server="#emailServer#" query="Auctioneer" type="html">
<!---Some email content--->
</cfmail>
<cfcatch type="Application">
<cflog text="#cfcatch.detail#" file="mail" type="Error" application="yes">
<cfmail to="admin#website.co.uk" from="#emailSite#" subject="Invalid E-Mail Address" type="html">
Email address not valid error.
#Auctioneer.email#
<cfdump var="#cfcatch.detail#">
</cfmail>
</cfcatch>
</cftry>

What you want is to loop through the addresses, validate them and send mails only for valid entries. Something like this
<cfloop query="getEmails">
<cfif isValid("email", Auctioneer.email)
...send valid email...
<cfelse>
...send invalid email, or better log in database...
</cfif>
</cfloop>
P.S. No need to put <> in to.

You could try validating the e-mail addresses in the query first.
For me, though, I never liked having the CFMAIL tag manage the query. It always seemed to cause more trouble than it's worth. I usually do something like this:
<cfoutput query="Auctioneer">
<cftry>
<cfmail to="#email#" from="#variables.emailSite#" subject="#variables.subject#" server="#application.emailServer#" type="html">
<!---Some email content--->
</cfmail>
<cfcatch type="Application">
<cflog text="#cfcatch.detail#" file="mail" type="Error" application="yes">
<cfmail to="admin#website.co.uk" from="#variables.emailSite#" subject="Invalid E-Mail Address" type="html">
Email address not valid error.
#email#
<cfdump var="#cfcatch.detail#">
</cfmail>
</cfcatch>
</cftry>
</cfoutput>

I would personally loop through them, catch the error and continue the loop.
for(var i = 1; i < Auctioneer.recordCount; i++) {
try {
//send email
} catch (Any e) {
//log
continue;
}
}

Related

Order of emails is changed when sending multiple emails with CFMail

I have an issue while sending the below two emails through CF 2016. When I run my code I'm receiving the "Password" email first and then the "Username" mail second. The order of sending is getting changed. I need to get "Username" mail first and then "Password" mail. How can I resolve this?
<cfmail to="#toEmail#" from="#fromEmail#" subject="Username" type="html">
Your username is #username#
</cfmail>
<cfmail to="#toEmail#" from="#fromEmail#" subject="Password" type="html">
Your password is #password#
</cfmail>
You can disable mail spooling on a per cfmail basis with spoolEnable. It does slow down the page though. Try it on only the first email. That will send out the first email immediately. Then let the second email get spooled for idle/later delivery.
<cfmail to="#toEmail#" from="#fromEmail#" subject="Username" type="html" spoolEnable="no">
Your username is #username#
</cfmail>
<cfmail to="#toEmail#" from="#fromEmail#" subject="Username" type="html">
Your username is #username#
</cfmail>
You could always to do something like this:
<cfmail to="#toEmail#" from="#fromEmail#" subject="Username" type="html">
Your username is #username#
</cfmail>
<cfthread name="SendPassword" action="run">
<cfscript>
sleep(appropriate number of milliseconds);
</cfscript>
<cfmail to="#toEmail#" from="#fromEmail#" subject="Password" type="html">
Your password is #password#
</cfmail>
</cfthread>
Look at your spool settings to get the appropriate number of milliseconds.

Coldfusion how to get function name and line number when application crashed or error

i'm working on my legacy system old code of coldfusion, is there a way i can define cfcatch in application.cfc and catch all errors of my application with
Function name
Query name
Line Number of code
Template Name
To debug fast rather then writing everywhere in code.
application developer did not catch any error anywhere in code.i did insert cfcatch in code some of the places but still lot more to do, and because of production i don't want to modify so much of code.
im inserting cfcatch in databse and sending email to development team. because system is in production.
You can use the cferror tag, or onError to direct all errors to a given page/function.
If you use cferror, the exception will be passed in the error variable. If you use OnError, it's a parameter.
To help you along, my own error emails include the following. You will notice that we have special handling to help point out places where a blank may have been passed into a sql integer field, which happens more often than I'd like to admit.
An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br />
Time: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br />
<!--- Smarter error catching for form fields --->
<cfif (error.message contains "Invalid data '' for CFSQLTYPE CF_SQL_INTEGER") and isdefined("form")>
<!--- This stores a list of the Id fields --->
<cfloop collection="#form#" item="thisField">
<!--- Get the last two characters of the field name --->
<cfset lastTwoChars = right(thisField, 2)>
<!--- Get the value of the field --->
<cfset thisFieldValue = evaluate('form.#thisField#')>
<!--- Check to see if this is an Id field and if it's value is blank. --->
<cfif lastTwoChars eq 'Id' and thisFieldValue eq ''>
<h3 style="font-weight: bold; color: red">#thisField# is blank and it's possibly an integer field.</h3>
</cfif>
</cfloop>
</cfif>
<cfdump var="#error#" label="Error">
<br/>
<cfdump var="#form#" label="Form">
<br/>
<cfdump var="#url#" label="URL">
<br/>
<cfdump var="#session#" label="session">

Catching an error message

I'm using Coldfusion Fusebox 3 and I would like to know how I can keep my app from throwing an error message if someone thoughtlessly removes the Circuit and fuseaction from the URL.
For example, if the original URL is:
http://www.noname/Intranet/index.cfm?fuseaction=Bulletins.main
...and someone removes the circuit information so it reads like the following: http://www.noname/Intranet/index.cfm?fuseaction=
...the app throws an error message. Can I code against something like this happening?
Here is my fbx_Settings.cfm file as it exists right now. Thank you.
Try something along these lines, haven't had chance to test but should go something like this in your index.cfm file.
<cfprocessingdirective suppressWhiteSpace="yes">
<cftry>
<!--- Include the config file --->
<cfinclude template="../config.cfm">
<cfset variables.fromFusebox = True>
<cfinclude template="fbx_fusebox30_CF50.cfm">
<cfif Len(fusebox.fuseaction) EQ 0>
<!--- Error Handle --->
</cfif>
<cfcatch type="Any">
<!---<cfset SendErrorEmail("Error", cfcatch)><cfabort />--->
</cfcatch>
</cftry>
</cfprocessingdirective>
or better still, in your switch file have a default case such as:
<cfdefaultcase>
<cfinclude template="act_HandleError.cfm">
<cflocation url="hompage.cfm" addtoken="false">
</cfdefaultcase>
Hope this helps!

why can I not catch an error message in a Coldfusion cftry/cfcatch statement?

I have a form where I can upload logos a plenty. I'm validating files (empty form fields, wrong extension, ...) inside a cftry/cfcatch statement.
When I find an error in the cftry, I do this:
<cfthrow type="FileNotFound" message="#tx_settings_app_error_create_first#" />
and inside my 'cfcatch'
<cfcatch>
<cfoutput><script type="text/javascript">window.onload = function(){alert("#cfcatch.message#");window.location.href="hs_apps.cfm"; } </script></cfoutput>
</cfcatch>
This works fine, catches all errors and alerts the user what is wrong.
Now I wanted to use the same handler on a database call where I'm checking for duplicate username. Still the same:
<cfquery datasource="#Session.datasource#" name="duplicates">
SELECT a.app_alias
FROM apps AS a
WHERE a.iln = <cfqueryparam value = "#Session.loginID#" cfsqltype="cf_sql_varchar" maxlength="13">
AND a.app_alias = <cfqueryparam value = "#form.app_basic_alias#" cfsqltype="cf_sql_varchar" maxlength="50">
</cfquery>
<cfif duplicates.recordcount GT 0>
<cfthrow type="FileNotFound" message="#tx_settings_apps_error_dup#" />
</cfif>
The cfcatch is also the same.
However. This now procudes a server error page and I'm thrown out of the application.
Question:
Any idea, why I'm struggling to get cftry/cfcatch to work here? I'm clueless.
Thanks!
EDIT:
Here is the full code
<cfif isDefined("send_basic")>
<cfset variables.timestamp = now()>
<cfset variables.orderview = "1">
<cfif form.send_basic_type EQ "new">
<cftry>
<cfif module_check.recordcount GT 0>
<cfloop query="module_check">
<cfif module_check.module_name EQ "preorder">
<cfset variables.module_name = module_check.module_name>
<cfset variables.b2b_preord_ok = "true">
</cfif>
</cfloop>
<cfif form.app_basic_orderview EQ "preo">
<cfset variables.orderview = "0">
</cfif>
</cfif>
<!--- PROBLEM HERE: DUPLICATES --->
<cfquery datasource="#Session.datasource#" name="duplicates">
SELECT a.app_alias
FROM apps AS a
WHERE a.iln = <cfqueryparam value = "#Session.loginID#" cfsqltype="cf_sql_varchar" maxlength="13">
AND a.app_alias = <cfqueryparam value = "#form.app_basic_alias#" cfsqltype="cf_sql_varchar" maxlength="50">
</cfquery>
<cfif duplicates.recordcount GT 0>
<cfthrow type="FileNotFound" message="#tx_settings_apps_error_dup#" />
</cfif>
<!--- IF PASS, CREATE/UPDATE --->
<cfquery datasource="#Session.datasource#">
INSERT INTO apps ( ... )
VALUES( ... )
</cfquery>
<cfset variables.app_action = "Applikation erstellt">
<!--- success --->
<cfoutput><script type="text/javascript">window.onload = function(){alert("#tx_settings_app_cfm_create#");}</script></cfoutput>
<cfcatch>
<cfoutput><script type="text/javascript">window.onload = function(){alert("#tx_settings_app_err_create#");}</script></cfoutput>
</cfcatch>
</cftry>
<cfelse>
<cftry>
<!--- UPDATE --->
<cfquery datasource="#Session.datasource#">
UPDATE apps
SET ... = ...
</cfquery>
<cfset variables.app_action = "Applikation aktualisiert">
<!--- success --->
<cfoutput><script type="text/javascript">window.onload = function(){alert("#tx_settings_app_cfm_update#");}</script></cfoutput>
<cfcatch>
<cfoutput><script type="text/javascript">window.onload = function(){alert("#tx_settings_app_err_update#");}</script></cfoutput>
</cfcatch>
</cftry>
</cfif>
</cfif>
The error message I'm getting it the message I specify =
<cfthrow type="FileNotFound" message="#tx_settings_apps_error_dup#" />
Which if caught should alert the text behind tx_settings_apps_error_dup. If I dump the cfcatch, cfcatch.message is my specified text, so the error gets caught allright, only I get a server error page vs. an alert. I'm using exactly the same handler for fileuploads and form submits. I don't get why it's not working here?
Thanks for helping out!
WORKAROUD:
Note nice, but suffice(s):
<cfif dups.recordcount NEQ 0>
<cfoutput><script type="text/javascript">window.onload = function(){alert("#tx_settings_apps_error_dup#"); location.href = "hs_apps_detail.cfm?create=newApp&id=none";}</script
</cfoutput>
<cfabort>
</cfif>
So when a duplicate is found I alert the user, reload the exact same page and cfabort to prevent the old page from processing further. Patch that is.
(moved this down from being just a comment)
OK, so the catch is definitely catching the exception if you're able to dump it, so it's not that the try/catch ain't working, it's something else. Bear in mind that processing will continue until the end of the request after your catch block, and only then will the output buffer be flushed, and your alert() sent to the browser. It sounds to me like after your output the alert, and processing continues, some OTHER error is occurring which is causing the server's error page to display. I recommend getting rid of the error page temporarily and eyeballing the actual error CF is raising.
NB: if you want processing to stop immediately in the catch block after you output the alert(), you're going to need to tell CF that, ie: with a <cfabort>. Otherwise, as per above, it'll just keep going.
I think exceptions that are caught by the server error page are still logged in the exception log, but I could be wrong. You could always put an onError() handler in your Application.cfc, log whatever error occurred, then rethrow the error so the error page still deals with it. That way you get the info on the error, and the punter still sees the nice error page.

CFCATCH throwing error in CFC

For some reason, a piece of code that works fine on a *.cfm page, and did work fine in a *.cfc, now is throwing an error when error is detected.
The error is:
Element SQL is undefined in CFCATCH.
The code block where this is getting throw looks like this:
<cfcatch type="database">
<cfset errorMessage = "
<p>#cfcatch.message#</p>
<p>Please send the following to a developer:</p>
<p>#cfcatch.SQL#</p> <--- ERROR HERE
<p>#cfcatch.queryError#</p>
<p>#cfcatch.Where#</p>">
some other stuff
</cfcatch>
Any thoughts?
UPDATE
Using #BenKoshy suggestion, I modified my <cfcatch> statement.
Remember K.I.S.S.? Keep It Simple Stupid
Using his method and then modifying it, I was getting more data back than I was going use, so I went with a simple version, and it works as advertised.
<cfif isDefined("cfcatch.message")>
<cfset errorMessage = errorMessage & "<p>#cfcatch.message#</p>">
</cfif>
<cfif isDefined("cfcatch.SQL")>
<cfset errorMessage = errorMessage & "<p>Please send the following to a developer:</p><p>#cfcatch.SQL#</p>">
</cfif>
<cfif isDefined("cfcatch.QueryError")>
<cfset errorMessage = errorMessage & "<p>#cfcatch.queryError#</p>">
</cfif>
<cfif isDefined("cfcatch.Where")>
<cfset errorMessage = errorMessage & "<p>#cfcatch.Where#</p>">
</cfif>
Nice and easy and it works. KISS
Just means the error data did not contain an SQL statement. Shouldn't assume that variable will exist for all errors:
<cfif isDefined("cfcatch.sql")>
<p>#cfcatch.SQL#</p>
</cfif>
Is the easy fix. Probably best to loop through the struct like this:
<cfparam name="errorMessage" default="">
<cfloop collection="#cfcatch#" item="this">
<cfset errorMessage = errorMessage & "<p>#cfcatch[this]#</p>">
</cfloop>