Changing Contact Form 7 with the wpcf7_before_send_mail Hook

Some notes about using (and perhaps abusing) the Contact Form 7 process in a WordPress site. (Contact Form 7 is a popular plugin for WordPress sites that lets you easily create a Contact Us type form. We use it here, although we’ve also tweaked what it does with our FormSpammerTrap for Contact Form 7 plugin that effectively reduces Contact Form spam. You can check out that plugin – and our other FormSpammerTrap spam-bot blocking techniques at our FormSpammerTrap.com site.)

We were inspired by an article we found via the googles while searching for information on CF7 hooks, because we wanted to do things to the CF7 form content after it was submitted, but before the form was emailed. The article is here. The code is theirs, but we wanted to explain it in more detail (mostly for our own purposes, as we wanted to use a similar process for our own purposes).

Let’s take a look at what we can do after the Contact form is submitted, and before CF7 emails the message. Our intent is to change the Subject line of the form to something other than what the visitor entered. You could easily use this code for your own purposes.

First, lets ‘hook’ into the wpcf7_before_send_mail process. This is done with the standard WP add_action function. (Remember that you can ‘hook’ into any WP function that has a ‘hook’. Ask the googles how the add_action thing works.) Here is the code that you would place in your Child Theme’s function.php file (or perhaps in a plugin):

The add_action code
 
add_action( 'wpcf7_before_send_mail', 'my_change_subject_mail' );

This will wait for the hook to be called, and run the my_change_subject_mail() function.

Now we need to create the my_change_subject_mail function. I’m going to show and explain each line separately. We’ll put the entire function at the end.

This defines the function:

Defining the function
 
<?php 
function my_change_subject_mail($WPCF7_ContactForm)
{

This will get the current WPCF7_ContactForm object. We need this object to change the subject value therein.

Get the current WPCF7_ContactForm object
 
$wpcf7 = WPCF7_ContactForm :: get_current() ;

Here we get the Submission object, which is generated when the user hits the ‘send’ submit button.

Cet the WPCF7 Submission Object Instance
 
$submission = WPCF7_Submission :: get_instance() ;

Next, let’s ensure that the contact form has been submitted.

Check if there is a submission of the contact form
 
if ($submission)
{

If the form is empty, exit the function.

Exit the function if it the contact form is empty
 
if ( empty ($posted_data))
return ;

This is how we read a value of the form. The basic CF7 Contact Form has variables, this next line references the variable that was defined as ‘your-message’. If you want to work with another field on the form, use that field name as the parameter of the $posted_data array.

 

Read the your-subject field contents into the $subject variable
 
$subject = $posted_data['your-message'];

At this point, you could do a search/replace on the subject, or anything else. For instance, maybe you’d like to store the message fields in a database. You would set various variables – like we did with the $subject variable – to values from the $posted_data array. Then you could store those variables into a table in your database.

We’re not going to do anything with the $subject variable, we just wanted to show you that it could be done.

Our intent is to change the ‘subject’ of the email to something else. First, we have to read the property of the $mail object. This is the object that CF7 uses to create the email.

Get the contact form's values into the $mail array
 
// do some replacements in the cf7 email body
$mail = $WPCF7_ContactForm->prop('mail') ;

Since the subject line in our CF7 form is called ‘subject’, here is how we change the contents of that field:

 

Change the Subject field's value
 
$mail['subject'] = "this is an alternate subject" ;

Now that we have changed a value in the $mail array, we need to set that value in the WPCF7_ContactForm object:

Store our new subject back into the CF7 ContactForm object
 
// Save the email body
$WPCF7_ContactForm->set_properties( array("mail" => $mail)) ;

If we are curious about all of the contents of the WPCF7_ContactForm object, we could quickly write it to the error.log file. This is OK for our purposes, as we are on a development site, and the error.log is a quick way to look at something. Note that you can’t ‘echo’ or ‘print’ anything to the screen in this process; it won’t be shown.

Look at all the contents of the object
 
// error_log( print_r( $WPCF7_ContactForm, 1 ) );

All done. We’ll return the object just in case it is needed.

Exit out of the function
 
return $WPCF7_ContactForm ;
}
}

By looking at the contents of the object, you might find other things that you might like to change. The $mail part of the object is stuff that will be emailed.

The result of all of this is that we have changed the subject line of the emailed message with out little function. We could add additional parts (maybe some extra data like the IP address of the sender, or whatever) to the $mail array -maybe the message content –  and that would also be sent.

All done!  Any questions, use the comments. We’ll try our best to muddle through an answer to your question.

Here’s the entire function:

The Entire Code
 
