PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/mail/lib/user.php

https://gitlab.com/alexprowars/bitrix
PHP | 556 lines | 424 code | 79 blank | 53 comment | 50 complexity | 1516cdd20743bdf538f86c691915b314 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Mail;
  3. use Bitrix\Main;
  4. use Bitrix\Main\Localization\Loc;
  5. Main\Localization\Loc::loadMessages(__FILE__);
  6. class User
  7. {
  8. /**
  9. * Creates mail user
  10. *
  11. * @param array $fields User fields.
  12. * @return int|false
  13. */
  14. public static function create($fields)
  15. {
  16. $user = new \CUser;
  17. $userFields = array(
  18. 'LOGIN' => $fields["EMAIL"],
  19. 'EMAIL' => $fields["EMAIL"],
  20. 'NAME' => (!empty($fields["NAME"]) ? $fields["NAME"] : ''),
  21. 'LAST_NAME' => (!empty($fields["LAST_NAME"]) ? $fields["LAST_NAME"] : ''),
  22. 'PERSONAL_PHOTO' => (!empty($fields["PERSONAL_PHOTO_ID"]) ? \CFile::makeFileArray($fields['PERSONAL_PHOTO_ID']) : false),
  23. 'EXTERNAL_AUTH_ID' => 'email',
  24. );
  25. if (Main\ModuleManager::isModuleInstalled('intranet'))
  26. {
  27. $userFields['UF_DEPARTMENT'] = array();
  28. }
  29. if (
  30. isset($fields['UF'])
  31. && is_array($fields['UF'])
  32. )
  33. {
  34. foreach($fields['UF'] as $key => $value)
  35. {
  36. if (!empty($value))
  37. {
  38. $userFields[$key] = $value;
  39. }
  40. }
  41. }
  42. $mailGroup = self::getMailUserGroup();
  43. if (!empty($mailGroup))
  44. {
  45. $userFields["GROUP_ID"] = $mailGroup;
  46. }
  47. $result = $user->add($userFields);
  48. return $result;
  49. }
  50. /**
  51. * Runs user login
  52. *
  53. * @return void
  54. */
  55. public static function login()
  56. {
  57. $eventManager = Main\EventManager::getInstance();
  58. $handler = $eventManager->addEventHandlerCompatible('main', 'OnUserLoginExternal', array('\Bitrix\Mail\User', 'onLoginExternal'));
  59. global $USER;
  60. $USER->login(null, null, 'Y');
  61. $eventManager->removeEventHandler('main', 'OnUserLoginExternal', $handler);
  62. }
  63. /**
  64. * Returns mail user ID
  65. *
  66. * @param array &$params Auth params.
  67. * @return int|false
  68. */
  69. public static function onLoginExternal(&$params)
  70. {
  71. $context = Main\Application::getInstance()->getContext();
  72. $request = $context->getRequest();
  73. if ($token = $request->get('token') ?: $request->getCookie('MAIL_AUTH_TOKEN'))
  74. {
  75. $userRelation = UserRelationsTable::getList(array(
  76. 'select' => array('USER_ID'),
  77. 'filter' => array(
  78. '=TOKEN' => $token,
  79. '=USER.EXTERNAL_AUTH_ID' => 'email',
  80. 'USER.ACTIVE' => 'Y'
  81. )
  82. ))->fetch();
  83. if ($userRelation)
  84. {
  85. $context->getResponse()->addCookie(new Main\Web\Cookie('MAIL_AUTH_TOKEN', $token));
  86. return $userRelation['USER_ID'];
  87. }
  88. }
  89. return false;
  90. }
  91. /**
  92. * Returns User-Entity unique email and entry point URL
  93. *
  94. * @param string $siteId Site ID.
  95. * @param int $userId User ID.
  96. * @param string $entityType Entity type ID.
  97. * @param int $entityId Entity ID.
  98. * @param string $entityLink Entity URL.
  99. * @param string $backurl Back URL.
  100. * @return array|false
  101. */
  102. public static function getReplyTo($siteId, $userId, $entityType, $entityId, $entityLink = null, $backurl = null)
  103. {
  104. $filter = array(
  105. '=SITE_ID' => $siteId,
  106. '=USER_ID' => $userId,
  107. '=ENTITY_TYPE' => $entityType,
  108. '=ENTITY_ID' => $entityId
  109. );
  110. $userRelation = UserRelationsTable::getList(array('filter' => $filter))->fetch();
  111. if (empty($userRelation))
  112. {
  113. $filter['=SITE_ID'] = null;
  114. $userRelation = UserRelationsTable::getList(array('filter' => $filter))->fetch();
  115. }
  116. if (empty($userRelation))
  117. {
  118. if (empty($entityLink))
  119. return false;
  120. $userRelation = array(
  121. 'SITE_ID' => $siteId,
  122. 'TOKEN' => base_convert(md5(time().Main\Security\Random::getBytes(6)), 16, 36),
  123. 'USER_ID' => $userId,
  124. 'ENTITY_TYPE' => $entityType,
  125. 'ENTITY_ID' => $entityId,
  126. 'ENTITY_LINK' => $entityLink,
  127. 'BACKURL' => $backurl
  128. );
  129. if (!UserRelationsTable::add($userRelation)->isSuccess())
  130. return false;
  131. }
  132. $site = Main\SiteTable::getByPrimary($siteId)->fetch();
  133. $context = Main\Application::getInstance()->getContext();
  134. $scheme = $context->getRequest()->isHttps() ? 'https' : 'http';
  135. $domain = $site['SERVER_NAME'] ?: \COption::getOptionString('main', 'server_name', '');
  136. if (preg_match('/^(?<domain>.+):(?<port>\d+)$/', $domain, $matches))
  137. {
  138. $domain = $matches['domain'];
  139. $port = $matches['port'];
  140. }
  141. else
  142. {
  143. $port = $context->getServer()->getServerPort();
  144. }
  145. $port = in_array($port, array(80, 443)) ? '' : ':'.$port;
  146. $path = ltrim(trim($site['DIR'], '/') . '/pub/entry.php', '/');
  147. $replyTo = sprintf('rpl%s@%s', $userRelation['TOKEN'], $domain);
  148. $backUrl = sprintf('%s://%s%s/%s#%s', $scheme, $domain, $port, $path, $userRelation['TOKEN']);
  149. return array($replyTo, $backUrl);
  150. }
  151. /**
  152. * Returns Site-User-Entity unique email
  153. *
  154. * @param string $siteId Site ID.
  155. * @param int $userId User ID.
  156. * @param string $entityType Entity type ID.
  157. * @return array|false
  158. */
  159. public static function getForwardTo($siteId, $userId, $entityType)
  160. {
  161. $cache = new \CPHPCache();
  162. $cacheKey = sprintf('%s_%s', $userId, $entityType);
  163. $cacheDir = sprintf('/mail/user/forward/%s', bin2hex($siteId));
  164. if ($cache->initCache(365*24*3600, $cacheKey, $cacheDir))
  165. {
  166. $forwardTo = $cache->getVars();
  167. }
  168. else
  169. {
  170. $userRelation = UserRelationsTable::getList(array(
  171. 'filter' => array(
  172. '=SITE_ID' => $siteId,
  173. '=USER_ID' => $userId,
  174. '=ENTITY_TYPE' => $entityType,
  175. '=ENTITY_ID' => null
  176. )
  177. ))->fetch();
  178. if (empty($userRelation))
  179. {
  180. $userRelation = array(
  181. 'SITE_ID' => $siteId,
  182. 'TOKEN' => base_convert(md5(time().Main\Security\Random::getBytes(6)), 16, 36),
  183. 'USER_ID' => $userId,
  184. 'ENTITY_TYPE' => $entityType
  185. );
  186. if (!UserRelationsTable::add($userRelation)->isSuccess())
  187. return false;
  188. // for dav addressbook modification label
  189. $user = new \CUser;
  190. $user->update($userId, array());
  191. }
  192. $site = Main\SiteTable::getByPrimary($siteId)->fetch();
  193. $domain = $site['SERVER_NAME'] ?: \COption::getOptionString('main', 'server_name', '');
  194. if (preg_match('/^(?<domain>.+):(?<port>\d+)$/', $domain, $matches))
  195. $domain = $matches['domain'];
  196. $forwardTo = sprintf('fwd%s@%s', $userRelation['TOKEN'], $domain);
  197. $cache->startDataCache();
  198. $cache->endDataCache($forwardTo);
  199. }
  200. return array($forwardTo);
  201. }
  202. public static function parseEmailRecipient($to)
  203. {
  204. if (!preg_match('/^(?<type>rpl|fwd)(?<token>[a-z0-9]+)@(?<domain>.+)/i', $to, $matches))
  205. {
  206. return false;
  207. }
  208. return $matches;
  209. }
  210. public static function getUserRelation($token)
  211. {
  212. $userRelation = UserRelationsTable::getList(array(
  213. 'filter' => array(
  214. '=TOKEN' => $token,
  215. 'USER.ACTIVE' => 'Y'
  216. )
  217. ))->fetch();
  218. if (!$userRelation)
  219. {
  220. return false;
  221. }
  222. return $userRelation;
  223. }
  224. /**
  225. * Sends email related events
  226. *
  227. * @param string $to Recipient email.
  228. * @param array $message Message.
  229. * @param string &$error Error.
  230. * @return bool
  231. */
  232. public static function onEmailReceived($to, $message, $recipient, $userRelation, &$error)
  233. {
  234. $type = $recipient['type'];
  235. $token = $recipient['token'];
  236. $message['secret'] = $token;
  237. switch ($type)
  238. {
  239. case 'rpl':
  240. $content = Message::parseReply($message);
  241. break;
  242. case 'fwd':
  243. $content = Message::parseForward($message);
  244. break;
  245. }
  246. if (empty($content) && empty($message['files']))
  247. {
  248. $error = sprintf('Empty message (rcpt: %s)', $to);
  249. return false;
  250. }
  251. $attachments = array_filter(
  252. array_combine(
  253. array_column((array) $message['files'], 'name'),
  254. array_column((array) $message['files'], 'tmp_name')
  255. )
  256. );
  257. $addResult = User\MessageTable::add(array(
  258. 'TYPE' => $type,
  259. 'SITE_ID' => $userRelation['SITE_ID'],
  260. 'ENTITY_TYPE' => $userRelation['ENTITY_TYPE'],
  261. 'ENTITY_ID' => $userRelation['ENTITY_ID'],
  262. 'USER_ID' => $userRelation['USER_ID'],
  263. 'SUBJECT' => $message['subject'],
  264. 'CONTENT' => $content,
  265. 'ATTACHMENTS' => serialize($attachments),
  266. ));
  267. if ($addResult->isSuccess())
  268. {
  269. \CAgent::addAgent(
  270. "\\Bitrix\\Mail\\User::sendEventAgent(".$addResult->getId().");",
  271. "mail", //module
  272. "N", //period
  273. 10 //interval
  274. );
  275. return true;
  276. }
  277. return false;
  278. }
  279. /**
  280. * Agent method, retrieves stored user message and sends an event
  281. */
  282. public static function sendEventAgent($messageId = 0, $cnt = 0)
  283. {
  284. $messageId = intval($messageId);
  285. if ($messageId <= 0)
  286. {
  287. return;
  288. }
  289. $res = User\MessageTable::getList(array(
  290. 'filter' => array(
  291. '=ID' => $messageId
  292. )
  293. ));
  294. if ($messageFields = $res->fetch())
  295. {
  296. if (intval($cnt) > 10)
  297. {
  298. if (Main\Loader::includeModule('im'))
  299. {
  300. $title = trim($messageFields['SUBJECT']);
  301. if ($title == '')
  302. {
  303. $title = trim($messageFields['CONTENT']);
  304. $title = preg_replace("/\[ATTACHMENT\s*=\s*[^\]]*\]/is".BX_UTF_PCRE_MODIFIER, "", $title);
  305. $CBXSanitizer = new \CBXSanitizer;
  306. $CBXSanitizer->delAllTags();
  307. $title = $CBXSanitizer->sanitizeHtml($title);
  308. }
  309. \CIMNotify::add(array(
  310. "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM,
  311. "NOTIFY_TYPE" => IM_NOTIFY_SYSTEM,
  312. "NOTIFY_MODULE" => "mail",
  313. "NOTIFY_EVENT" => "user_message_failed",
  314. "TO_USER_ID" => $messageFields['USER_ID'],
  315. "NOTIFY_MESSAGE" => Loc::getMessage("MAIL_USER_MESSAGE_FAILED", array(
  316. "#TITLE#" => $title
  317. ))
  318. ));
  319. }
  320. User\MessageTable::delete($messageId);
  321. return;
  322. }
  323. switch ($messageFields['TYPE'])
  324. {
  325. case 'rpl':
  326. $eventId = sprintf('onReplyReceived%s', $messageFields['ENTITY_TYPE']);
  327. break;
  328. case 'fwd':
  329. $eventId = sprintf('onForwardReceived%s', $messageFields['ENTITY_TYPE']);
  330. break;
  331. }
  332. if (!empty($eventId))
  333. {
  334. $attachments = array();
  335. if (!empty($messageFields['ATTACHMENTS']))
  336. {
  337. $tmpAttachments = unserialize($messageFields['ATTACHMENTS'], ['allowed_classes' => false]);
  338. if (is_array($tmpAttachments))
  339. {
  340. foreach($tmpAttachments as $key => $uploadFile)
  341. {
  342. $file = \CFile::makeFileArray($uploadFile);
  343. if (
  344. is_array($file)
  345. && !empty($file)
  346. )
  347. {
  348. $file['name'] = $key;
  349. $attachments[$key] = $file;
  350. }
  351. }
  352. }
  353. }
  354. $event = new Main\Event(
  355. 'mail', $eventId,
  356. array(
  357. 'site_id' => $messageFields['SITE_ID'],
  358. 'entity_id' => $messageFields['ENTITY_ID'],
  359. 'from' => $messageFields['USER_ID'],
  360. 'subject' => $messageFields['SUBJECT'],
  361. 'content' => $messageFields['CONTENT'],
  362. 'attachments' => $attachments
  363. )
  364. );
  365. $event->send();
  366. foreach ($event->getResults() as $eventResult)
  367. {
  368. if ($eventResult->getType() == \Bitrix\Main\EventResult::ERROR)
  369. {
  370. $cnt++;
  371. global $pPERIOD;
  372. $pPERIOD = 10 + (60 * $cnt);
  373. return "\\Bitrix\\Mail\\User::sendEventAgent(".$messageId.", ".$cnt.");";
  374. }
  375. }
  376. User\MessageTable::delete($messageId);
  377. }
  378. }
  379. return;
  380. }
  381. /**
  382. * Returns email users group
  383. *
  384. * @return array
  385. */
  386. public static function getMailUserGroup()
  387. {
  388. $res = array();
  389. $mailInvitedGroup = Main\Config\Option::get("mail", "mail_invited_group", false);
  390. if ($mailInvitedGroup)
  391. {
  392. $res[] = intval($mailInvitedGroup);
  393. }
  394. return $res;
  395. }
  396. public static function getDefaultEmailFrom($serverName = false)
  397. {
  398. if (Main\ModuleManager::isModuleInstalled('bitrix24') && defined("BX24_HOST_NAME"))
  399. {
  400. if(preg_match("/\\.bitrix24\\.([a-z]+|com\\.br)$/i", BX24_HOST_NAME))
  401. {
  402. $domain = BX24_HOST_NAME;
  403. }
  404. else
  405. {
  406. $domain = str_replace(".", "-", BX24_HOST_NAME).".bitrix24.com";
  407. }
  408. $defaultEmailFrom = "info@".$domain;
  409. }
  410. else
  411. {
  412. $defaultEmailFrom = Main\Config\Option::get('main', 'email_from', '');
  413. if ($defaultEmailFrom == '')
  414. {
  415. $defaultEmailFrom = "info@".($serverName ?: Main\Config\Option::get('main', 'server_name', $GLOBALS["SERVER_NAME"]));
  416. }
  417. }
  418. return $defaultEmailFrom;
  419. }
  420. public static function getUserData($userList, $nameTemplate)
  421. {
  422. $result = array();
  423. if (
  424. !is_array($userList)
  425. || empty($userList)
  426. )
  427. {
  428. return $result;
  429. }
  430. $filter = array(
  431. "ID" => $userList,
  432. "ACTIVE" => "Y",
  433. "=EXTERNAL_AUTH_ID" => 'email'
  434. );
  435. if (
  436. \IsModuleInstalled('intranet')
  437. || Main\Config\Option::get("main", "new_user_registration_email_confirmation", "N") == "Y"
  438. )
  439. {
  440. $filter["CONFIRM_CODE"] = false;
  441. }
  442. $res = \Bitrix\Main\UserTable::getList(array(
  443. 'order' => array(),
  444. 'filter' => $filter,
  445. 'select' => array("ID", "EMAIL", "NAME", "LAST_NAME", "SECOND_NAME", "LOGIN")
  446. ));
  447. while ($user = $res->fetch())
  448. {
  449. $result[$user["ID"]] = array(
  450. "NAME_FORMATTED" => (
  451. !empty($user["NAME"])
  452. || !empty($user["LAST_NAME"])
  453. ? \CUser::formatName($nameTemplate, $user)
  454. : ''
  455. ),
  456. "EMAIL" => $user["EMAIL"]
  457. );
  458. }
  459. return $result;
  460. }
  461. public static function handleSiteUpdate($fields)
  462. {
  463. if (array_key_exists('SERVER_NAME', $fields))
  464. {
  465. static::clearTokensCache();
  466. }
  467. }
  468. public static function handleServerNameUpdate()
  469. {
  470. static::clearTokensCache();
  471. }
  472. public static function clearTokensCache()
  473. {
  474. $cache = new \CPHPCache();
  475. $cache->cleanDir('/mail/user/forward');
  476. }
  477. }