123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <?php
- // Copyright (C) 2010-2012 Combodo SARL
- //
- // This file is part of iTop.
- //
- // iTop is free software; you can redistribute it and/or modify
- // it under the terms of the GNU Affero General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // iTop is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with iTop. If not, see <http://www.gnu.org/licenses/>
- /**
- * Specific page to read a mailbox using the POP3 protocol, get the incoming
- * mails, turn them into UserRequest tickets, then remove the mails
- * from the mailbox. In order to create tickets from emails received into
- * such an inbox, this page must be called at frequent intervals, since it
- * will process all the messages sitting in the inbox, then exit.
- * You can use a simple scheduled 'wget' command line script to call this page
- * from either a 'cron'' (Unix) or 'at' (Windows) command.
- *
- * Use this page as an example and feel free to tailor it to your needs,
- * especially the default settings for the ticket (see below)
- *
- * @copyright Copyright (C) 2010-2012 Combodo SARL
- * @license http://opensource.org/licenses/AGPL-3.0
- */
- // Some PEAR includes that are required for reading emails
- include 'Net/POP3.php';
- include 'Mail/mimeDecode.php';
- // Parameters to access your mailbox
- define('MAILBOX_SERVER', 'pop3.combodo.com'); // Replace with the IP or FQDN name of your POP3 server
- define('MAILBOX_SERVER_PORT', 110); // 110 is the default for POP3
- define('MAILBOX_ACCOUNT', 'test@combodo.com'); // You mailbox account
- define('MAILBOX_PASSWORD', 'combodo'); // Password for this mailbox
- // Default settings for the ticket creation
- define('DEFAULT_IMPACT', '2');
- define('DEFAULT_URGENCY', '2');
- define('DEFAULT_SERVICE_ID', 2);
- define('DEFAULT_SUBSERVICE_ID', 12);
- define('DEFAULT_PRODUCT', 'Request via eMail');
- define('DEFAULT_WORKGROUP_ID', 5);
- if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
- require_once(__DIR__.'/../approot.inc.php');
- require_once(APPROOT.'/application/application.inc.php');
- require_once(APPROOT.'/application/startup.inc.php');
- function GetSender($aHeaders)
- {
- $aResult = array('name' => '', 'email' => '');
- $aResult['name'] = $aHeaders['From'];
- $aMatches = array();
- if (preg_match('/\(([0-9a-zA-Z\._]+)@(.+)@(.+)\)/U', array_pop($aHeaders['Received']), $aMatches))
- {
- $aResult['email'] = $aMatches[1].'@'.$aMatches[2];
- }
- return $aResult;
- }
- /**
- * Create a User Request ticket from the basic information retrieved from an email
- * @param string $sSenderEmail eMail address of the sender (From), used to lookup a contact in iTop
- * @param string $sSubject eMail's subject, will be turned into the title of the ticket
- * @param string $sBody Body of the email, will be fitted into the ticket's description
- * @return UserRequest The created ticket, or null if the creation failed for some reason...
- */
- function CreateTicket($sSenderEmail, $sSubject, $sBody)
- {
- $oTicket = null;
- try
- {
- $oContactSearch = new DBObjectSearch('Contact'); // Can be either a Person or a Team, but must be a valid Contact
- $oContactSearch->AddCondition('email', $sSenderEmail, '=');
- $oSet = new DBObjectSet($oContactSearch);
- if ($oSet->Count() == 1)
- {
- $oContact = $oSet->Fetch();
- $oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id'));
- $oTicket = new UserRequest;
- $oTicket->Set('title', $sSubject);
- $oTicket->Set('description', $sBody);
- $oTicket->Set('org_id', $oOrganization->GetKey());
- $oTicket->Set('caller_id', $oContact->GetKey());
- $oTicket->Set('impact', DEFAULT_IMPACT);
- $oTicket->Set('urgency', DEFAULT_URGENCY);
- $oTicket->Set('product', DEFAULT_PRODUCT);
- $oTicket->Set('service_id', DEFAULT_SERVICE_ID); // Can be replaced by a search for a valid service for this 'org_id'
- $oTicket->Set('servicesubcategory_id', DEFAULT_SUBSERVICE_ID); // Same as above...
- $oTicket->Set('workgroup_id', DEFAULT_WORKGROUP_ID); // Same as above...
- // Record the change information about the object
- $oMyChange = MetaModel::NewObject("CMDBChange");
- $oMyChange->Set("date", time());
- $sUserString = $oContact->GetName().', submitted by email';
- $oMyChange->Set("userinfo", $sUserString);
- $iChangeId = $oMyChange->DBInsert();
- $oTicket->DBInsertTracked($oMyChange);
- }
- else
- {
- echo "No contact found in iTop having the email: $sSenderEmail, email message ignored.\n";
- }
- }
- catch(Exception $e)
- {
- echo "Error: exception ".$e->getMessage();
- $oTicket = null;
- }
- return $oTicket;
- }
- /**
- * Main program
- */
- // Connect to the POP3 server & open the mailbox
- $oPop3 = new Net_POP3();
- $oPop3->connect(MAILBOX_SERVER, MAILBOX_SERVER_PORT);
- $oPop3->login(MAILBOX_ACCOUNT, MAILBOX_PASSWORD);
- // Read all the messages from the mailbox and tries to create a new ticket for each one
- // Note: it is expected that the sender of the email exists a valid contact as a 'Contact'
- // in iTop (identified by her/his email address), otherwise the ticket creation will fail
- $iNbMessages = $oPop3->numMsg();
- for($index = 1; $index <= $iNbMessages; $index++)
- {
- $params['include_bodies'] = true;
- $params['decode_bodies'] = true;
- $params['decode_headers'] = true;
- $params['crlf'] = "\r\n";
- $aHeaders = $oPop3->getParsedHeaders($index);
- $aSender = GetSender($aHeaders);
- $oDecoder = new Mail_mimeDecode( $oPop3->getRawHeaders($index).$params['crlf'].$oPop3->getBody($index) );
- $oStructure = $oDecoder->decode($params);
- $sSubject = $aHeaders['Subject'];
- // Search for the text/plain body part
- $iPartIndex = 0;
- $bFound = false;
- $sTextBody = '';
- //echo "<pre>\n";
- //print_r($oStructure);
- //echo "</pre>\n";
- if (!isset($oStructure->parts) || count($oStructure->parts) == 0)
- {
- $sTextBody = $oStructure->body;
- }
- else
- {
- // Find the first "part" of the body which is in text/plain
- while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
- {
- //echo "<p>Reading part $iPartIndex</p>\n";
- if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
- ($oStructure->parts[$iPartIndex]->ctype_secondary == 'plain') )
- {
- $sTextBody = $oStructure->parts[$iPartIndex]->body;
- $bFound = true;
- //echo "<p>Plain text found ! ($sTextBody)</p>\n";
- }
- $iPartIndex++;
- }
- // Try again but this time look for an HTML part
- if (!$bFound)
- {
- while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
- {
- //echo "<p>Reading part $iPartIndex</p>\n";
- if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
- ($oStructure->parts[$iPartIndex]->ctype_secondary == 'html') )
- {
- $sTextBody = $oStructure->parts[$iPartIndex]->body;
- $bFound = true;
- //echo "<p>HTML text found ! (".htmlentities($sTextBody, ENT_QUOTES, 'UTF-8').")</p>\n";
- }
- $iPartIndex++;
- }
- }
- }
- // Bug: depending on the email, the email address could be found in :
- // email => 'john.foo@combodo.com'
- // name => 'john foo <john.foo@combodo.com>
- $oTicket = CreateTicket($aSender['email'], $sSubject, $sTextBody);
- if ($oTicket != null)
- {
- // Ticket created, delete the email
- $oPop3->deleteMsg($index);
- echo "Ticket: ".$oTicket->GetName()." created.\n";
- }
- }
- $oPop3->disconnect();
- ?>
|