add_action( 'wpcf7_before_send_mail', 'my_change_subject_mail' );
function my_change_subject_mail($WPCF7_ContactForm)
{
$wpcf7 = WPCF7_ContactForm :: get_current() ;
$submission = WPCF7_Submission :: get_instance() ;
if ($submission)
{
$posted_data = $submission->get_posted_data() ;
// nothing's here... do nothing...
if ( empty ($posted_data))
return ;
$subject = $posted_data['your-message'];
//$subject = substr($this->replace_tags( $template['subject'] ), 0, 50);
// do some replacements in the cf7 email body
$mail = $WPCF7_ContactForm->prop('mail') ;
$mail['subject'] = "this is an alternate subject" ;
// Save the email body
$WPCF7_ContactForm->set_properties( array("mail" => $mail)) ;
// error_log( print_r( $WPCF7_ContactForm, 1 ) );
// return current cf7 instance
return $WPCF7_ContactForm ;
}
}

Using INI files on PHP sites

I’ve built some personal web sites using PHP. I’ve been working on one site that I hope to bring public soon. The site will contain some personal information that must be encrypted. So I have been using code that is (hopefully) secure from potential exposure. There is data stored in a database, and some of that data will need to stay confidential to any outside hacks. The intent is to write code stores data securely, even if the source code files are compromised. Of course, it is difficult to do that level of security, but there are techniques that help with that.

One of the techniques, which I am documenting here (mostly for my own benefit), is to have some variable data used by the code pages stored in an area away from normal web access. Think of the credentials used for database access, for instance. That is data that needs to be used by the code, but should not appear in the the code files that use the data. So we need a way to store the variables data in an outside file for use by any code page that needs it.

There are several steps involved in this. First, we need to have a plain text file that contains the variables values. The data is stored in an array;in this example, the array is called ‘config’. Here is the file (parameters.txt) that defines the array that contains the variables

[config]

xProgram = “My Program Name”

xHeading1 = “The Heading 1 Text”

xHeading2 = “The Heading 2 Text”

xText = “This is the true text that belongs to the program”

Note that we have used double-quotes to surround text with space characters. That’s to ensure that there won’t be a problem (and an error) if the text string contains a reserved word (as in the xText value).

The process of reading the configuration file into a variable (let’s call it $xvariable), which will contain the arrays as defined in the configuration file. So the $xvariable array will contain those four values. We can reference each value with code similar to $xvariable[‘config’][‘xProgram’], which will contain the value of ‘My Program Name’, when you read the file contents into an array called $xvariable. You can put multiple array names within the brackets, if you need additional data arrays. And you might want to consider non-specific names for the variables, like using numbers instead of a descriptive name like we show above.

Now that we have created the parameters.txt file, we secure place to put it. Normally, you would want to place this file outside of the site root, but you may not have access outside of the site root on some shared hosting systems. So we will place it in a subfolder of the site root called ‘xini’. That makes the configuration file will be accessed as ‘./xini/parameters.txt’.

With the file in the ‘xini’ folder, we need to protect that folder (and any files within that folder) from prying eyes. This is done by putting the following commands in an ‘.htaccess’ file. These commands will prevent access to any file with a ‘txt’ extension.

<FilesMatch “\.txt$”>
Order allow, deny
Deny from all
< /FilesMatch>

There’s lots of other places that discuss .htaccess file, so go there if you need more info.

At this point, we have the configuration file built, stored in the ‘xini’ folder, and protected by the .htaccess file.

Next, we need a function to read the parameters.txt configuration file and make the ‘config’ array available to the other code pages. Here, we will use a function that we store in our functions ‘include’ file.

function show_ini() {
global $config;
// check for ini file there
if (file_exists(‘./xini/parameters.txt’)==0)  {
die (“Did not find the file.”);
}

// file found, read it into the $config array
$config = parse_ini_file(‘./xini/parameters.txt’);

return;
}

We just call the show_ini file at the top of the functions.php file (the code file that contains all of the functions used by the program). Since all pages ‘include_once’ the functions.php file, the config array will be available to all code pages.

Note that we use the ‘global’ command at the beginning of the function so that the config array will be available outside of the scope of the function. Another note: you will have to ensure that the page that calls the function can get to the file using the path you specify in the file_exists and parse_ini_file, so adjust that as needed. And some additional error trapping, or a more friendly ‘die’ process would be useful to add.

But the process allows you to store confidential information outside of the code pages. Of course, access to all of the site’s source code files will be a concern, but (hopefully) there are other protections against that exposure.

[added 3 Oct 2014]

Found that the ini file can contain ‘//’ or ‘/*’ and ‘*/’ pairs. But you can’t put any parenthesis or square bracket characters in the ini file. If you do, the parameters in the ini file won’t be read.

Another Form Spammer Blocking Success Story

I’ve written before about blocking form spam here and also here . You can look at all the details there.

And I have another form spammer blocking success story — on one of my other sites, the DigitalChoke blog.

