195 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/php
 | 
						|
<?php
 | 
						|
 | 
						|
require_once 'vendor/autoload.php';
 | 
						|
 | 
						|
// Load the .env file
 | 
						|
$dotenv = new Dotenv\Dotenv(__DIR__);
 | 
						|
$dotenv->load();
 | 
						|
 | 
						|
// Debug Mode will show more information.
 | 
						|
$debugMode = getenv('DEBUG_MODE');
 | 
						|
 | 
						|
// Dry Run Mode will suppress sending an e-mail to Redmine.  Only really useful with debug mode on.
 | 
						|
$dryRun = getenv('DRY_RUN');
 | 
						|
 | 
						|
// Test addresses work normally, but tag the email subject with "[TEST]".
 | 
						|
$test = getenv('TEST');
 | 
						|
 | 
						|
$deliveryAddress = getenv('DELIVERY_ADDRESS');
 | 
						|
 | 
						|
if($debugMode) {
 | 
						|
  error_reporting(E_ALL);
 | 
						|
}
 | 
						|
 | 
						|
// initialize.
 | 
						|
$deliveredTo = $from = $project = $email = $subject = NULL;
 | 
						|
$params = array(
 | 
						|
  'url' => getenv('REDMINE_URL'),
 | 
						|
  'key' => getenv('KEY'),
 | 
						|
  'unknown-user' => 'create',
 | 
						|
  'allow-override' => 'all',
 | 
						|
  'project' => getenv('CATCHALL_PROJECT_NAME'),
 | 
						|
  'tracker' => 'general',
 | 
						|
);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// read from stdin
 | 
						|
$fd = fopen("php://stdin", "r");
 | 
						|
 | 
						|
// Loop through the incoming message, one line at a time.
 | 
						|
