Here is a simple example of a custom Mailhandler command processor. It searches the Subject field of an email for an identifier, and provides it as a mapping source called Case ID for node mapping. Mailhandler command processors are written as Ctools plugins. At the time of writing, Mailhandler is at 2.0-rc1.

The default command plugin is destructive to the $message object. If your plugin doesn't seem to be getting the data you want from $message, lower your plugin's weight in order to run at the desired time. Plugins are ordered by weight in the UI, so you can visually see at what point your plugin will run.

mycustomcommand.info

name = "Sample Command Plugin"
description = "Parses ticket ID from subject line for Mailhandler."
version = "7.x-1.0"
core = "7.x"
dependencies[] = "ctools"
dependencies[] = "feeds"
dependencies[] = "mailhandler"
package = "sample"

files[] = mycustomcommand.module

mycustomcommand.module

/**
 * Implements hook_ctools_plugin_directory().
 */
function mycustomcommand_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'ctools' && $plugin_type == 'commands_plugin') {
    return 'plugins/' . $plugin_type;
  }
  if ($owner == 'mailhandler') {
    return 'plugins/' . $plugin_type;
  }
}

plugins/commands/mycustomcommand.inc

/**
 * @file
 * MailhandlerCommandsMyCustomCommand class.
 */

$plugin = array(
  'name' => 'Sample processor',
  'description' => 'Extracts Case ID from subject line.',
  'handler' => array(
    'class' => 'MailhandlerCommandsMyCustomCommand',
    'parent' => 'MailhandlerCommands',
  ),
  'file' => 'MailhandlerCommandsMyCustomCommand.class.php',
  'weight' => 30,
);

plugins/commands/MailhandlerCommandsMyCustomCommand.class.php file

/**
 * @file
 * MailhandlerCommandsMyCustomCommand class.
 */

class MailhandlerCommandsMyCustomCommand extends MailhandlerCommands {

  /**
   * Parse the subject for a Case ID.
   */
  function process(&$message, $source) {

    $splitmail = array();
    $splitmail = explode("-----(Please reply above this line)-----",$message['origbody']);

    //strip everything after this text
    $message['origbody'] = $splitmail[0];

    //grab case_id from subject line
    $message['case_id'] = substr($message['subject'], strpos($message['subject'], 'case #') + 6);
  }

  function getMappingSources() {
    $sources = array();

      $sources['case_id'] = array(
        'title' => t('Case ID'),
        'description' => t('The original Case ID'),
      );
    return $sources;
  }
}

Comments

dafeder’s picture

I'm finding this page very confusing. First, the filenames in the .info file don't seem to match up with the filenames given above the code snippet. Second, there's no real explanation here of how to add a basic command. For instance, I'd like to add a command to my emails that's something like this:

group: groupname

Where some simple logic converts the string "groupname" into an nid for what group to post this node to. I don't really see how to do this from the example, which seems to be more about how to do more complicated filtering of message bodies?

narayanis’s picture

I fixed the .info issue. Ctools plugins are dynamically loaded, so they don't need to be in files[] at all.

Command logic lives in your class file (mycustomcommand.class.php in this example). All of the relevant email data lives in $message.

process() is where you do any data manipulation, like finding and parsing your string and turning it into a useful value.

getMappingSources() is where you set your field in the Source mapping page of the Feeds UI.

wuh’s picture

If anyone is trying to create this module for better understanding of how plugins work, note that the folder named commands_plugin should be commands. Hope this helps somebody.

EDIT:

Also, the file mycustomcommand.class.php should in fact be named MailhandlerCommandsMyCustomCommand.class.php for this to work

narayanis’s picture

Please feel free to edit the page and fix my mistakes. This was my first ctools plugin.

wuh’s picture

I've done that now - it was a very helpful article for me by the way - thank you

wilks’s picture

I just created the class.php and inc files under mailhandler/plugins/mailhandler/commands and this seems to be working. Not sure if this will cause any other issues as yet.

I am using a new custom command to look for the address of the original sender of a forwarded email. Here is what I am using:

MailhandlerCommandsMyCustomCommand.inc

<?php
/**
 * @file
 * MailhandlerCommandsMyCustomCommand class.
 */

$plugin = array(
  'name' => 'Forwarded processor',
  'description' => 'Extracts original sender from Forwarded email.',
  'handler' => array(
    'class' => 'MailhandlerCommandsMyCustomCommand',
    'parent' => 'MailhandlerCommands',
  ),
  'file' => 'MailhandlerCommandsMyCustomCommand.class.php',
  'weight' => 30,
);
?>

MailhandlerCommandsMyCustomCommand.class.php

<?php
/**
 * @file
 * MailhandlerCommandsMyCustomCommandclass.
 */

class MailhandlerCommandsMyCustomCommand extends MailhandlerCommands {

  /**
   * Parse the body text for the From: field.
   */
  function process(&$message, $source) {

    $string = $message['body_text'];

    $pattern = '/From:\s+(.*?)\s*(?:\[mailto:|<)(.*?)(?:[\]>])/s';
    preg_match($pattern, $string, $matches);

    //Insert email from pattern matching
    $message['orig_address'] = $matches[2];
  }

  function getMappingSources() {
    $sources = array();

      $sources['orig_address'] = array(
        'title' => t('Original Sender'),
        'description' => t('The original Email Sender'),
      );
    return $sources;
  }
}
?>