I wrote about it there; take a peek if you are interested in how to block form spam on your blog or web site.

It really works. And it is really easy to implement. And it is really free.

Check it out. You can get form spam blocked on your site.

Ultimate Form Spammer Blocking

A while back, I wrote about a technique to block form spammers. I have implemented it on several sites that I have built. In some cases, the site originally didn’t have any protection against form spammers, or used easily-bypassed techniques like hidden fields, silly questions, changing contact page names, or even captchas. Even with those techniques, form spam still arrived.

In most cases, the volume wasn’t enough for me to worry about. Sometimes, a form spammer would find one of my site forms, and start spamming it daily. At that point (when it started getting irritating), I would implement my ‘ultimate form spammer blocking’t technique.  And the form spam immediately stopped; the form spammer never was seen again on that site.

So I have put together a package of files that you can use in your site forms to get rid of your form spam. It’s all open source, and quite clever (he said with some modesty). With just a few modifications of your form, and adding one or two files to your system, you can get rid of your form spammer problem.

The package of files is written in PHP, and requires that your visitor has JavaScript running (not Java). But once you set things up, you will not be bothered by form spam again. Your form spammers will get redirected to my Form Spammer Trap site instead of sending your form spam.

The package includes support for WordPress sites, with the use of a template that you specify for your contact page. No special add-ins needed, although you may need to do some minor CSS formatting changes. Full instructions on how to implement in your site, whether PHP-based or a WordPress site, are included in the package.

So, how do you get it? Well, you use our contact form. Just fill in the form with your name, email address, and comment text of “I want your form spammer blocking package” (along with any other comments), and I’ll get the zip file out to you. Don’t use the comment form on this post, unless you really want to expose your email address.

Our Contact form uses our Ultimate Form Spammer Blocking technique. If you want to see what will happen to a form spammer, just click on the “Submit” button on the contact page (don’t click anywhere else).  We use the WordPress template version of the package, so you can see how it looks with our site theme.

And it is all free, although donations are accepted. If you don’t think you can install it yourself, contact me and we’ll arrange for some help at a nominal fee. Or if you don’t want to use our package, the technique is shown on our previous post about preventing form spam, so you can roll it yourself.

But our ‘Ultimate Form Spammer Blocking’ package will get rid of any form spam on your web site. It really works!

(Added: If you want more details, go to my Form Spammer Trap web site that uses the technique. That site is where form spammers will end up.)

Mail Retention Problems

I manage some other web sites, besides the ones that I create for my own amusement. One of them is for Dr. Jerry Pournelle, a science fiction author and really smart guy. The site, which always have some good commentary on lots of different subjects, is called “Chaos Manor”; the blog site is here at  www.jerrypournelle.com/chaosmanor . Dr Pournelle had a monthly column with Byte Magazine, one of the premier computer magazines. Like a lot of computer magazines that exploded in size and readership in the early days of personal computing (1970’s-1980’s, for those that are interested in ancient history), the magazine is a shadow of it’s former self. Dr. Pournelle was probably one of the first ‘bloggers’ before that term was even invented. In any case, it’s a very interesting site.

He gets a lot of email, which he uses as fodder for his blog. He downloads all of that email to his local computer network’s Outlook installation. The mail is received by the hosting company, then he downloads it to his local Outlook system, with the setting to delete the mails from the hosting system. There are several email addresses that he has used over the years, but all the emails are forwarded on the host system to his primary email address on the hosting system.

And therein lies the problem. When you set up forwarding on just about all hosting systems, the message is retained in the original account. And since messages are only downloaded from the main account, the other email addresses have messages that never get deleted. If you get a lot of email, the number of messages just increases. And when you get a lot of email, the number of message files can add up. In Dr. Pournelle’s case, the file count got over 700K. The hosting company wasn’t happy about that number.

So options are to increase the allowed file count by paying more for hosting, or get rid of all of the old message files manually. All 700,000 of them. That would take quite a while, as in fact it did. I was able to delete about 500,000 of them, but it took many hours (days, actually). And that is only a temporary solution. The file count will only increase, and I will have to do the whole process again at some point.

So I was looking at options. The first would be a setting on the forwarded accounts that would forward and delete. But that option is not available. Well, there is probably some script that could be run to do that, but the ‘googles’ are inconclusive on a known good solution for that.

Another option would be to use a forwarding process only, without an actual email account for the forwarded email. But that doesn’t work properly; mail can get lost. So that’s not a good solution.

