createfrommail.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. define('DEFAULT_WORKGROUP_ID', 5);
  48. require_once('../approot.inc.php');
  49. require_once(APPROOT.'/application/application.inc.php');
  50. require_once(APPROOT.'/application/startup.inc.php');
  51. function GetSender($aHeaders)
  52. {
  53. $aResult = array('name' => '', 'email' => '');
  54. $aResult['name'] = $aHeaders['From'];
  55. $aMatches = array();
  56. if (preg_match('/\(([0-9a-zA-Z\._]+)@(.+)@(.+)\)/U', array_pop($aHeaders['Received']), $aMatches))
  57. {
  58. $aResult['email'] = $aMatches[1].'@'.$aMatches[2];
  59. }
  60. return $aResult;
  61. }
  62. /**
  63. * Create a User Request ticket from the basic information retrieved from an email
  64. * @param string $sSenderEmail eMail address of the sender (From), used to lookup a contact in iTop
  65. * @param string $sSubject eMail's subject, will be turned into the title of the ticket
  66. * @param string $sBody Body of the email, will be fitted into the ticket's description
  67. * @return UserRequest The created ticket, or null if the creation failed for some reason...
  68. */
  69. function CreateTicket($sSenderEmail, $sSubject, $sBody)
  70. {
  71. $oTicket = null;
  72. try
  73. {
  74. $oContactSearch = new DBObjectSearch('Contact'); // Can be either a Person or a Team, but must be a valid Contact
  75. $oContactSearch->AddCondition('email', $sSenderEmail, '=');
  76. $oSet = new DBObjectSet($oContactSearch);
  77. if ($oSet->Count() == 1)
  78. {
  79. $oContact = $oSet->Fetch();
  80. $oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id'));
  81. $oTicket = new UserRequest;
  82. $oTicket->Set('title', $sSubject);
  83. $oTicket->Set('description', $sBody);
  84. $oTicket->Set('org_id', $oOrganization->GetKey());
  85. $oTicket->Set('caller_id', $oContact->GetKey());
  86. $oTicket->Set('impact', DEFAULT_IMPACT);
  87. $oTicket->Set('urgency', DEFAULT_URGENCY);
  88. $oTicket->Set('product', DEFAULT_PRODUCT);
  89. $oTicket->Set('service_id', DEFAULT_SERVICE_ID); // Can be replaced by a search for a valid service for this 'org_id'
  90. $oTicket->Set('servicesubcategory_id', DEFAULT_SUBSERVICE_ID); // Same as above...
  91. $oTicket->Set('workgroup_id', DEFAULT_WORKGROUP_ID); // Same as above...
  92. // Record the change information about the object
  93. $oMyChange = MetaModel::NewObject("CMDBChange");
  94. $oMyChange->Set("date", time());
  95. $sUserString = $oContact->GetName().', submitted by email';
  96. $oMyChange->Set("userinfo", $sUserString);
  97. $iChangeId = $oMyChange->DBInsert();
  98. $oTicket->DBInsertTracked($oMyChange);
  99. }
  100. else
  101. {
  102. echo "No contact found in iTop having the email: $sSenderEmail, email message ignored.\n";
  103. }
  104. }
  105. catch(Exception $e)
  106. {
  107. echo "Error: exception ".$e->getMessage();
  108. $oTicket = null;
  109. }
  110. return $oTicket;
  111. }
  112. /**
  113. * Main program
  114. */
  115. // Connect to the POP3 server & open the mailbox
  116. $oPop3 = new Net_POP3();
  117. $oPop3->connect(MAILBOX_SERVER, MAILBOX_SERVER_PORT);
  118. $oPop3->login(MAILBOX_ACCOUNT, MAILBOX_PASSWORD);
  119. // Read all the messages from the mailbox and tries to create a new ticket for each one
  120. // Note: it is expected that the sender of the email exists a valid contact as a 'Contact'
  121. // in iTop (identified by her/his email address), otherwise the ticket creation will fail
  122. $iNbMessages = $oPop3->numMsg();
  123. for($index = 1; $index <= $iNbMessages; $index++)
  124. {
  125. $params['include_bodies'] = true;
  126. $params['decode_bodies'] = true;
  127. $params['decode_headers'] = true;
  128. $params['crlf'] = "\r\n";
  129. $aHeaders = $oPop3->getParsedHeaders($index);
  130. $aSender = GetSender($aHeaders);
  131. $oDecoder = new Mail_mimeDecode( $oPop3->getRawHeaders($index).$params['crlf'].$oPop3->getBody($index) );
  132. $oStructure = $oDecoder->decode($params);
  133. $sSubject = $aHeaders['Subject'];
  134. // Search for the text/plain body part
  135. $iPartIndex = 0;
  136. $bFound = false;
  137. $sTextBody = '';
  138. //echo "<pre>\n";
  139. //print_r($oStructure);
  140. //echo "</pre>\n";
  141. if (!isset($oStructure->parts) || count($oStructure->parts) == 0)
  142. {
  143. $sTextBody = $oStructure->body;
  144. }
  145. else
  146. {
  147. // Find the first "part" of the body which is in text/plain
  148. while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
  149. {
  150. //echo "<p>Reading part $iPartIndex</p>\n";
  151. if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
  152. ($oStructure->parts[$iPartIndex]->ctype_secondary == 'plain') )
  153. {
  154. $sTextBody = $oStructure->parts[$iPartIndex]->body;
  155. $bFound = true;
  156. //echo "<p>Plain text found ! ($sTextBody)</p>\n";
  157. }
  158. $iPartIndex++;
  159. }
  160. // Try again but this time look for an HTML part
  161. if (!$bFound)
  162. {
  163. while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
  164. {
  165. //echo "<p>Reading part $iPartIndex</p>\n";
  166. if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
  167. ($oStructure->parts[$iPartIndex]->ctype_secondary == 'html') )
  168. {
  169. $sTextBody = $oStructure->parts[$iPartIndex]->body;
  170. $bFound = true;
  171. //echo "<p>HTML text found ! (".htmlentities($sTextBody, ENT_QUOTES, 'UTF-8').")</p>\n";
  172. }
  173. $iPartIndex++;
  174. }
  175. }
  176. }
  177. // Bug: depending on the email, the email address could be found in :
  178. // email => 'john.foo@combodo.com'
  179. // name => 'john foo <john.foo@combodo.com>
  180. $oTicket = CreateTicket($aSender['email'], $sSubject, $sTextBody);
  181. if ($oTicket != null)
  182. {
  183. // Ticket created, delete the email
  184. $oPop3->deleteMsg($index);
  185. echo "Ticket: ".$oTicket->GetName()." created.\n";
  186. }
  187. }
  188. $oPop3->disconnect();
  189. ?>