
Rules is an especially useful Drupal module for all kinds of tasks. One use you might want to put it to is providing admin notifications of certain events on your site, e.g. user registrations (covered in the previous post) and the creation of new comments and content by “untrusted” users (assuming your use case allows them to create any content at all). For some use cases, you may wish to put strict limits on the creation of user accounts and content, but for the purposes of this article we are assuming you are administering a Drupal site where you want to encourage growth and community involvement, so you might allow anonymous users to comment on posts (albeit likely with the rel="nofollow"* attribute added to their links). And you might also allow users to create and confirm their own accounts and then create some types of content (e.g. forum posts, bug reports, etc). The downside is that you’ll need to be vigilant about squashing all the spam this policy invites (or the flow of new spam will quickly increase and be damaging to your SEO efforts), but on a site with only moderate traffic you should be able to manage this without a lot of trouble. This post covers using Rules to provide notifications of new comments and content. If you keep a close eye on user registrations and immediately block the user accounts which follow a pattern like other spam accounts you’ve removed (i.e. accounts likely created with the help of a “spambot”), you can eliminate almost all of the spam that requires use of an authenticated user account.
*Adding rel="nofollow" to links posted in “Filtered HTML”, presumably the only text format you allow for “untrusted” users, is simple, but well worth doing if you allow “anonymous” or newly-registered “authenticated” users to make any kinds of posts on your site. In Drupal 6, go to admin/settings/filters/1/configure and select the “Spam link deterrent” checkbox. In Drupal 7, go to admin/config/content/formats/filtered_html and find the vertical tab near the bottom labeled “Limit allowed HTML tags”, where the same feature is enabled with a checkbox labeled “Add rel="nofollow" to all links”.
Getting back on topic, the three events we want to create Rules for are:
In every case, creating a new rule starts by going to the “add rule” page:
D6: admin/rules/trigger/add
D7: admin/config/workflow/rules/reaction/add
This rule sends an (HTML or plain text) email which includes the comment title and body, along with a link to quickly edit it. Here at Cocomore, rather than delete comment spam, we’ve been unpublishing the comments so we can still observe patterns. So we don’t get an email for each of our own responses to comments, we configure the rule to only notify us when “untrusted” users (i.e. any users who don’t have a “staff” or admin role) post comments.
The first steps, picking a name and adding tags for it, then clicking “add action…”, are virtually identical in both Drupal 6 and Drupal 7 and for each rule. So if you wish to see illustrations of these steps, please look at part 1 of this article. The event we want to react to is called “After saving a new comment” in both the Drupal 6 and Drupal 7 versions of Rules. This is also simple enough that I will leave out any illustration here.
This is almost the same in Drupal 6 and Drupal 7. First select the “user has roles” condition. In the next part of adding the condition, we can select which roles the condition applies to. First we make sure that we select the right user for the “role condition”. In this case, the right user to select as the “argument” (Drupal 6) or “Data selector” (Drupal 7) is the author of the created comment, i.e. in Drupal 6 select “created comment author” and in Drupal 7, select “comment:author”.
Now we only want to send email when an anonymous user or basic authenticated user posts a comment. For the purposes of illustration, I have created a testing environment with two staff roles (one is “administrator” and the other is “editor”). Since both “staff” roles are also “authenticated” (whenever they are logged in, they have the “authenticated user” role, too), we want to use negation in our condition. The roles of the user who posted the comment should NOT include any of the privileged staff roles (or any other “trusted” role you would like to ignore here). So we select the two staff roles, the “Negate” checkbox, and “any” selected role. Then we need to remember to click “Save” for our new condition to be added.
The “Add action” click pre-step is almost identical in Drupal 6 and Drupal 7, as is the selection of which action to perform (sending a mail); if you wish to see the illustration, please see the relevant screenshots in part 1 of this article.
For the purposes of this article, we will assume that we only want to send the administrator an email when people post comments, so it’s most appropriate to select the “Send (HTML) mail to all users of a role” option, then select “administrator” for the role to receive the email. That way, the administrator can choose to forward emails to the content author when she feels that the author should post a response to the comment. Alternatively, you could include your site’s content author(s) in the comment moderation process and allow them to also receive all the messages about comments by adding their email addresses to a comma-separated list of (in Drupal 6, “arbitrary”) email addresses. Or perhaps you have an “author” role and can select that. Or you could use the “token” to specifically send an email to the author of the commented content. If your site has multiple administrators, you might want to test your rule with an “arbitrary” email action, then copy the configuration for the “subject” and message “body” to a new action so that only you get the messages during the “testing phase”.
Tokens available for use differ significantly between Drupal 6 and Drupal 7, but most are available in both or at least there is some way to achieve similar results for most output you might want to have. I’ve created some simple messages which you can use as a starting point (if you import the rules export code I’ve attached.) You might need to tweak the array code to fit your site’s configuration (e.g. role IDs, etc)
Rules allows you to export and import rules from saved code, so I have attached an export of this rule. Even if you don’t want exactly the same action, this could be useful as a starting point for a new rule on your site. There are four versions of the import code attached, two each for Drupal 6 and Drupal 7 (for each version of Drupal, there is one version of the rule which uses HTML mail for the admin notification email, and one which just sends a plain mail.)
For Drupal 6 users, you can experiment with my exported Rules code for HTML email or plain text email. Drupal 7 users can download the HTML and/or plain text versions, as well.
This rule is actually similar enough to the comment-based rule that it’s a good candidate for demonstrating the power of the “clone” operation in Rules for Drupal 7 (unfortunately, Rules in Drupal 6 won’t let us change the event from comment-related to content-related, which is a bit of a drag since much of the rest of the Rule could be a straight copy, but you can create a new Drupal 6 rule that is triggered by the creation of new content, create a similar “condition”, then copy/paste in the email code and edit, as needed). But to experiment with cloning, those of you in Drupal 7 can start by going back to the main Rules overview page (admin/config/workflow/rules in Drupal 7). The clone link is virtually the same in both Drupal 6 and Drupal 7:
Let’s first think about the differences, then clone the content and edit accordingly. The first significant difference is the title and “tags”, which should obviously say “content” rather than “comment”. Edit the cloned rule, and click on “Save changes”. The next difference is only slightly less trivial. We need to delete the “event” for “After saving a new comment” and add a new event in its place: “After saving new content”. You should then see that there is a warning next to the summary of the condition: “comment:author” is a token which no longer makes any sense.
Not to worry, we can fix that. Click on the “edit” link next to the condition and change the “Data selector” field from “comment:author” to “node:author”. We still only want to trigger the rule for users who do not have one of our trusted staff roles, so the rest of the condition can stay the same. Click on “Save” to go back to the main edit page for the rule, where we just need to click the “edit” link next to the “Send HTML mail…” action and change our message to be a bit more appropriate for the creation of new content.
In the email subject, we can change the word, “comment”, to the token, “[node:content-type]”, which will be dynamically re-written to say, for example, “bug report”. We can change all the links and mentions of comment to the appropriate tokens for content. With just a few edits, we can have a new message body that looks something like this:
A new piece of [node:content-type] content has been posted on [site:name]. Please review for spam or post a reply, if appropriate:
<strong>Title:</strong> <a href="[node:url]">[node:title]</a> (<a href="[node:edit-url]">edit</a>)
<strong>Content body:</strong>
[node:body]If you are using Drupal 6, we couldn’t clone the “new comment” rule as a starting point for our “new content” rule, but it should be clear how to create the rule we need. Start by creating a new rule triggered by the event: “After saving new content”.
Here we want to select the “content’s author” option for the “user” in the “Arguments configuration” section. The rest is just like we did before; select trusted roles, negate, and make sure “any” is selected for the “match against…” option:
Now simply create your email message, just as before, but using token replacement patterns that work with content. So you might want to use something like: “New [node:type-name] on [:global:site-name]” for your “Subject” and enter an HTML message like:
<p>Please check the following new [node:type-name] content, created [node:small], for possible spam:<br />
<strong>Content: </strong><a href="[node:node-url]">[node:title]</a> (<a href="[:global:site-url]node/[node:nid]/edit">edit</a>)<br />
<strong>Created by:</strong> <a href="[author:account-url]">[author:user]</a></p>[node:body] token and we have to build our “edit url” from the various components (i.e. the token for the site’s base URL, which outputs, e.g. "http://example.com/" and ends in a slash, plus node/[node:nid]/edit gives us the same output that the [node:edit-url] token provides in Drupal 7.)
The following is a screenshot of the message generated by one of the most recent pieces of spam “content” posted on drupal.cocomore.com when I didn’t spot the new account creation early enough to block the user before they started spamming:
I’ve also attached the exported Rules for all versions (Drupal 6 and Drupal 7 / plain and HTML email notifications), so if this code is of any help to your process, you can work with it:
Drupal 6 new content created by untrusted role—HTML email / Plain-text email
Drupal 7 new content created by untrusted role—HTML email / Plain-text email
As I suggested in the previous post, it’s probably best to start by initially triggering a simple rule with an even simpler email (to test that you get your message) and then build up the complexity a small step at a time, testing as you go. Sometimes the tokens don’t work as expected or a token might not have a value in every situation; and unfortunately in such cases, Rules just doesn’t send a message. If you are working in a development environment, you can turn on full “debugging” for Rules in the settings and allow all roles to see the evaluation of the rules (so you can switch between test users and see what happens when you trigger the actions).
I wish you the best of luck in creating the perfect Rules workflow for your use case.
Comments
thanks a lot for the post! I
thanks a lot for the post! I am new at this, so it is going to be helpful
i wish i came across your blog earlier, bookmarking it now