Wednesday, September 15, 2010

javax.jdo.JDOException: Class Date for query has not been resolved.

You have to declare missing imports using query.declareImports(). Example:

Query query = pm.newQuery(
    "SELECT FROM " + Device.class.getCanonicalName() + " WHERE" +
    " lastSeen < dataExpireDate"
);
                 
query.declareImports("import java.util.Date");
query.declareParameters("Date dataExpireDate");

'or' filters can only check equality Exception

As described in "Query Filters" section here:

... keep in mind that || can only be employed when the filters it separates all have the same field name. In other words, || is only legal in situations where the filters it separates can be combined into a single contains() filter.

Saturday, February 6, 2010

Email parsing and automated responding with PHP

In this short post I'll show how to create a simple email responder in PHP. No big deal, we are just going to reply on each received message with a new message that contains custom body and the very same subject.

If you are interested in more complex example feel free to check it out here. It is an email auto responder that for given location (address or coordinates) in Croatia replies with the list of neighboring points of interests. It also features abuse blocking implemented via PHP Authorization web service.

But now let's get back to our simple example!

In first two steps we are going to create a new email account and set a forwarder. Let's say that your hosting environment is equipped with cPanel. The instructions are not much different for any other site management application.

So, in 'Mail' section we click on 'Email Accounts':


and fill out the 'Add a New Email Account' form. For example:


We click on 'Create' and new email account is there. Now let's set up forwarding for that account. Again in 'Mail' section we click on 'Forwarders':

 

Here we configure forwarder for newly created e-mail address. As 'Destination' we select 'Pipe to a Program' and in text box we enter a relative path (from home directory) to our PHP script:


After we click on 'Add Forwarder' we are done with cPanel. Before we go on with PHP, you can try out what has been done so far and send a first email to forwarded address. In case you do so, you can expect a bounce back mail with the similar content:


We have received an error since the message was forwarder to non-existing script. Nice, let's proceed with PHP.

First important thing is that before our <?php tag, we have to start with hashbang. In my case, the hashbang is the following:

#!/usr/local/bin/php

This basically says that our script should be interpreted by PHP which can be found on that and that path. Tha path to PHP executable might be different on your system, you can find it out by executing which php in your console.

Second important thing is that actual email is piped to our script via standard input aka stdin. We can think of stdin as of a file that can be reached by opening php://stdin

With the following statement:

$lines = file("php://stdin");

we will read complete email into array of strings, each string being a line. As it has been said earlier, our auto-responder will reply back to sender with email that contains the same subject and a custom message body. For that purpose we'll extract 'From:' and 'Subject:' fields using regular expressions. So the complete code snippet would be:

#!/usr/local/bin/php
<?php

$from    = "";
$subject = "";
$message = "Thanks for email!";

$lines = file("php://stdin");
foreach ($lines as $line) {
 if (preg_match("/^From: (.*)/", $line, $matches)) {
  $from = $matches[1];
 } else if (preg_match("/^Subject: (.*)/", $line, $matches)) {
  $subject = $matches[1];
 }
}

mail($from, $subject, $message);

?>

We are not done yet. As our script should be executable file and not a webpage, we have to set the right permissions and chmod it to 0755. Another important note is that PHP script should not produce any output, so be sure that you don't have any trailing whitespace after ?> tag.

Depending on your requirements and frequency of incoming emails, as mail function is time consuming, you might want to send out emails in batch mode when server is not under heavy load. In that case you should check out PHP Batch Mail.

And that would be it!