So, it looks like a script is what I need to create. I’ve got a good start on it, with the PHP program I wrote that checks sites for changed files (here http://securitydawg.com/?p=109 ). I just need to adjust it a bit to select and delete messages that are xx days old (so as not to delete any mail messages that haven’t been downloaded yet).

But it would be nice if the hosting company had a forwarding process that would ‘forward and delete’.

 

Checking Your Web Site for Changed Files

I manage several web sites. Most of them are for my amusement. A monthly count of visits to some of these sites can probably be counted on one finger of one hand.

I also manage a few WordPress-based sites. Some of them have a reasonable amount of traffic. As with any type of site, there is a possibility of an attack that might insert some malware code into a page.

An example of this is the recent attack against WordPress sites, by trying to log in as the ‘admin’ user using a dictionary attack of passwords. There were many WordPress sites that were successfully compromised due to poor security or password practices. (See this entry.)

Now the WordPress sites that I manage weren’t compromised with this attack. I always create a new admin-level user, select a strong password. I then log in as that new admin-level user, then demote the existing ‘admin’ user to the lowest authority level, ensuring it has a strong (and different) password. That way, that ‘admin’ user is still there, but a successful login of ‘admin’ would not give the attacker any privileges.

Other sites that I have created and manager are written in PHP, and there is the possibility of attacks there,although I do try to write code that prevents exploitation.

But I needed a way to check a bunch of sites, and alert me if files have been changed. There are paid programs to do that, but a well-written custom program would work too. Here are the requirements for such a program.

  • The program should look at all files on the site, and compute a ‘hash’ of some sort.
  • The program should store those file names and hash values in a database table.
  • Each time the program runs, it should compare the current file/hash values with the values stored in the database. If the values do not match, then the file has changed.
  • If there are new files on the site, the program should add those to the database
  • The results of new and changed files should be emailed to me
  • The process should be automatically scheduled to run on a regular basis.

That sounds reasonable enough. Since I am the owner of the site, I should be able to look at the email and determine if there were any files changed or added that I don’t know about. Then I can investigate further to see why the file had changed. it would be a good program to have on a web site to be alerted about changes.

Now, there are probably programs out there that do that – paid or open-source. But it would be a good exercise for me to write one of my own. Of course, there might be some code fragments out there in the ‘googles’ that might be useful and save some programming time. But the result would be something that would be very useful to me.

So that’s what I did. The result is a program I call “HashFiles”. It is a fairly simple process, and will work with small and large sites. And it does each of the items in my requirements list. I am rather pleased with myself for figuring it out.

So I decided that the program might be useful for others. If you are interested (and this is assuming that anyone is really reading this blog besides me – perhaps a generous assumption), please indicate your interest in a comment.

Saving Your Data

An important part of information security is making your data available, and keeping that data available. Loss of data can be a minor inconvenience, or it can kill your business. And it is not just businesses that need to worry about data loss.

Think of your personal data. All of those pictures on your camera, your phone, your laptop, or your computer. Or even the non-electronic data like printed pictures, slides, important papers, journals — the list is almost endless. Protecting that data from different kinds of loss is important to a business, and to individuals.

And there are lots of ways to back up that data, no matter what it is. On a personal level, you can copy files to CD/DVDs, or to an external hard drive (USB thumb drive, external hard disk). Those are valid solutions. But only if you remember to do them. And then there is the storage issue. Where do you keep these backup copies? Keeping them in the same physical location protects the data — until there is a flood, or a fire, or tornado, or a theft, or … well, the possibilities for data loss have not been fully mitigated.

One of the solutions I have used for a couple of years is an on-line backup service. The service I use is from Carbonite (www.carbonite.com), and costs $59/year for unlimited, automatic on-line backup. Tree important words in that statement. Unlimited backup takes care of all of my files at the same basic cost. Automatic means that I don’t have to worry about doing it. And the third important part is “on-line” — the data is stored off-site in ‘the cloud’.

With Carbonite, everything is automatic. I install the software on one computer at home (they have a multiple-computer plan also). I designate the folders to back up. The Carbonite software automatically copies my files to their servers, over my Interwebs connection, and does it with a minimal impact on my other on-line activities. If I make a change to a file, that changed file is added to the backup list.

And it is all done automatically. It meets the requirements for keeping my backups current; the files are available if I need them; and I don’t have to remember to do anything.

But what about the multiple computers around your house? You may have a couple of laptops or  desktops at your house. How do you keep all of your computers backed up?

With Carbonite,  you have to pay for one yearly subscription ($59) for every computer you back up. If you have multiple computers at home, that can start getting expensive. A bit of adjustment on your end will fix that.

In my case, the desktop computer downstairs is Carbonited. That computer, plus our two laptops, are all networked together. So a process of copying data from laptops to desktop gets our laptop files as part of the Carbonite backup. That’s done with the free Microsoft SyncToy, which syncs the files from laptop to desktop.  It’s pretty fast (much faster than a straight copy command), since it only works on files that have changed.

So my important personal data is backed up with Carbonite. There are other services that perform similar functions; some have better pricing for multiple computers. But my data is safe from a local (home) disaster, and it is mostly hands-free.