PageRenderTime 38ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/tine20/Expressomail/Model/MessageDispositionNotificationPart.php

https://gitlab.com/rsilveira1987/Expresso
PHP | 305 lines | 154 code | 50 blank | 101 comment | 17 complexity | 127918bf78f0c1049acef6b849b225ad MD5 | raw file
  1. <?php
  2. /**
  3. * class to hold Message Disposition Notification (MDN) part
  4. *
  5. * @package Expressomail
  6. * @subpackage Model
  7. * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
  8. * @author Fernando Alberto Reuter Wendt <fernando-alberto.wendt@serpro.gov.br>
  9. * @copyright Copyright (c) 2011 Metaways Infosystems GmbH (http://www.metaways.de)
  10. * @copyright Copyright (c) 2016 Serviço Fedral de Processamento de Dados - SERPRO
  11. */
  12. class Expressomail_Model_MessageDispositionNotificationPart
  13. {
  14. /***** STATIC ATTRIBUTES : RFC CONFORMANCE *****/
  15. /**
  16. * Disposition Mode Automatic
  17. */
  18. const DISPOSITION_MODE_AUTOMATIC = 'automatic-action';
  19. /**
  20. * Disposition Mode Manual
  21. */
  22. const DISPOSITION_MODE_MANUAL = 'manual-action';
  23. /**
  24. * Disposition Mode Sent Automatic
  25. */
  26. const DISPOSITION_MODE_MDN_AUTOMATIC = 'MDN-sent-automatically';
  27. /**
  28. * Disposition Mode Sent Manually
  29. */
  30. const DISPOSITION_MODE_MDN_MANUAL = 'MDN-sent-manually';
  31. /**
  32. * Disposition Type Displayed
  33. */
  34. const DISPOSITION_TYPE_DISPLAYED = 'displayed';
  35. /**
  36. * Disposition Type Dispached
  37. */
  38. const DISPOSITION_TYPE_DISPACHED = 'dispatched';
  39. /**
  40. * Disposition Type Processed
  41. */
  42. const DISPOSITION_TYPE_PROCESSED = 'processed';
  43. /**
  44. * Disposition Type Deleted
  45. */
  46. const DISPOSITION_TYPE_DELETED = 'deleted';
  47. /**
  48. * Disposition Type Denied
  49. */
  50. const DISPOSITION_TYPE_DENIED = 'denied';
  51. /**
  52. * Disposition Type Failed
  53. */
  54. const DISPOSITION_TYPE_FAILED = 'failed';
  55. /**
  56. * Disposition Modifier Error
  57. */
  58. const DISPOSITION_MODIFIER_ERROR = 'error';
  59. /**
  60. * Disposition Modifier Warning
  61. */
  62. const DISPOSITION_MODIFIER_WARNING = 'warning';
  63. /**
  64. * Disposition Modifier Superseded
  65. */
  66. const DISPOSITION_MODIFIER_SUPERSEDED = 'superseded';
  67. /**
  68. * Disposition Modifier Expired
  69. */
  70. const DISPOSITION_MODIFIER_EXPIRED = 'expired';
  71. /**
  72. * Disposition Modifer Mailbox Terminated
  73. */
  74. const DISPOSITION_MODIFIER_MAILBOX_TERMINATED = 'mailbox-terminated';
  75. /***** Properties *****/
  76. protected $_parsed = FALSE;
  77. protected $_mdnBody;
  78. protected $_recipient;
  79. protected $_dispositionMode;
  80. protected $_dispositionType;
  81. protected $_customMessage;
  82. /**
  83. * Object class constructor
  84. *
  85. * @param type $_mdnBody
  86. */
  87. public function __construct($_mdnBody)
  88. {
  89. $this->_mdnBody = $_mdnBody;
  90. }
  91. /**
  92. * Set the type of disposition
  93. *
  94. * @param string $_foundType
  95. */
  96. protected function _setDispositionType($_foundType)
  97. {
  98. preg_match('/[[:alnum:]-_]+$/', $_foundType, $type);
  99. if(empty($type) || count($type) != 1){
  100. $return = 'Unknown Action';
  101. Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__
  102. . ' MDN action unhandled: ' . print_r($type,true));
  103. }
  104. else{
  105. $return = '';
  106. switch ($type[0]) {
  107. case self::DISPOSITION_TYPE_DELETED :
  108. $return = 'Message was deleted';
  109. break;
  110. default:
  111. $return = 'Unknown Type';
  112. Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__
  113. . ' MDN type not mapped error: ' . $type[0]);
  114. break;
  115. }
  116. }
  117. $this->_dispositionType = $return;
  118. }
  119. /**
  120. * Set the mode of the disposition
  121. *
  122. * @param string $_foundDisposition
  123. */
  124. protected function _setDispositionMode($_foundDisposition)
  125. {
  126. preg_match('/[[:alnum:]-_]+\/[[:alnum:]-_]+;/', $_foundDisposition, $mode);
  127. $return = '';
  128. if(empty($mode) || count($mode) != 1){
  129. $return = 'Unknown Mode';
  130. Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__
  131. . ' MDN mode unhandled: ' . print_r($mode,true));
  132. }
  133. else{
  134. switch ($mode[0]) {
  135. case self::DISPOSITION_MODE_AUTOMATIC.'/'.self::DISPOSITION_MODE_MDN_AUTOMATIC.';' :
  136. $return = 'Automatic Action Performed';
  137. break;
  138. case self::DISPOSITION_MODE_MANUAL :
  139. $return = 'Manual Action Performed';
  140. break;
  141. default:
  142. $return = 'Unknown Mode';
  143. Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__
  144. . ' MDN Mode value mapping error: ' . $mode[0]);
  145. break;
  146. }
  147. }
  148. $this->_dispositionMode = $return;
  149. }
  150. /**
  151. * Parse MDN Message
  152. */
  153. public function parse()
  154. {
  155. // Break per message and per recipient fields
  156. $out = preg_split('/(?<=\x0A)\x0D\x0A/', $this->_mdnBody);
  157. $errors = array();
  158. $this->_recipients = array();
  159. foreach ($out as $perRecipients) {
  160. $recipient = array();
  161. //Final-Recipient (Required)
  162. preg_match('/Final-Recipient:\s*[[:alnum:]-_]+;\s*(.+?)\x0D\x0A/', $perRecipients, $matches);
  163. if (empty($matches) || count($matches) != 2){
  164. $errors[] = 'Error Parsing per Message Block: Final-Recipient Field';
  165. }
  166. //Switch Sieve '^' identifyer delimiter for '.' email address notation
  167. $matches = str_replace('^', '.', $matches);
  168. $finalRecipient = $matches[1];
  169. $recipient['finalRecipient'] = $finalRecipient;
  170. unset($matches);
  171. $this->_recipients[] = $recipient;
  172. //Disposition action type mapping
  173. preg_match('/Disposition:\s[[:alnum:]-_]+\/[[:alnum:]-_]+;\s[[:alnum:]-_]+/', $perRecipients, $foundDisposition);
  174. if (empty($foundDisposition) || count($foundDisposition != 1)){
  175. $errors[] = 'Error Parsing per Message Block: Disposition Field';
  176. }
  177. $this->_setDispositionMode($foundDisposition[0]);
  178. $this->_setDispositionType($foundDisposition[0]);
  179. }
  180. $this->_parsed = TRUE;
  181. }
  182. /*
  183. * Defaults body message content to be displayed for user
  184. *
  185. * @param Tinebase_Translation $_translateIt
  186. * @return string $htmlOut
  187. */
  188. protected function _MessageBodyTemplate($_translateIt){
  189. $htmlOut = "";
  190. // Final message recipient: most will have just one
  191. $htmlOut .= '<b>' . $_translateIt->_('Recipient') . ':</b> ';
  192. $htmlOut .= $this->_recipients[0]['finalRecipient'];
  193. $htmlOut .= '<br />';
  194. // How it happend: most will be SIEVE automatic action
  195. $htmlOut .= '<b>' . $_translateIt->_('Action Type') . ':</b> ';
  196. $htmlOut .= $_translateIt->_($this->_dispositionMode);
  197. $htmlOut .= '<br />';
  198. // What happend: by now, most will be deleted action
  199. $htmlOut .= '<b>' . $_translateIt->_('Status') . ':</b> ';
  200. $htmlOut .= $_translateIt->_($this->_dispositionType);
  201. $htmlOut .= '<br /><br />';
  202. // Has a custom message to show? Display user creation SIEVE filter data here
  203. if (strlen(trim($this->_customMessage)) > 0){
  204. $htmlOut .= '<b>' . $_translateIt->_('Custom User Message') . ':</b> ';
  205. $htmlOut .= '<i>&quot;' . trim($this->_customMessage) . '&quot;</i>';
  206. $htmlOut .= '<br />';
  207. }
  208. return $htmlOut;
  209. }
  210. /**
  211. * Get the user friendly HTML content message
  212. *
  213. * @param string $userMessage
  214. * @return string $html
  215. */
  216. public function getHTMLFormatted($userMessage)
  217. {
  218. $this->_customMessage = $userMessage;
  219. if (!$this->_parsed) {
  220. $this->parse();
  221. }
  222. $translate = Tinebase_Translation::getTranslation('Expressomail');
  223. $html = '<html>'
  224. . '<head>'
  225. . '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
  226. . '<style type="text/css">'
  227. . '.expressomail-body-blockquote {'
  228. . 'margin: 5px 10px 0 3px;'
  229. . 'padding-left: 10px;'
  230. . 'border-left: 2px solid #000088;'
  231. . '}'
  232. . '</style>'
  233. . '</head>'
  234. . '<body>';
  235. $html .= '<h3>' . $translate->_('Message Disposition Notification') . '</h3>';
  236. $html .= '<br /><br />';
  237. $html .= $this->_MessageBodyTemplate($translate);
  238. $html .= '</body></html>';
  239. return $html;
  240. }
  241. /**
  242. * Get original SIEVE filter message created
  243. *
  244. * @return string $findMessage
  245. */
  246. public function getCustomMessage(){
  247. preg_match('/The following reason was given:\x0D\x0A\w.{0,255}/', $this->_mdnBody, $matches);
  248. //If there is no custom message, returns nothing
  249. if (empty($matches)) {
  250. return '';
  251. }
  252. $findMessage = explode(':',$matches[0]);
  253. return $findMessage[1];
  254. }
  255. }