PageRenderTime 64ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/code/classes/Daemon/PMaild/MTA/MailSolver.class.php

https://github.com/blekkzor/pinetd2
PHP | 164 lines | 129 code | 19 blank | 16 comment | 26 complexity | 7e5f93668a01ee23166c68ab2585d1f4 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. namespace Daemon\PMaild\MTA;
  3. use pinetd\SQL;
  4. class MailSolver {
  5. static protected function readAlias($SQL, $alias, $res) {
  6. $alias->last_transit = $SQL->now();
  7. $alias->commit();
  8. // determine case
  9. if (!is_null($alias->http_target)) {
  10. $res['type'] = 'http';
  11. $res['target'] = $alias->http_target;
  12. $res['on_error'] = $alias->mail_target; // if HTTP call fails, a mail is dispatched
  13. return $res;
  14. }
  15. if (!is_null($alias->mail_target)) {
  16. $target = $alias->mail_target;
  17. if ($target[0] == '@') $target = $user . $target;
  18. $res['type'] = 'redirect';
  19. $res['target'] = $target;
  20. return $res;
  21. }
  22. // CONTINUE HERE: load account referenced, and continue to next
  23. return $alias->real_target;
  24. }
  25. static protected function readList($SQL, $list, $res, $mode = 'message') {
  26. $list->last_transit = $SQL->now();
  27. $list->commit();
  28. $res['type'] = 'list';
  29. $res['target'] = $list->id;
  30. $res['list'] = $list;
  31. $res['mode'] = $mode;
  32. return $res;
  33. }
  34. static protected function getListName($name) {
  35. $pos = strrpos($name, '-');
  36. if ($pos === false) return false;
  37. $code = strtolower(substr($name, $pos+1));
  38. $name = substr($name, 0, $pos);
  39. switch($code) {
  40. case 'subscribe':
  41. case 'unsubscribe':
  42. return array($name, $code);
  43. }
  44. return false;
  45. }
  46. static public function solve($mail, &$localConfig) {
  47. $res = array();
  48. $res['mail'] = $mail;
  49. $res['received'] = array();
  50. $pos = strrpos($mail, '@');
  51. if ($pos === false) return false;
  52. $user = substr($mail, 0, $pos);
  53. $domainname = substr($mail, $pos+1);
  54. $res['mail_user'] = $user;
  55. $res['mail_domain'] = $domainname;
  56. $SQL = SQL::Factory($localConfig['Storage']);
  57. $DAO_domains = $SQL->DAO('domains', 'domainid');
  58. $domain = $DAO_domains->loadByField(array('domain' => $domainname));
  59. if (!$domain) {
  60. $DAO_domainaliases = $SQL->DAO('domainaliases', 'domain');
  61. $alias = $DAO_domainaliases[$domainname];
  62. if (!$alias) {
  63. // No domainalias, no domain, it's not someone from here
  64. $res['type'] = 'remote';
  65. $res['target'] = $res['mail'];
  66. return $res;
  67. }
  68. $domain = $DAO_domains[$alias->domainid];
  69. } else {
  70. $domain = $domain[0];
  71. }
  72. // fetch flags for this domain
  73. $flags = $domain->flags;
  74. $flags = array_flip(explode(',', $flags));
  75. // at this point we know we'll have a local delivery
  76. Storage::validateTables($SQL, $domain->domainid);
  77. $res['domainid'] = $domain->domainid;
  78. $res['domainbean'] = $domain;
  79. if (isset($flags['account_without_plus_symbol'])) {
  80. // emails on this domain can't contain a "+" symbol. It is used to add extra data
  81. list($user) = explode('+', $user);
  82. }
  83. // spawn this domain's DAO
  84. $DAO_accounts = $SQL->DAO('z'.$domain->domainid.'_accounts', 'id');
  85. $DAO_alias = $SQL->DAO('z'.$domain->domainid.'_alias', 'id');
  86. $DAO_lists = $SQL->DAO('z'.$domain->domainid.'_lists', 'id');
  87. // first, locate an alias...
  88. $alias = $DAO_alias->loadByField(array('user'=>$user));
  89. if ($alias) {
  90. $aliasres = self::readAlias($SQL, $alias[0], $res);
  91. if (is_array($aliasres)) return $aliasres;
  92. $account = $DAO_accounts[$aliasres];
  93. // CONTINUE HERE: load account referenced, and continue to next
  94. } else {
  95. // load mailing list
  96. $list = $DAO_lists->loadByField(array('user'=>$user));
  97. if ($list) {
  98. return self::readList($SQL, $list[0], $res);
  99. } else {
  100. // Load account
  101. $account = $DAO_accounts->loadByField(array('user' => $user));
  102. }
  103. }
  104. if (!$account) {
  105. // check for special list cases
  106. $list_name = self::getListName($user);
  107. if ($list_name) {
  108. $list = $DAO_lists->loadByField(array('user'=>$list_name[0]));
  109. if ($list) {
  110. $list = $list[0];
  111. if ($list->allow_subscribe == 'Y') {
  112. return self::readList($SQL, $list, $res, $list_name[1]);
  113. }
  114. }
  115. }
  116. // check for 'default' alias
  117. $alias = $DAO_alias->loadByField(array('user'=>'default'));
  118. if ($alias) {
  119. $aliasres = self::readAlias($SQL, $alias[0], $res);
  120. if (is_array($aliasres)) return $aliasres;
  121. $account = $DAO_accounts[$aliasres];
  122. }
  123. // check if we should "create account on mail"
  124. if (isset($flags['create_account_on_mail'])) {
  125. // Let's create an empty account
  126. $DAO_accounts->insertValues(array('user' => $user, 'password' => NULL));
  127. $account = $DAO_accounts->loadByField(array('user' => $user));
  128. }
  129. if (!$account)
  130. return '503 5.1.1 Mailbox not found';
  131. }
  132. // check if we got an account list, or just one account
  133. if (is_array($account))
  134. $account = $account[0];
  135. if (!is_null($account->redirect)) {
  136. $res['type'] = 'redirect';
  137. $res['target'] = $account->redirect;
  138. return $res;
  139. }
  140. $res['type'] = 'local';
  141. $res['target'] = $account->id;
  142. $res['target_mail'] = $account->user.'@'.$domain->domain;
  143. return $res;
  144. }
  145. }