while (!feof($fd)) {
 | 
						|
 | 
						|
  $line = fgets($fd);
 | 
						|
 | 
						|
  //if this line is the "delivered-to", extract the subaddress, if there is one.
 | 
						|
  if(preg_match("/^delivered-to: (.*)/i", $line, $matches)) {
 | 
						|
    $deliveredTo = $matches[1];
 | 
						|
    if(preg_match("/$deliveryAddress.*\+(\S*)@/i", $deliveredTo, $matches)) {
 | 
						|
      $project = $matches[1];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //also extract the "From" address.
 | 
						|
  if(!$from && preg_match("/^from: (.*)/i", $line, $matches)) {
 | 
						|
    $from = $matches[1];
 | 
						|
  }
 | 
						|
 | 
						|
  //Alter the Subject if this is a test.
 | 
						|
  if ($test && preg_match("/^Subject:(.*)/i", $line)) {
 | 
						|
    $line = $subject = str_replace('Subject: ', 'Subject: [TEST] ', $line);
 | 
						|
  }
 | 
						|
 | 
						|
  //build the email variable, which is output to Redmine.
 | 
						|
  $email .= $line;
 | 
						|
}
 | 
						|
fclose($fd);
 | 
						|
 | 
						|
//Handle special cases
 | 
						|
//Strip out "auto-generated" from GCal notifications
 | 
						|
if($from == 'Google Calendar <calendar-notification@google.com>') {
 | 
						|
  $params['unknown-user'] = 'accept';
 | 
						|
  $email = str_replace("Auto-Submitted: auto-generated\n", '', $email);
 | 
						|
}
 | 
						|
 | 
						|
// If we don't know the project yet, attempt to determine it from the complete email address.
 | 
						|
if(!$project) {
 | 
						|
  $project = ParseSenderEmail($from);
 | 
						|
}
 | 
						|
// Still no project?  Check the domain of the sender.
 | 
						|
if(!$project) {
 | 
						|
  $project = ParseSenderDomain($from);  
 | 
						|
}
 | 
						|
//Add the project code (if applicable).
 | 
						|
if($project) {
 | 
						|
  $params['project'] = $project;
 | 
						|
}
 | 
						|
 | 
						|
if($debugMode) {
 | 
						|
  //debug code.
 | 
						|
  $email .= "\n\nDelivered To - $deliveredTo\n";
 | 
						|
  $email .= "Project - $project\n";
 | 
						|
  $email .= "From -  $from\n";
 | 
						|
  $email .= "Subject -  $subject\n";
 | 
						|
  $email .= "Params:\n";
 | 
						|
  $email .=  print_r($params, TRUE);
 | 
						|
  saveEmail($email);
 | 
						|
}
 | 
						|
 | 
						|
if(!$dryRun) {
 | 
						|
  SendToMailHandler($email, $params);
 | 
						|
}
 | 
						|
 | 
						|
// Send to Ruby mailhandler.
 | 
						|
function SendToMailHandler($input, $params) {
 | 
						|
 | 
						|
  $descriptorspec = array(
 | 
						|
    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
 | 
						|
    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
 | 
						|
    2 => array("pipe", "w"),  // stderr is a pipe that the child will write to
 | 
						|
  );
 | 
						|
  $process = proc_open("/usr/local/bin/rdm-mailhandler.rb --url={$params['url']} --key={$params['key']} --unknown-user={$params['unknown-user']} --no-permission-check --allow-override={$params['allow-override']} --project {$params['project']} --tracker {$params['tracker']}", $descriptorspec, $pipes);
 | 
						|
 | 
						|
  if (is_resource($process)) {
 | 
						|
    // $pipes now looks like this:
 | 
						|
    // 0 => writeable handle connected to child stdin
 | 
						|
    // 1 => readable handle connected to child stdout
 | 
						|
    // Any error output will be appended to /tmp/error-output.txt
 | 
						|
 | 
						|
    fwrite($pipes[0], $input);
 | 
						|
    fclose($pipes[0]);
 | 
						|
 | 
						|
    echo stream_get_contents($pipes[1]);
 | 
						|
    $errorMessage = stream_get_contents($pipes[2]);
 | 
						|
    fclose($pipes[1]);
 | 
						|
    fclose($pipes[2]);
 | 
						|
 | 
						|
    // It is important that you close any pipes before calling
 | 
						|
    // proc_close in order to avoid a deadlock
 | 
						|
    $return_value = proc_close($process);
 | 
						|
 | 
						|
    // Log errors, also display on screen and send an email
 | 
						|
    if($return_value) {
 | 
						|
      echo $errorMessage;
 | 
						|
      $log = "Redmine redirect error: $errorMessage";
 | 
						|
      syslog(LOG_ERR, $log);
 | 
						|
 | 
						|
      $to = "info@megaphonetech.com";
 | 
						|
      $subject = "Redmine email routing failure";
 | 
						|
      $message = $log . "\n\n";
 | 
						|
      $message .= $input;
 | 
						|
      mail($to, $subject, $message);
 | 
						|
      saveEmail($input);
 | 
						|
    }
 | 
						|
 | 
						|
    echo "command returned $return_value\n";
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
//See if this email address is associated with a particular project
 | 
						|
function ParseSenderEmail($from) {
 | 
						|
  $project = $email = NULL;
 | 
						|
  if(preg_match("/\b([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4})\b/i", $from, $matches)) {
 | 
						|
    $email = $matches[1];
 | 
						|
  }
 | 
						|
  if (($handle = fopen(__DIR__ . "/" . "data/usermap.csv", 'r')) !== FALSE) {
 | 
						|
    while (($data = fgetcsv($handle, 1000)) !== FALSE) {
 | 
						|
      $users[$data[0]] = $data[1];
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (isset($users[$email])) {
 | 
						|
    $project = $users[$email];
 | 
						|
  }
 | 
						|
  return $project;
 | 
						|
}
 | 
						|
 | 
						|
function ParseSenderDomain($email) {
 | 
						|
  $domain = $project = NULL;
 | 
						|
  if(preg_match("/@(.*)\b/", $email, $matches)) {
 | 
						|
    $domain = $matches[1];
 | 
						|
  }
 | 
						|
  if (($handle = fopen(__DIR__ . "/" . "data/domainmap.csv", 'r')) !== FALSE) {
 | 
						|
    while (($data = fgetcsv($handle, 1000)) !== FALSE) {
 | 
						|
      $domains[$data[0]] = $data[1];
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if(isset($domains[$domain])) {
 | 
						|
    $project = $domains[$domain];
 | 
						|
  }
 | 
						|
  return $project;
 | 
						|
}
 | 
						|
 | 
						|
function saveEmail($email) {
 | 
						|
  $debugFileName = '/tmp/EmailProcessing' . time();
 | 
						|
  echo "$debugFileName";
 | 
						|
  $debugFile = fopen($debugFileName, 'w');
 | 
						|
  fwrite($debugFile, $email);
 | 
						|
  fclose($debugFile);
 | 
						|
  // also print to stdout, in case we're running manually
 | 
						|
  echo $email;
 | 
						|
}
 | 
						|
 | 
						|
?>
 |