createfrommail.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. // Copyright (C) 2010-2012 Combodo SARL
  3. //
  4. // This file is part of iTop.
  5. //
  6. // iTop is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU Affero General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // iTop is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Affero General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Affero General Public License
  17. // along with iTop. If not, see <http://www.gnu.org/licenses/>
  18. /**
  19. * Specific page to read a mailbox using the POP3 protocol, get the incoming
  20. * mails, turn them into UserRequest tickets, then remove the mails
  21. * from the mailbox. In order to create tickets from emails received into
  22. * such an inbox, this page must be called at frequent intervals, since it
  23. * will process all the messages sitting in the inbox, then exit.
  24. * You can use a simple scheduled 'wget' command line script to call this page
  25. * from either a 'cron'' (Unix) or 'at' (Windows) command.
  26. *
  27. * Use this page as an example and feel free to tailor it to your needs,
  28. * especially the default settings for the ticket (see below)
  29. *
  30. * @copyright Copyright (C) 2010-2012 Combodo SARL
  31. * @license http://opensource.org/licenses/AGPL-3.0
  32. */
  33. // Some PEAR includes that are required for reading emails
  34. include 'Net/POP3.php';
  35. include 'Mail/mimeDecode.php';
  36. // Parameters to access your mailbox
  37. define('MAILBOX_SERVER', 'pop3.combodo.com'); // Replace with the IP or FQDN name of your POP3 server
  38. define('MAILBOX_SERVER_PORT', 110); // 110 is the default for POP3
  39. define('MAILBOX_ACCOUNT', 'test@combodo.com'); // You mailbox account
  40. define('MAILBOX_PASSWORD', 'combodo'); // Password for this mailbox
  41. // Default settings for the ticket creation
  42. define('DEFAULT_IMPACT', '2');
  43. define('DEFAULT_URGENCY', '2');
  44. define('DEFAULT_SERVICE_ID', 2);
  45. define('DEFAULT_SUBSERVICE_ID', 12);
  46. define('DEFAULT_PRODUCT', 'Request via eMail');
  47. define('DEFAULT_WORKGROUP_ID', 5);
  48. if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
  49. require_once(__DIR__.'/../approot.inc.php');
  50. require_once(APPROOT.'/application/application.inc.php');
  51. require_once(APPROOT.'/application/startup.inc.php');
  52. function GetSender($aHeaders)
  53. {
  54. $aResult = array('name' => '', 'email' => '');
  55. $aResult['name'] = $aHeaders['From'];
  56. $aMatches = array();
  57. if (preg_match('/\(([0-9a-zA-Z\._]+)@(.+)@(.+)\)/U', array_pop($aHeaders['Received']), $aMatches))
  58. {
  59. $aResult['email'] = $aMatches[1].'@'.$aMatches[2];
  60. }
  61. return $aResult;
  62. }
  63. /**
  64. * Create a User Request ticket from the basic information retrieved from an email
  65. * @param string $sSenderEmail eMail address of the sender (From), used to lookup a contact in iTop
  66. * @param string $sSubject eMail's subject, will be turned into the title of the ticket
  67. * @param string $sBody Body of the email, will be fitted into the ticket's description
  68. * @return UserRequest The created ticket, or null if the creation failed for some reason...
  69. */
  70. function CreateTicket($sSenderEmail, $sSubject, $sBody)
  71. {
  72. $oTicket = null;
  73. try
  74. {
  75. $oContactSearch = new DBObjectSearch('Contact'); // Can be either a Person or a Team, but must be a valid Contact
  76. $oContactSearch->AddCondition('email', $sSenderEmail, '=');
  77. $oSet = new DBObjectSet($oContactSearch);
  78. if ($oSet->Count() == 1)
  79. {
  80. $oContact = $oSet->Fetch();
  81. $oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id'));
  82. $oTicket = new UserRequest;
  83. $oTicket->Set('title', $sSubject);
  84. $oTicket->Set('description', $sBody);
  85. $oTicket->Set('org_id', $oOrganization->GetKey());
  86. $oTicket->Set('caller_id', $oContact->GetKey());
  87. $oTicket->Set('impact', DEFAULT_IMPACT);
  88. $oTicket->Set('urgency', DEFAULT_URGENCY);
  89. $oTicket->Set('product', DEFAULT_PRODUCT);
  90. $oTicket->Set('service_id', DEFAULT_SERVICE_ID); // Can be replaced by a search for a valid service for this 'org_id'
  91. $oTicket->Set('servicesubcategory_id', DEFAULT_SUBSERVICE_ID); // Same as above...
  92. $oTicket->Set('workgroup_id', DEFAULT_WORKGROUP_ID); // Same as above...
  93. // Record the change information about the object
  94. $oMyChange = MetaModel::NewObject("CMDBChange");
  95. $oMyChange->Set("date", time());
  96. $sUserString = $oContact->GetName().', submitted by email';
  97. $oMyChange->Set("userinfo", $sUserString);
  98. $iChangeId = $oMyChange->DBInsert();
  99. $oTicket->DBInsertTracked($oMyChange);
  100. }
  101. else
  102. {
  103. echo "No contact found in iTop having the email: $sSenderEmail, email message ignored.\n";
  104. }
  105. }
  106. catch(Exception $e)
  107. {
  108. echo "Error: exception ".$e->getMessage();
  109. $oTicket = null;
  110. }
  111. return $oTicket;
  112. }
  113. /**
  114. * Main program
  115. */
  116. // Connect to the POP3 server & open the mailbox
  117. $oPop3 = new Net_POP3();
  118. $oPop3->connect(MAILBOX_SERVER, MAILBOX_SERVER_PORT);
  119. $oPop3->login(MAILBOX_ACCOUNT, MAILBOX_PASSWORD);
  120. // Read all the messages from the mailbox and tries to create a new ticket for each one
  121. // Note: it is expected that the sender of the email exists a valid contact as a 'Contact'
  122. // in iTop (identified by her/his email address), otherwise the ticket creation will fail
  123. $iNbMessages = $oPop3->numMsg();
  124. for($index = 1; $index <= $iNbMessages; $index++)
  125. {
  126. $params['include_bodies'] = true;
  127. $params['decode_bodies'] = true;
  128. $params['decode_headers'] = true;
  129. $params['crlf'] = "\r\n";
  130. $aHeaders = $oPop3->getParsedHeaders($index);
  131. $aSender = GetSender($aHeaders);
  132. $oDecoder = new Mail_mimeDecode( $oPop3->getRawHeaders($index).$params['crlf'].$oPop3->getBody($index) );
  133. $oStructure = $oDecoder->decode($params);
  134. $sSubject = $aHeaders['Subject'];
  135. // Search for the text/plain body part
  136. $iPartIndex = 0;
  137. $bFound = false;
  138. $sTextBody = '';
  139. //echo "<pre>\n";
  140. //print_r($oStructure);
  141. //echo "</pre>\n";
  142. if (!isset($oStructure->parts) || count($oStructure->parts) == 0)
  143. {
  144. $sTextBody = $oStructure->body;
  145. }
  146. else
  147. {
  148. // Find the first "part" of the body which is in text/plain
  149. while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
  150. {
  151. //echo "<p>Reading part $iPartIndex</p>\n";
  152. if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
  153. ($oStructure->parts[$iPartIndex]->ctype_secondary == 'plain') )
  154. {
  155. $sTextBody = $oStructure->parts[$iPartIndex]->body;
  156. $bFound = true;
  157. //echo "<p>Plain text found ! ($sTextBody)</p>\n";
  158. }
  159. $iPartIndex++;
  160. }
  161. // Try again but this time look for an HTML part
  162. if (!$bFound)
  163. {
  164. while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
  165. {
  166. //echo "<p>Reading part $iPartIndex</p>\n";
  167. if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
  168. ($oStructure->parts[$iPartIndex]->ctype_secondary == 'html') )
  169. {
  170. $sTextBody = $oStructure->parts[$iPartIndex]->body;
  171. $bFound = true;
  172. //echo "<p>HTML text found ! (".htmlentities($sTextBody, ENT_QUOTES, 'UTF-8').")</p>\n";
  173. }
  174. $iPartIndex++;
  175. }
  176. }
  177. }
  178. // Bug: depending on the email, the email address could be found in :
  179. // email => 'john.foo@combodo.com'
  180. // name => 'john foo <john.foo@combodo.com>
  181. $oTicket = CreateTicket($aSender['email'], $sSubject, $sTextBody);
  182. if ($oTicket != null)
  183. {
  184. // Ticket created, delete the email
  185. $oPop3->deleteMsg($index);
  186. echo "Ticket: ".$oTicket->GetName()." created.\n";
  187. }
  188. }
  189. $oPop3->disconnect();
  190. ?>