createfrommail.php 7.1 KB

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