Mail Importers are a way to monitor specific email accounts for arriving messages, and parse those messages based on their content.
Examples of Mail Importers
Mail Importers can be used for the following tasks:
- When you wish to respond via email to private messages, and have those private messages routed to other concrete5 site members.
- A blog addon that wishes to enable posting via email.
- A discussion addon that wants to enable posting of new messages via email.
How do Mail Importers Work?
When run, any enabled mail helper will connect to a particular email account over POP. Any unprocessed email messages will be parsed, and passed through a processing function defined by the importer. The message is deleted after it is processed. The "Process Email Posts" Job can be run or scheduled which, when run, loops through all enabled mail importers and runs them.
Setting Up Mail Importers
Mail Helpers are available from the mail tab in the settings section of the dashboard. Each mail helper may be enabled or disabled, and can contain its own information about the email address to poll, and how to connect to it.
Creating a Mail Helper
Creating your own mail importer is as simple as creating a new class in the Job format, and adding it to the libraries/mail/importers/ directory in your local web root. This importer will then appear in the Mail Importers section on the Email settings page in your site's dashboard settings section.
Step 1. Create the File
In your local libraries/ folder, create the mail/importers/ directory if it does not exist. Then, create a file in the typical concrete5 handle format. (all lowercase, with underscores separating spaces. e.g. 'send_private_message.php' or 'post_through_email.php')
Create a class in this file
Within this file, take the name of your file (minus .php) and camelcase it, then add "MailImporter" after this class, and use that as your job's class name, while extending the MailImporter class.
class PostThroughEmailMailImporter extends MailImporter
Define the process($mail) function
Create a function named process($mail) within your class. Then, within this function perform whatever action you wish, with the passed $mail object. The $mail object passed to the process() function is an instance of the MailImportedMessage object.
MailImportedMessage Object Methods
$mail->getOriginalMailObject()
Returns the original Zend_Mail_Storage_Pop3 object associated with this import action.
$mail->getOriginalMessageObject()
Returns the original Zend_Mail_Message object associated with this import action.
$mail->getOriginalMessageCount()
Returns the number of mail messages imported during this current run.
$mail->getSubject()
Returns the subject of the imported message.
$mail->getProcessedBody()
Returns the relevant content of the email message, minus any quotations, and the line that includes the validation hash.
$mail->getValidationHash()
Returns the validation hash that concrete5 includes in the mail message to validate the message with the original action.
$mail->validate()
Validates the email message - checks the validation hash found in the body with one in the database. Checks the from address as well.
$mail->getDataObject()
Returns an unserialized object that can be bound to the particular request.
A Mail Importer Example
concrete5 includes a mail importer that lets users respond to private messages through email, and those responses are automatically routed back to their original site as responses to the private messages. Here is how this is done:
1. The mail importer is installed during concrete5's installation as "private_message". 2. When a private message is sent to a user, and the user has opted to receive those messages via email, the following code is run:
$mh = Loader::helper('mail');
$mh->addParameter('msgSubject', $subject);
$mh->addParameter('msgBody', $text);
$mh->addParameter('msgAuthor', $this->getUserName());
$mh->addParameter('msgDateCreated', $msgDateCreated);
$mh->addParameter('profileURL', BASE_URL . View::url('/profile', 'view', $this->getUserID()));
$mh->addParameter('profilePreferencesURL', BASE_URL . View::url('/profile/edit'));
$mh->to($recipient->getUserEmail());
Loader::library('mail/importer');
$mi = MailImporter::getByHandle("private_message");
if (is_object($mi) && $mi->isMailImporterEnabled()) {
$mh->load('private_message_response_enabled');
// we store information ABOUT the message here. The mail handler has to know how to handle this.
$data = new stdClass;
$data->msgID = $msgID;
$data->toUID = $recipient->getUserID();
$data->fromUID = $this->getUserID();
$mh->enableMailResponseProcessing($mi, $data);
} else {
$mh->load('private_message');
}
The first half of this code block simply sets up a new mail helper. Information about this process can be found in the "mail helpers" section mail helpers. Later, however, we check to see whether the user has enabled the "private_message" mail helper. If so, we load an alternate mail template, and run MailHelper::enableMailResponseProcessing() with the relevant MailImporter object, and a simple data object we setup about the particular option. Then, when this information is sent, it contains some extra fields, and sets its reply-to address to be the same as the mail importer's. 3. When this message is replied to, the following code is executed by the private_message mail helper (which is found in concrete/libraries/mail/importers/private_message.php):
public function process($mail) {
// now that we're here, we know that we're validated and that this is an email coming from someone proper.
// We need to know what to do with it, now. We check the "data" column, which stores a serialized PHP object that contains relevant information about what this item needs to respond to, post to, etc...
$do = $mail->getDataObject();
Loader::model('user_private_message');
if ($do->msgID > 0) {
$upm = UserPrivateMessage::getByID($do->msgID);
if (is_object($upm)) {
$originalTo = UserInfo::getByID($do->toUID);
$originalFrom = UserInfo::getByID($do->fromUID);
$originalTo->sendPrivateMessage($originalFrom, $mail->getSubject(), $mail->getProcessedBody(), $upm);
}
}
}
This function simply retrieves the data object stored against the sent message, and sends email to the user we originally stored as the sender.
Installing a Mail Importer with a Package
To install a Mail Importer with a package, simply include the importer file in a libraries/mail/importers/ directory within the package, and execute the following code from within your package's install() command:
Loader::library('mail/importer');
MailImporter::add(array('miHandle' => 'your_handle'), $pkg);
Any importers installed in this way will automatically be removed if your package is uninstalled.