SMAILSvr.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:59k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "SList.h"
  26. #include "ShBlocks.h"
  27. #include "StrUtils.h"
  28. #include "BuffSock.h"
  29. #include "MiscUtils.h"
  30. #include "ResLocks.h"
  31. #include "BuffSock.h"
  32. #include "SvrUtils.h"
  33. #include "UsrUtils.h"
  34. #include "MessQueue.h"
  35. #include "SMAILUtils.h"
  36. #include "QueueUtils.h"
  37. #include "MailDomains.h"
  38. #include "SMTPUtils.h"
  39. #include "ExtAliases.h"
  40. #include "UsrMailList.h"
  41. #include "Filter.h"
  42. #include "MailConfig.h"
  43. #include "SMAILSvr.h"
  44. #include "AppDefines.h"
  45. #include "MailSvr.h"
  46. #define SMAIL_WAITMSG_TIMEOUT       2
  47. #define CUSTOM_PROC_LINE_MAX        1024
  48. #define SMAIL_EXTERNAL_EXIT_BREAK   16
  49. #define SMAIL_STOP_PROCESSING       3111965L
  50. static SMAILConfig *SMAILGetConfigCopy(SHB_HANDLE hShbSMAIL);
  51. static int SMAILThreadCountAdd(long lCount, SHB_HANDLE hShbSMAIL, SMAILConfig * pSMAILCfg = NULL);
  52. static int SMAILLogEnabled(SHB_HANDLE hShbSMAIL, SMAILConfig * pSMAILCfg = NULL);
  53. static int SMAILHandleResendNotify(SVRCFG_HANDLE hSvrConfig, QUEUE_HANDLE hQueue,
  54.    QMSG_HANDLE hMessage, SPLF_HANDLE hFSpool);
  55. static int SMAILTryProcessMessage(SVRCFG_HANDLE hSvrConfig, QUEUE_HANDLE hQueue,
  56.   QMSG_HANDLE hMessage, SHB_HANDLE hShbSMAIL,
  57.   SMAILConfig * pSMAILCfg);
  58. static int SMAILTryProcessSpool(SHB_HANDLE hShbSMAIL);
  59. static int SMAILProcessFile(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  60.     SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  61. static int SMAILMailingListExplode(UserInfo * pUI, SPLF_HANDLE hFSpool);
  62. static int SMAILRemoteMsgSMTPSend(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  63.   SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
  64.   char const *pszDestDomain, SMTPError * pSMTPE = NULL);
  65. static int SMAILHandleRemoteUserMessage(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  66. SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  67. QMSG_HANDLE hMessage, char const *pszDestDomain,
  68. char const *pszDestUser);
  69. static int SMAILCustomProcessMessage(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  70.      SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  71.      QMSG_HANDLE hMessage, char const *pszDestDomain,
  72.      char const *pszDestUser, char const *pszCustFilePath);
  73. static int SMAILCmdMacroSubstitutes(char **ppszCmdTokens, SPLF_HANDLE hFSpool);
  74. static int SMAILCmd_external(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  75.      char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  76.      SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  77. static int SMAILCmd_filter(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  78.    char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  79.    SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  80. static int SMAILCmd_smtp(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  81.  char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  82.  SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  83. static int SMAILCmd_smtprelay(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  84.       char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  85.       SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  86. static int SMAILCmd_redirect(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  87.      char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  88.      SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  89. static int SMAILCmd_lredirect(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  90.       char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  91.       SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage);
  92. static SMAILConfig *SMAILGetConfigCopy(SHB_HANDLE hShbSMAIL)
  93. {
  94. SMAILConfig *pLMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
  95. if (pLMAILCfg == NULL)
  96. return (NULL);
  97. SMAILConfig *pNewLMAILCfg = (SMAILConfig *) SysAlloc(sizeof(SMAILConfig));
  98. if (pNewLMAILCfg != NULL)
  99. memcpy(pNewLMAILCfg, pLMAILCfg, sizeof(SMAILConfig));
  100. ShbUnlock(hShbSMAIL);
  101. return (pNewLMAILCfg);
  102. }
  103. static int SMAILThreadCountAdd(long lCount, SHB_HANDLE hShbSMAIL, SMAILConfig * pSMAILCfg)
  104. {
  105. int iDoUnlock = 0;
  106. if (pSMAILCfg == NULL) {
  107. if ((pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL)) == NULL)
  108. return (ErrGetErrorCode());
  109. ++iDoUnlock;
  110. }
  111. pSMAILCfg->lThreadCount += lCount;
  112. if (iDoUnlock)
  113. ShbUnlock(hShbSMAIL);
  114. return (0);
  115. }
  116. static int SMAILLogEnabled(SHB_HANDLE hShbSMAIL, SMAILConfig * pSMAILCfg)
  117. {
  118. int iDoUnlock = 0;
  119. if (pSMAILCfg == NULL) {
  120. if ((pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL)) == NULL)
  121. return (ErrGetErrorCode());
  122. ++iDoUnlock;
  123. }
  124. unsigned long ulFlags = pSMAILCfg->ulFlags;
  125. if (iDoUnlock)
  126. ShbUnlock(hShbSMAIL);
  127. return ((ulFlags & SMAILF_LOG_ENABLED) ? 1 : 0);
  128. }
  129. unsigned int SMAILThreadProc(void *pThreadData)
  130. {
  131. SMAILConfig *pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
  132. if (pSMAILCfg == NULL) {
  133. ErrorPush();
  134. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  135. return (ErrorPop());
  136. }
  137. ///////////////////////////////////////////////////////////////////////////////
  138. //  Get thread id
  139. ///////////////////////////////////////////////////////////////////////////////
  140. long lThreadId = pSMAILCfg->lThreadCount;
  141. ///////////////////////////////////////////////////////////////////////////////
  142. //  Increase thread count
  143. ///////////////////////////////////////////////////////////////////////////////
  144. SMAILThreadCountAdd(+1, hShbSMAIL, pSMAILCfg);
  145. ShbUnlock(hShbSMAIL);
  146. SysLogMessage(LOG_LEV_MESSAGE, "SMAIL thread [%02ld] startedn", lThreadId);
  147. for (;;) {
  148. ///////////////////////////////////////////////////////////////////////////////
  149. //  Check shutdown condition
  150. ///////////////////////////////////////////////////////////////////////////////
  151. pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
  152. if ((pSMAILCfg == NULL) || (pSMAILCfg->ulFlags & SMAILF_STOP_SERVER)) {
  153. SysLogMessage(LOG_LEV_MESSAGE, "SMAIL thread [%02ld] exitingn",
  154.       lThreadId);
  155. if (pSMAILCfg != NULL)
  156. ShbUnlock(hShbSMAIL);
  157. break;
  158. }
  159. ShbUnlock(hShbSMAIL);
  160. ///////////////////////////////////////////////////////////////////////////////
  161. //  Process spool files
  162. ///////////////////////////////////////////////////////////////////////////////
  163. SMAILTryProcessSpool(hShbSMAIL);
  164. }
  165. ///////////////////////////////////////////////////////////////////////////////
  166. //  Decrease thread count
  167. ///////////////////////////////////////////////////////////////////////////////
  168. SMAILThreadCountAdd(-1, hShbSMAIL);
  169. SysLogMessage(LOG_LEV_MESSAGE, "SMAIL thread [%02ld] stoppedn", lThreadId);
  170. return (0);
  171. }
  172. static int SMAILHandleResendNotify(SVRCFG_HANDLE hSvrConfig, QUEUE_HANDLE hQueue,
  173.    QMSG_HANDLE hMessage, SPLF_HANDLE hFSpool)
  174. {
  175. ///////////////////////////////////////////////////////////////////////////////
  176. //  Check if it's time to notify about a failed delivery attempt
  177. ///////////////////////////////////////////////////////////////////////////////
  178. int iRetryCount = QueGetTryCount(hMessage);
  179. char szNotifyPattern[128] = "";
  180. SvrConfigVar("NotifyTryPattern", szNotifyPattern, sizeof(szNotifyPattern) - 1, hSvrConfig,
  181.      "");
  182. for (char *pszTry = szNotifyPattern; pszTry != NULL; ++pszTry) {
  183. if (isdigit(*pszTry) && (atoi(pszTry) == iRetryCount))
  184. break;
  185. if ((pszTry = strchr(pszTry, ',')) == NULL)
  186. return (0);
  187. }
  188. ///////////////////////////////////////////////////////////////////////////////
  189. //  Build the notification text and send the message
  190. ///////////////////////////////////////////////////////////////////////////////
  191. time_t tLastTry = QueGetLastTryTime(hMessage);
  192. time_t tNextTry = QueGetMessageNextOp(hQueue, hMessage);
  193. char szTimeLast[128] = "";
  194. char szTimeNext[128] = "";
  195. MscGetTimeStr(szTimeLast, sizeof(szTimeLast) - 1, tLastTry);
  196. MscGetTimeStr(szTimeNext, sizeof(szTimeNext) - 1, tNextTry);
  197. char *pszText =
  198.     StrSprint("** This is a temporary error and you do not have to resend the messagern"
  199.       "** The system tried to send the message at      : %srn"
  200.       "** The current number of delivery attempts is   : %drn"
  201.       "** The system will try to resend the message at : %srn",
  202.       szTimeLast, iRetryCount, szTimeNext);
  203. if (pszText == NULL)
  204. return (ErrGetErrorCode());
  205. int iNotifyResult = QueUtNotifyTempErrDelivery(hQueue, hMessage, hFSpool,
  206.        NULL, pszText, NULL);
  207. SysFree(pszText);
  208. return (iNotifyResult);
  209. }
  210. static int SMAILTryProcessMessage(SVRCFG_HANDLE hSvrConfig, QUEUE_HANDLE hQueue,
  211.   QMSG_HANDLE hMessage, SHB_HANDLE hShbSMAIL,
  212.   SMAILConfig * pSMAILCfg)
  213. {
  214. ///////////////////////////////////////////////////////////////////////////////
  215. //  Create the handle to manage the queue file
  216. ///////////////////////////////////////////////////////////////////////////////
  217. char szMessFilePath[SYS_MAX_PATH] = "";
  218. QueGetFilePath(hQueue, hMessage, szMessFilePath);
  219. SPLF_HANDLE hFSpool = USmlCreateHandle(szMessFilePath);
  220. if (hFSpool == INVALID_SPLF_HANDLE) {
  221. ErrorPush();
  222. ErrLogMessage(LOG_LEV_ERROR,
  223.       "Unable to load spool file "%s"n"
  224.       "%s = "%s"n",
  225.       szMessFilePath, SMTP_ERROR_VARNAME, "554 Error loading spool file");
  226. QueUtErrLogMessage(hQueue, hMessage,
  227.    "Unable to load spool file "%s"n"
  228.    "%s = "%s"n",
  229.    szMessFilePath, SMTP_ERROR_VARNAME,
  230.    "554 Error loading spool file");
  231. QueUtCleanupNotifyRoot(hQueue, hMessage, INVALID_SPLF_HANDLE,
  232.        ErrGetErrorString(ErrorFetch()));
  233. QueCloseMessage(hQueue, hMessage);
  234. return (ErrorPop());
  235. }
  236. ///////////////////////////////////////////////////////////////////////////////
  237. //  Check for mail loops
  238. ///////////////////////////////////////////////////////////////////////////////
  239. if (USmlMailLoopCheck(hFSpool, hSvrConfig) < 0) {
  240. ErrorPush();
  241. ///////////////////////////////////////////////////////////////////////////////
  242. //  Notify root and remove the message
  243. ///////////////////////////////////////////////////////////////////////////////
  244. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  245. ErrLogMessage(LOG_LEV_ERROR,
  246.       "Message <%s> blocked by mail loop check !n"
  247.       "%s = "%s"n",
  248.       pszSmtpMessageID, SMTP_ERROR_VARNAME,
  249.       "554 Message blocked by mail loop check");
  250. QueUtErrLogMessage(hQueue, hMessage,
  251.    "Message <%s> blocked by mail loop check !n"
  252.    "%s = "%s"n",
  253.    pszSmtpMessageID, SMTP_ERROR_VARNAME,
  254.    "554 Message blocked by mail loop check");
  255. QueUtCleanupNotifyRoot(hQueue, hMessage, hFSpool,
  256.        ErrGetErrorString(ErrorFetch()));
  257. USmlCloseHandle(hFSpool);
  258. QueCloseMessage(hQueue, hMessage);
  259. return (ErrorPop());
  260. }
  261. ///////////////////////////////////////////////////////////////////////////////
  262. //  Process queue file
  263. ///////////////////////////////////////////////////////////////////////////////
  264. if (SMAILProcessFile(hSvrConfig, hShbSMAIL, hFSpool, hQueue, hMessage) < 0) {
  265. ErrorPush();
  266. ///////////////////////////////////////////////////////////////////////////////
  267. //  Resend the message if it's not been cleaned up
  268. ///////////////////////////////////////////////////////////////////////////////
  269. if (QueCheckMessage(hQueue, hMessage) == 0) {
  270. USmlSyncChanges(hFSpool);
  271. ///////////////////////////////////////////////////////////////////////////////
  272. //  Handle resend notifications
  273. ///////////////////////////////////////////////////////////////////////////////
  274. SMAILHandleResendNotify(hSvrConfig, hQueue, hMessage, hFSpool);
  275. ///////////////////////////////////////////////////////////////////////////////
  276. //  Resend the message
  277. ///////////////////////////////////////////////////////////////////////////////
  278. QueUtResendMessage(hQueue, hMessage, hFSpool);
  279. } else
  280. QueCloseMessage(hQueue, hMessage);
  281. USmlCloseHandle(hFSpool);
  282. return (ErrorPop());
  283. }
  284. USmlCloseHandle(hFSpool);
  285. ///////////////////////////////////////////////////////////////////////////////
  286. //  Cleanup message
  287. ///////////////////////////////////////////////////////////////////////////////
  288. QueCleanupMessage(hQueue, hMessage);
  289. QueCloseMessage(hQueue, hMessage);
  290. return (0);
  291. }
  292. static int SMAILTryProcessSpool(SHB_HANDLE hShbSMAIL)
  293. {
  294. SMAILConfig *pSMAILCfg = SMAILGetConfigCopy(hShbSMAIL);
  295. if (pSMAILCfg == NULL) {
  296. ErrorPush();
  297. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  298. return (ErrorPop());
  299. }
  300. ///////////////////////////////////////////////////////////////////////////////
  301. //  Get queue file to process
  302. ///////////////////////////////////////////////////////////////////////////////
  303. QMSG_HANDLE hMessage = QueExtractMessage(hSpoolQueue, SMAIL_WAITMSG_TIMEOUT);
  304. if (hMessage != INVALID_QMSG_HANDLE) {
  305. ///////////////////////////////////////////////////////////////////////////////
  306. //  Get configuration handle
  307. ///////////////////////////////////////////////////////////////////////////////
  308. SVRCFG_HANDLE hSvrConfig = SvrGetConfigHandle();
  309. if (hSvrConfig == INVALID_SVRCFG_HANDLE) {
  310. ErrorPush();
  311. ErrLogMessage(LOG_LEV_ERROR,
  312.       "Unable to load server configuration filen"
  313.       "%s = "%s"n", SMTP_ERROR_VARNAME,
  314.       "417 Unable to load server configuration file");
  315. QueUtErrLogMessage(hSpoolQueue, hMessage,
  316.    "Unable to load server configuration filen"
  317.    "%s = "%s"n", SMTP_ERROR_VARNAME,
  318.    "417 Unable to load server configuration file");
  319. QueUtResendMessage(hSpoolQueue, hMessage, NULL);
  320. SysFree(pSMAILCfg);
  321. return (ErrorPop());
  322. }
  323. ///////////////////////////////////////////////////////////////////////////////
  324. //  Process queue file
  325. ///////////////////////////////////////////////////////////////////////////////
  326. SMAILTryProcessMessage(hSvrConfig, hSpoolQueue, hMessage, hShbSMAIL, pSMAILCfg);
  327. SvrReleaseConfigHandle(hSvrConfig);
  328. }
  329. SysFree(pSMAILCfg);
  330. return (0);
  331. }
  332. static int SMAILProcessFile(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  333.     SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  334. {
  335. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  336. int iRcptDomains = StrStringsCount(ppszRcpt);
  337. char szDestUser[MAX_ADDR_NAME] = "";
  338. char szDestDomain[MAX_ADDR_NAME] = "";
  339. char szAliasFilePath[SYS_MAX_PATH] = "";
  340. if (iRcptDomains < 1) {
  341. ErrSetErrorCode(ERR_BAD_EMAIL_ADDR);
  342. return (ERR_BAD_EMAIL_ADDR);
  343. }
  344. ///////////////////////////////////////////////////////////////////////////////
  345. //  We can have two cases here. The recipient is a simple one, or it has an
  346. //  explicit routing (@dom1,@dom2:usr@dom).
  347. ///////////////////////////////////////////////////////////////////////////////
  348. if (iRcptDomains == 1) {
  349. if (USmtpSplitEmailAddr(ppszRcpt[0], szDestUser, szDestDomain) < 0)
  350. return (ErrGetErrorCode());
  351. } else if (USmtpSplitEmailAddr(ppszRcpt[0], NULL, szDestDomain) < 0)
  352. return (ErrGetErrorCode());
  353. ///////////////////////////////////////////////////////////////////////////////
  354. //  Is the target handled with cmdalias ?
  355. ///////////////////////////////////////////////////////////////////////////////
  356. if (USmlGetCmdAliasCustomFile(hFSpool, hQueue, hMessage, szDestDomain,
  357.       szDestUser, szAliasFilePath) == 0) {
  358. ///////////////////////////////////////////////////////////////////////////////
  359. //  Do cmd alias processing
  360. ///////////////////////////////////////////////////////////////////////////////
  361. if (SMAILCustomProcessMessage(hSvrConfig, hShbSMAIL, hFSpool, hQueue, hMessage,
  362.       szDestDomain, szDestUser, szAliasFilePath) < 0)
  363. return (ErrGetErrorCode());
  364. }
  365. ///////////////////////////////////////////////////////////////////////////////
  366. //  Check if we are at home
  367. ///////////////////////////////////////////////////////////////////////////////
  368. else if (MDomIsHandledDomain(szDestDomain) == 0) {
  369. UserInfo *pUI = UsrGetUserByNameOrAlias(szDestDomain, szDestUser);
  370. if (pUI != NULL) {
  371. SysLogMessage(LOG_LEV_MESSAGE,
  372.       "SMAIL local SMTP = "%s" From = <%s> To = <%s>n",
  373.       USmlGetSMTPDomain(hFSpool), USmlMailFrom(hFSpool),
  374.       ppszRcpt[0]);
  375. if (UsrGetUserType(pUI) == usrTypeUser) {
  376. ///////////////////////////////////////////////////////////////////////////////
  377. //  Local user case
  378. ///////////////////////////////////////////////////////////////////////////////
  379. LocalMailProcConfig LMPC;
  380. ZeroData(LMPC);
  381. LMPC.ulFlags =
  382. (SMAILLogEnabled(hShbSMAIL)) ? LMPCF_LOG_ENABLED : 0;
  383. if (USmlProcessLocalUserMessage
  384.     (hSvrConfig, pUI, hFSpool, hQueue, hMessage, LMPC) < 0) {
  385. ErrorPush();
  386. UsrFreeUserInfo(pUI);
  387. return (ErrorPop());
  388. }
  389. } else {
  390. ///////////////////////////////////////////////////////////////////////////////
  391. //  Apply filters ...
  392. ///////////////////////////////////////////////////////////////////////////////
  393. if (FilFilterMessage
  394.     (hFSpool, hQueue, hMessage, FILTER_MODE_INBOUND) < 0) {
  395. ErrorPush();
  396. UsrFreeUserInfo(pUI);
  397. return (ErrorPop());
  398. }
  399. ///////////////////////////////////////////////////////////////////////////////
  400. //  Local mailing list case
  401. ///////////////////////////////////////////////////////////////////////////////
  402. if (SMAILMailingListExplode(pUI, hFSpool) < 0) {
  403. ErrorPush();
  404. UsrFreeUserInfo(pUI);
  405. return (ErrorPop());
  406. }
  407. }
  408. UsrFreeUserInfo(pUI);
  409. } else {
  410. ErrorPush();
  411. ///////////////////////////////////////////////////////////////////////////////
  412. //  No account inside the handled domain
  413. ///////////////////////////////////////////////////////////////////////////////
  414. char szBounceMsg[512] = "";
  415. SysSNPrintf(szBounceMsg, sizeof(szBounceMsg) - 1,
  416.     "Unknown user "%s" in domain "%s"", szDestUser,
  417.     szDestDomain);
  418. QueUtErrLogMessage(hQueue, hMessage, "%sn", szBounceMsg);
  419. QueUtNotifyPermErrDelivery(hQueue, hMessage, hFSpool, szBounceMsg, NULL,
  420.    true);
  421. return (ErrorPop());
  422. }
  423. } else {
  424. ///////////////////////////////////////////////////////////////////////////////
  425. //  Remote user case ( or custom domain user )
  426. ///////////////////////////////////////////////////////////////////////////////
  427. if (SMAILHandleRemoteUserMessage(hSvrConfig, hShbSMAIL, hFSpool,
  428.  hQueue, hMessage, szDestDomain, szDestUser) < 0)
  429. return (ErrGetErrorCode());
  430. }
  431. return (0);
  432. }
  433. static int SMAILMailingListExplode(UserInfo * pUI, SPLF_HANDLE hFSpool)
  434. {
  435. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  436. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  437. char szDestUser[MAX_ADDR_NAME] = "";
  438. char szDestDomain[MAX_ADDR_NAME] = "";
  439. if (USmtpSplitEmailAddr(ppszRcpt[0], szDestUser, szDestDomain) < 0)
  440. return (ErrGetErrorCode());
  441. ///////////////////////////////////////////////////////////////////////////////
  442. //  Get Mailing List Sender address. If this account variable does not exist
  443. //  the sender will be the "real" message sender
  444. ///////////////////////////////////////////////////////////////////////////////
  445. char *pszMLSender = UsrGetUserInfoVar(pUI, "ListSender");
  446. ///////////////////////////////////////////////////////////////////////////////
  447. //  Check if the use of the Reply-To: is requested
  448. ///////////////////////////////////////////////////////////////////////////////
  449. int iUseReplyTo = UsrGetUserInfoVarInt(pUI, "UseReplyTo", 1);
  450. USRML_HANDLE hUsersDB = UsrMLOpenDB(pUI);
  451. if (hUsersDB == INVALID_USRML_HANDLE) {
  452. ErrorPush();
  453. SysFreeCheck(pszMLSender);
  454. return (ErrorPop());
  455. }
  456. ///////////////////////////////////////////////////////////////////////////////
  457. //  Mailing list scan
  458. ///////////////////////////////////////////////////////////////////////////////
  459. MLUserInfo *pMLUI = UsrMLGetFirstUser(hUsersDB);
  460. for (; pMLUI != NULL; pMLUI = UsrMLGetNextUser(hUsersDB)) {
  461. if (strchr(pMLUI->pszPerms, 'R') != NULL) {
  462. ///////////////////////////////////////////////////////////////////////////////
  463. //  Get message handle
  464. ///////////////////////////////////////////////////////////////////////////////
  465. QMSG_HANDLE hMessage = QueCreateMessage(hSpoolQueue);
  466. if (hMessage == INVALID_QMSG_HANDLE) {
  467. ErrorPush();
  468. SysFreeCheck(pszMLSender);
  469. UsrMLFreeUser(pMLUI);
  470. UsrMLCloseDB(hUsersDB);
  471. return (ErrorPop());
  472. }
  473. char szQueueFilePath[SYS_MAX_PATH] = "";
  474. QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
  475. ///////////////////////////////////////////////////////////////////////////////
  476. //  Create spool file. If "pszMLSender" is NULL the original sender is kept
  477. ///////////////////////////////////////////////////////////////////////////////
  478. if (USmlCreateSpoolFile
  479.     (hFSpool, pszMLSender, pMLUI->pszAddress, szQueueFilePath,
  480.      (iUseReplyTo != 0) ? "Reply-To" : "", ppszRcpt[0], NULL) < 0) {
  481. ErrorPush();
  482. QueCleanupMessage(hSpoolQueue, hMessage);
  483. QueCloseMessage(hSpoolQueue, hMessage);
  484. SysFreeCheck(pszMLSender);
  485. UsrMLFreeUser(pMLUI);
  486. UsrMLCloseDB(hUsersDB);
  487. return (ErrorPop());
  488. }
  489. ///////////////////////////////////////////////////////////////////////////////
  490. //  Transfer file to the spool
  491. ///////////////////////////////////////////////////////////////////////////////
  492. if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
  493. ErrorPush();
  494. QueCleanupMessage(hSpoolQueue, hMessage);
  495. QueCloseMessage(hSpoolQueue, hMessage);
  496. SysFreeCheck(pszMLSender);
  497. UsrMLFreeUser(pMLUI);
  498. UsrMLCloseDB(hUsersDB);
  499. return (ErrorPop());
  500. }
  501. }
  502. UsrMLFreeUser(pMLUI);
  503. }
  504. UsrMLCloseDB(hUsersDB);
  505. SysFreeCheck(pszMLSender);
  506. return (0);
  507. }
  508. static int SMAILRemoteMsgSMTPSend(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  509.   SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
  510.   char const *pszDestDomain, SMTPError * pSMTPE)
  511. {
  512. ///////////////////////////////////////////////////////////////////////////////
  513. //  Apply filters ...
  514. ///////////////////////////////////////////////////////////////////////////////
  515. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_OUTBOUND) < 0)
  516. return (ErrGetErrorCode());
  517. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  518. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  519. char const *pszSpoolFile = USmlGetSpoolFile(hFSpool);
  520. char const *pszSpoolFilePath = USmlGetSpoolFilePath(hFSpool);
  521. char const *pszMailFrom = USmlMailFrom(hFSpool);
  522. char const *pszSendMailFrom = USmlSendMailFrom(hFSpool);
  523. char const *pszRcptTo = USmlRcptTo(hFSpool);
  524. char const *pszSendRcptTo = USmlSendRcptTo(hFSpool);
  525. char const *pszRelayDomain = USmlGetRelayDomain(hFSpool);
  526. FileSection FS;
  527. ///////////////////////////////////////////////////////////////////////////////
  528. //  This function retrieve the spool file message section and sync the content.
  529. //  This is necessary before sending the file
  530. ///////////////////////////////////////////////////////////////////////////////
  531. if (USmlGetMsgFileSection(hFSpool, FS) < 0)
  532. return (ErrGetErrorCode());
  533. ///////////////////////////////////////////////////////////////////////////////
  534. //  Get HELO domain
  535. ///////////////////////////////////////////////////////////////////////////////
  536. char szHeloDomain[MAX_HOST_NAME] = "";
  537. SvrConfigVar("HeloDomain", szHeloDomain, sizeof(szHeloDomain) - 1, hSvrConfig, "");
  538. char const *pszHeloDomain = IsEmptyString(szHeloDomain) ? NULL : szHeloDomain;
  539. ///////////////////////////////////////////////////////////////////////////////
  540. //  If it's a relayed message use the associated relay
  541. ///////////////////////////////////////////////////////////////////////////////
  542. if (pszRelayDomain != NULL) {
  543. SysLogMessage(LOG_LEV_MESSAGE,
  544.       "SMAIL SMTP-Send CMX = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  545.       pszRelayDomain, pszSMTPDomain, pszMailFrom, pszRcptTo);
  546. if (pSMTPE != NULL)
  547. USmtpCleanupError(pSMTPE);
  548. if (USmtpSendMail(pszRelayDomain, pszHeloDomain, pszSendMailFrom, pszSendRcptTo,
  549.   &FS, pSMTPE) < 0) {
  550. ErrorPush();
  551. char szSmtpError[512] = "";
  552. USmtpGetSMTPError(pSMTPE, szSmtpError, sizeof(szSmtpError));
  553. ErrLogMessage(LOG_LEV_MESSAGE,
  554.       "SMAIL SMTP-Send CMX = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  555.       "%s = "%s"n"
  556.       "%s = "%s"n", pszRelayDomain, pszSMTPDomain, pszMailFrom,
  557.       pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError,
  558.       SMTP_SERVER_VARNAME, USmtpGetErrorServer(pSMTPE));
  559. QueUtErrLogMessage(hQueue, hMessage,
  560.    "SMAIL SMTP-Send CMX = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  561.    "%s = "%s"n"
  562.    "%s = "%s"n", pszRelayDomain, pszSMTPDomain,
  563.    pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  564.    szSmtpError, SMTP_SERVER_VARNAME,
  565.    USmtpGetErrorServer(pSMTPE));
  566. return (ErrorPop());
  567. }
  568. if (SMAILLogEnabled(hShbSMAIL))
  569. USmlLogMessage(hFSpool, "SMTP", pszRelayDomain);
  570. return (0);
  571. }
  572. ///////////////////////////////////////////////////////////////////////////////
  573. //  Check the existance of direct SMTP forwarders
  574. ///////////////////////////////////////////////////////////////////////////////
  575. char **ppszFwdGws = USmtpGetFwdGateways(hSvrConfig, pszDestDomain);
  576. if (ppszFwdGws != NULL) {
  577. ///////////////////////////////////////////////////////////////////////////////
  578. //  By initializing this to zero makes XMail to discharge all mail for domains
  579. //  that have an empty forwarders list
  580. ///////////////////////////////////////////////////////////////////////////////
  581. int iSendErrorCode = 0;
  582. for (int ss = 0; ppszFwdGws[ss] != NULL; ss++) {
  583. SysLogMessage(LOG_LEV_MESSAGE,
  584.       "SMAIL SMTP-Send FWD = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  585.       ppszFwdGws[ss], pszSMTPDomain, pszMailFrom, pszRcptTo);
  586. if (pSMTPE != NULL)
  587. USmtpCleanupError(pSMTPE);
  588. if ((iSendErrorCode = USmtpSendMail(ppszFwdGws[ss], pszHeloDomain,
  589.     pszSendMailFrom, pszSendRcptTo, &FS,
  590.     pSMTPE)) == 0) {
  591. ///////////////////////////////////////////////////////////////////////////////
  592. //  Log Mailer operation
  593. ///////////////////////////////////////////////////////////////////////////////
  594. if (SMAILLogEnabled(hShbSMAIL))
  595. USmlLogMessage(hFSpool, "FWD", ppszFwdGws[ss]);
  596. break;
  597. }
  598. char szSmtpError[512] = "";
  599. USmtpGetSMTPError(pSMTPE, szSmtpError, sizeof(szSmtpError));
  600. ErrLogMessage(LOG_LEV_MESSAGE,
  601.       "SMAIL SMTP-Send FWD = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  602.       "%s = "%s"n"
  603.       "%s = "%s"n", ppszFwdGws[ss], pszSMTPDomain, pszMailFrom,
  604.       pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError,
  605.       SMTP_SERVER_VARNAME, USmtpGetErrorServer(pSMTPE));
  606. QueUtErrLogMessage(hQueue, hMessage,
  607.    "SMAIL SMTP-Send FWD = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  608.    "%s = "%s"n"
  609.    "%s = "%s"n", ppszFwdGws[ss], pszSMTPDomain,
  610.    pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  611.    szSmtpError, SMTP_SERVER_VARNAME,
  612.    USmtpGetErrorServer(pSMTPE));
  613. if ((pSMTPE != NULL) && USmtpIsFatalError(pSMTPE))
  614. break;
  615. }
  616. StrFreeStrings(ppszFwdGws);
  617. return (iSendErrorCode);
  618. }
  619. ///////////////////////////////////////////////////////////////////////////////
  620. //  Try to get custom mail exchangers or DNS mail exchangers and if both tests
  621. //  fails try direct
  622. ///////////////////////////////////////////////////////////////////////////////
  623. char **ppszMXGWs = USmtpGetMailExchangers(hSvrConfig, pszDestDomain);
  624. if (ppszMXGWs == NULL) {
  625. char szDomainMXHost[256] = "";
  626. MXS_HANDLE hMXSHandle = USmtpGetMXFirst(hSvrConfig, pszDestDomain,
  627. szDomainMXHost);
  628. if (hMXSHandle != INVALID_MXS_HANDLE) {
  629. int iSendErrorCode = 0;
  630. do {
  631. SysLogMessage(LOG_LEV_MESSAGE,
  632.       "SMAIL SMTP-Send MX = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  633.       szDomainMXHost, pszSMTPDomain, pszMailFrom,
  634.       pszRcptTo);
  635. if (pSMTPE != NULL)
  636. USmtpCleanupError(pSMTPE);
  637. if ((iSendErrorCode = USmtpSendMail(szDomainMXHost, pszHeloDomain,
  638.     pszSendMailFrom,
  639.     pszSendRcptTo, &FS,
  640.     pSMTPE)) == 0) {
  641. ///////////////////////////////////////////////////////////////////////////////
  642. //  Log Mailer operation
  643. ///////////////////////////////////////////////////////////////////////////////
  644. if (SMAILLogEnabled(hShbSMAIL))
  645. USmlLogMessage(hFSpool, "SMTP", szDomainMXHost);
  646. break;
  647. }
  648. char szSmtpError[512] = "";
  649. USmtpGetSMTPError(pSMTPE, szSmtpError, sizeof(szSmtpError));
  650. ErrLogMessage(LOG_LEV_MESSAGE,
  651.       "SMAIL SMTP-Send MX = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  652.       "%s = "%s"n"
  653.       "%s = "%s"n", szDomainMXHost, pszSMTPDomain,
  654.       pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  655.       szSmtpError, SMTP_SERVER_VARNAME,
  656.       USmtpGetErrorServer(pSMTPE));
  657. QueUtErrLogMessage(hQueue, hMessage,
  658.    "SMAIL SMTP-Send MX = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  659.    "%s = "%s"n"
  660.    "%s = "%s"n", szDomainMXHost, pszSMTPDomain,
  661.    pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  662.    szSmtpError, SMTP_SERVER_VARNAME,
  663.    USmtpGetErrorServer(pSMTPE));
  664. if ((pSMTPE != NULL) && USmtpIsFatalError(pSMTPE))
  665. break;
  666. } while (USmtpGetMXNext(hMXSHandle, szDomainMXHost) == 0);
  667. USmtpMXSClose(hMXSHandle);
  668. if (iSendErrorCode < 0)
  669. return (iSendErrorCode);
  670. } else {
  671. ///////////////////////////////////////////////////////////////////////////////
  672. //  MX records for destination domain not found, try direct !
  673. ///////////////////////////////////////////////////////////////////////////////
  674. SysLogMessage(LOG_LEV_MESSAGE,
  675.       "MX records for domain "%s" not found, trying direct.n",
  676.       pszDestDomain);
  677. SysLogMessage(LOG_LEV_MESSAGE,
  678.       "SMAIL SMTP-Send FF = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  679.       pszDestDomain, pszSMTPDomain, pszMailFrom, pszRcptTo);
  680. if (pSMTPE != NULL)
  681. USmtpCleanupError(pSMTPE);
  682. if (USmtpSendMail
  683.     (pszDestDomain, pszHeloDomain, pszSendMailFrom, pszSendRcptTo, &FS,
  684.      pSMTPE) < 0) {
  685. ErrorPush();
  686. char szSmtpError[512] = "";
  687. USmtpGetSMTPError(pSMTPE, szSmtpError, sizeof(szSmtpError));
  688. ErrLogMessage(LOG_LEV_MESSAGE,
  689.       "SMAIL SMTP-Send FF = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  690.       "%s = "%s"n"
  691.       "%s = "%s"n", pszDestDomain, pszSMTPDomain,
  692.       pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  693.       szSmtpError, SMTP_SERVER_VARNAME,
  694.       USmtpGetErrorServer(pSMTPE));
  695. QueUtErrLogMessage(hQueue, hMessage,
  696.    "SMAIL SMTP-Send FF = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  697.    "%s = "%s"n"
  698.    "%s = "%s"n", pszDestDomain, pszSMTPDomain,
  699.    pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  700.    szSmtpError, SMTP_SERVER_VARNAME,
  701.    USmtpGetErrorServer(pSMTPE));
  702. return (ErrorPop());
  703. }
  704. ///////////////////////////////////////////////////////////////////////////////
  705. //  Log Mailer operation
  706. ///////////////////////////////////////////////////////////////////////////////
  707. if (SMAILLogEnabled(hShbSMAIL))
  708. USmlLogMessage(hFSpool, "SMTP", pszDestDomain);
  709. }
  710. } else {
  711. int iSendErrorCode = 0;
  712. for (int ss = 0; ppszMXGWs[ss] != NULL; ss++) {
  713. SysLogMessage(LOG_LEV_MESSAGE,
  714.       "SMAIL SMTP-Send MX = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  715.       ppszMXGWs[ss], pszSMTPDomain, pszMailFrom, pszRcptTo);
  716. if (pSMTPE != NULL)
  717. USmtpCleanupError(pSMTPE);
  718. if ((iSendErrorCode = USmtpSendMail(ppszMXGWs[ss], pszHeloDomain,
  719.     pszSendMailFrom, pszSendRcptTo, &FS,
  720.     pSMTPE)) == 0) {
  721. ///////////////////////////////////////////////////////////////////////////////
  722. //  Log Mailer operation
  723. ///////////////////////////////////////////////////////////////////////////////
  724. if (SMAILLogEnabled(hShbSMAIL))
  725. USmlLogMessage(hFSpool, "SMTP", ppszMXGWs[ss]);
  726. break;
  727. }
  728. char szSmtpError[512] = "";
  729. USmtpGetSMTPError(pSMTPE, szSmtpError, sizeof(szSmtpError));
  730. ErrLogMessage(LOG_LEV_MESSAGE,
  731.       "SMAIL SMTP-Send MX = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  732.       "%s = "%s"n"
  733.       "%s = "%s"n", ppszMXGWs[ss], pszSMTPDomain, pszMailFrom,
  734.       pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError,
  735.       SMTP_SERVER_VARNAME, USmtpGetErrorServer(pSMTPE));
  736. QueUtErrLogMessage(hQueue, hMessage,
  737.    "SMAIL SMTP-Send MX = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  738.    "%s = "%s"n"
  739.    "%s = "%s"n", ppszMXGWs[ss], pszSMTPDomain,
  740.    pszMailFrom, pszRcptTo, SMTP_ERROR_VARNAME,
  741.    szSmtpError, SMTP_SERVER_VARNAME,
  742.    USmtpGetErrorServer(pSMTPE));
  743. if ((pSMTPE != NULL) && USmtpIsFatalError(pSMTPE))
  744. break;
  745. }
  746. StrFreeStrings(ppszMXGWs);
  747. if (iSendErrorCode < 0)
  748. return (iSendErrorCode);
  749. }
  750. return (0);
  751. }
  752. static int SMAILHandleRemoteUserMessage(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  753. SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  754. QMSG_HANDLE hMessage, char const *pszDestDomain,
  755. char const *pszDestUser)
  756. {
  757. ///////////////////////////////////////////////////////////////////////////////
  758. //  Try domain custom processing
  759. ///////////////////////////////////////////////////////////////////////////////
  760. char szCustFilePath[SYS_MAX_PATH] = "";
  761. if (USmlGetDomainMsgCustomFile(hFSpool, hQueue, hMessage, pszDestDomain,
  762.        szCustFilePath) == 0)
  763. return (SMAILCustomProcessMessage
  764. (hSvrConfig, hShbSMAIL, hFSpool, hQueue, hMessage, pszDestDomain,
  765.  pszDestUser, szCustFilePath));
  766. ///////////////////////////////////////////////////////////////////////////////
  767. //  Fall down to use standard SMTP delivery
  768. ///////////////////////////////////////////////////////////////////////////////
  769. SMTPError SMTPE;
  770. USmtpInitError(&SMTPE);
  771. if (SMAILRemoteMsgSMTPSend(hSvrConfig, hShbSMAIL, hFSpool, hQueue, hMessage,
  772.    pszDestDomain, &SMTPE) < 0) {
  773. ErrorPush();
  774. ///////////////////////////////////////////////////////////////////////////////
  775. //  If a permanent SMTP error has been detected, then notify the message
  776. //  sender and remove the spool file
  777. ///////////////////////////////////////////////////////////////////////////////
  778. if (USmtpIsFatalError(&SMTPE))
  779. QueUtNotifyPermErrDelivery(hQueue, hMessage, hFSpool,
  780.    USmtpGetErrorMessage(&SMTPE),
  781.    USmtpGetErrorServer(&SMTPE), true);
  782. USmtpCleanupError(&SMTPE);
  783. return (ErrorPop());
  784. }
  785. USmtpCleanupError(&SMTPE);
  786. return (0);
  787. }
  788. static int SMAILCustomProcessMessage(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  789.      SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  790.      QMSG_HANDLE hMessage, char const *pszDestDomain,
  791.      char const *pszDestUser, char const *pszCustFilePath)
  792. {
  793. FILE *pCPFile = fopen(pszCustFilePath, "rt");
  794. if (pCPFile == NULL) {
  795. ErrSetErrorCode(ERR_FILE_OPEN, pszCustFilePath);
  796. return (ERR_FILE_OPEN);
  797. }
  798. ///////////////////////////////////////////////////////////////////////////////
  799. //  Create pushback command file
  800. ///////////////////////////////////////////////////////////////////////////////
  801. char szTmpFile[SYS_MAX_PATH] = "";
  802. SysGetTmpFile(szTmpFile);
  803. FILE *pPushBFile = fopen(szTmpFile, "wt");
  804. if (pPushBFile == NULL) {
  805. fclose(pCPFile);
  806. ErrSetErrorCode(ERR_FILE_CREATE, szTmpFile);
  807. return (ERR_FILE_CREATE);
  808. }
  809. int iPushBackCmds = 0;
  810. char szCmdLine[CUSTOM_PROC_LINE_MAX] = "";
  811. while (MscGetConfigLine(szCmdLine, sizeof(szCmdLine) - 1, pCPFile) != NULL) {
  812. char **ppszCmdTokens = StrGetTabLineStrings(szCmdLine);
  813. if (ppszCmdTokens == NULL)
  814. continue;
  815. int iFieldsCount = StrStringsCount(ppszCmdTokens);
  816. if (iFieldsCount > 0) {
  817. ///////////////////////////////////////////////////////////////////////////////
  818. //  Do command line macro substitution
  819. ///////////////////////////////////////////////////////////////////////////////
  820. SMAILCmdMacroSubstitutes(ppszCmdTokens, hFSpool);
  821. int iCmdResult = 0;
  822. if (stricmp(ppszCmdTokens[0], "external") == 0)
  823. iCmdResult =
  824. SMAILCmd_external(hSvrConfig, hShbSMAIL, pszDestDomain,
  825.   ppszCmdTokens, iFieldsCount, hFSpool,
  826.   hQueue, hMessage);
  827. else if (stricmp(ppszCmdTokens[0], "filter") == 0)
  828. iCmdResult = SMAILCmd_filter(hSvrConfig, hShbSMAIL, pszDestDomain,
  829.      ppszCmdTokens, iFieldsCount, hFSpool,
  830.      hQueue, hMessage);
  831. else if (stricmp(ppszCmdTokens[0], "smtp") == 0)
  832. iCmdResult = SMAILCmd_smtp(hSvrConfig, hShbSMAIL, pszDestDomain,
  833.    ppszCmdTokens, iFieldsCount, hFSpool,
  834.    hQueue, hMessage);
  835. else if (stricmp(ppszCmdTokens[0], "smtprelay") == 0)
  836. iCmdResult =
  837. SMAILCmd_smtprelay(hSvrConfig, hShbSMAIL, pszDestDomain,
  838.    ppszCmdTokens, iFieldsCount, hFSpool,
  839.    hQueue, hMessage);
  840. else if (stricmp(ppszCmdTokens[0], "redirect") == 0)
  841. iCmdResult =
  842. SMAILCmd_redirect(hSvrConfig, hShbSMAIL, pszDestDomain,
  843.   ppszCmdTokens, iFieldsCount, hFSpool,
  844.   hQueue, hMessage);
  845. else if (stricmp(ppszCmdTokens[0], "lredirect") == 0)
  846. iCmdResult =
  847. SMAILCmd_lredirect(hSvrConfig, hShbSMAIL, pszDestDomain,
  848.    ppszCmdTokens, iFieldsCount, hFSpool,
  849.    hQueue, hMessage);
  850. else {
  851. SysLogMessage(LOG_LEV_ERROR,
  852.       "Invalid command "%s" in file "%s"n",
  853.       ppszCmdTokens[0], pszCustFilePath);
  854. }
  855. ///////////////////////////////////////////////////////////////////////////////
  856. //  Check for the stop-processing error code
  857. ///////////////////////////////////////////////////////////////////////////////
  858. if (iCmdResult == SMAIL_STOP_PROCESSING) {
  859. StrFreeStrings(ppszCmdTokens);
  860. break;
  861. }
  862. ///////////////////////////////////////////////////////////////////////////////
  863. //  Test if we must save a failed command
  864. //  <0 = Error ; ==0 = Success ; >0 = Transient error ( save the command )
  865. ///////////////////////////////////////////////////////////////////////////////
  866. if (iCmdResult > 0) {
  867. fprintf(pPushBFile, "%sn", szCmdLine);
  868. ++iPushBackCmds;
  869. }
  870. ///////////////////////////////////////////////////////////////////////////////
  871. //  An error code might result if filters blocked the message. If this is the
  872. //  case QueCheckMessage() will return error and we MUST stop processing
  873. ///////////////////////////////////////////////////////////////////////////////
  874. if ((iCmdResult < 0) && (QueCheckMessage(hQueue, hMessage) < 0)) {
  875. ErrorPush();
  876. StrFreeStrings(ppszCmdTokens);
  877. fclose(pPushBFile);
  878. fclose(pCPFile);
  879. SysRemove(szTmpFile);
  880. return (ErrorPop());
  881. }
  882. }
  883. StrFreeStrings(ppszCmdTokens);
  884. }
  885. fclose(pPushBFile);
  886. fclose(pCPFile);
  887. SysRemove(pszCustFilePath);
  888. if (iPushBackCmds > 0) {
  889. ///////////////////////////////////////////////////////////////////////////////
  890. //  If commands left out of processing, push them into the custom file
  891. ///////////////////////////////////////////////////////////////////////////////
  892. if (MscMoveFile(szTmpFile, pszCustFilePath) < 0)
  893. return (ErrGetErrorCode());
  894. ErrSetErrorCode(ERR_INCOMPLETE_PROCESSING);
  895. return (ERR_INCOMPLETE_PROCESSING);
  896. }
  897. SysRemove(szTmpFile);
  898. return (0);
  899. }
  900. static int SMAILCmdMacroSubstitutes(char **ppszCmdTokens, SPLF_HANDLE hFSpool)
  901. {
  902. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  903. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  904. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  905. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  906. char const *pszMessageID = USmlGetSpoolFile(hFSpool);
  907. int iFromDomains = StrStringsCount(ppszFrom);
  908. int iRcptDomains = StrStringsCount(ppszRcpt);
  909. FileSection FS;
  910. ///////////////////////////////////////////////////////////////////////////////
  911. //  This function retrieve the spool file message section and sync the content.
  912. //  This is necessary before passing the file name to external programs
  913. ///////////////////////////////////////////////////////////////////////////////
  914. if (USmlGetMsgFileSection(hFSpool, FS) < 0)
  915. return (ErrGetErrorCode());
  916. for (int ii = 0; ppszCmdTokens[ii] != NULL; ii++) {
  917. if (strcmp(ppszCmdTokens[ii], "@@FROM") == 0) {
  918. char *pszNewValue =
  919. SysStrDup((iFromDomains > 0) ? ppszFrom[iFromDomains - 1] : "");
  920. if (pszNewValue == NULL)
  921. return (ErrGetErrorCode());
  922. SysFree(ppszCmdTokens[ii]);
  923. ppszCmdTokens[ii] = pszNewValue;
  924. } else if (strcmp(ppszCmdTokens[ii], "@@RCPT") == 0) {
  925. char *pszNewValue =
  926. SysStrDup((iRcptDomains > 0) ? ppszRcpt[iRcptDomains - 1] : "");
  927. if (pszNewValue == NULL)
  928. return (ErrGetErrorCode());
  929. SysFree(ppszCmdTokens[ii]);
  930. ppszCmdTokens[ii] = pszNewValue;
  931. } else if (strcmp(ppszCmdTokens[ii], "@@FILE") == 0) {
  932. char *pszNewValue = SysStrDup(FS.szFilePath);
  933. if (pszNewValue == NULL)
  934. return (ErrGetErrorCode());
  935. SysFree(ppszCmdTokens[ii]);
  936. ppszCmdTokens[ii] = pszNewValue;
  937. } else if (strcmp(ppszCmdTokens[ii], "@@MSGID") == 0) {
  938. char *pszNewValue = SysStrDup(pszMessageID);
  939. if (pszNewValue == NULL)
  940. return (ErrGetErrorCode());
  941. SysFree(ppszCmdTokens[ii]);
  942. ppszCmdTokens[ii] = pszNewValue;
  943. } else if (strcmp(ppszCmdTokens[ii], "@@MSGREF") == 0) {
  944. char *pszNewValue = SysStrDup(pszSmtpMessageID);
  945. if (pszNewValue == NULL)
  946. return (ErrGetErrorCode());
  947. SysFree(ppszCmdTokens[ii]);
  948. ppszCmdTokens[ii] = pszNewValue;
  949. } else if (strcmp(ppszCmdTokens[ii], "@@TMPFILE") == 0) {
  950. char szTmpFile[SYS_MAX_PATH] = "";
  951. SysGetTmpFile(szTmpFile);
  952. if (MscCopyFile(szTmpFile, FS.szFilePath) < 0) {
  953. ErrorPush();
  954. CheckRemoveFile(szTmpFile);
  955. return (ErrorPop());
  956. }
  957. char *pszNewValue = SysStrDup(szTmpFile);
  958. if (pszNewValue == NULL)
  959. return (ErrGetErrorCode());
  960. SysFree(ppszCmdTokens[ii]);
  961. ppszCmdTokens[ii] = pszNewValue;
  962. } else if (strcmp(ppszCmdTokens[ii], "@@USERAUTH") == 0) {
  963. char szAuthName[MAX_ADDR_NAME] = "-";
  964. USmlMessageAuth(hFSpool, szAuthName, sizeof(szAuthName) - 1);
  965. char *pszNewValue = SysStrDup(szAuthName);
  966. if (pszNewValue == NULL)
  967. return (ErrGetErrorCode());
  968. SysFree(ppszCmdTokens[ii]);
  969. ppszCmdTokens[ii] = pszNewValue;
  970. }
  971. }
  972. return (0);
  973. }
  974. static int SMAILCmd_external(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  975.      char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  976.      SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  977. {
  978. ///////////////////////////////////////////////////////////////////////////////
  979. //  Apply filters ...
  980. ///////////////////////////////////////////////////////////////////////////////
  981. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_INBOUND) < 0)
  982. return (ErrGetErrorCode());
  983. if (iNumTokens < 5) {
  984. ErrSetErrorCode(ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  985. return (ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  986. }
  987. int iPriority = atoi(ppszCmdTokens[1]);
  988. int iWaitTimeout = atoi(ppszCmdTokens[2]);
  989. int iExitStatus = 0;
  990. if (SysExec(ppszCmdTokens[3], &ppszCmdTokens[3], iWaitTimeout, iPriority,
  991.     &iExitStatus) < 0) {
  992. ErrorPush();
  993. char const *pszMailFrom = USmlMailFrom(hFSpool);
  994. char const *pszRcptTo = USmlRcptTo(hFSpool);
  995. ErrLogMessage(LOG_LEV_MESSAGE,
  996.       "SMAIL EXTRN-Send Prg = "%s" Domain = "%s" From = "%s" To = "%s" Failed !n",
  997.       ppszCmdTokens[3], pszDestDomain, pszMailFrom, pszRcptTo);
  998. QueUtErrLogMessage(hQueue, hMessage,
  999.    "SMAIL EXTRN-Send Prg = "%s" Domain = "%s" From = "%s" To = "%s" Failed !n",
  1000.    ppszCmdTokens[3], pszDestDomain, pszMailFrom, pszRcptTo);
  1001. return (ErrorPop());
  1002. }
  1003. ///////////////////////////////////////////////////////////////////////////////
  1004. //  Log Mailer operation
  1005. ///////////////////////////////////////////////////////////////////////////////
  1006. if (SMAILLogEnabled(hShbSMAIL))
  1007. USmlLogMessage(hFSpool, "EXTRN", ppszCmdTokens[3]);
  1008. return ((iExitStatus == SMAIL_EXTERNAL_EXIT_BREAK) ? SMAIL_STOP_PROCESSING: 0);
  1009. }
  1010. static int SMAILCmd_filter(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  1011.    char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  1012.    SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  1013. {
  1014. if (iNumTokens < 5) {
  1015. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1016. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1017. }
  1018. int iPriority = atoi(ppszCmdTokens[1]);
  1019. int iWaitTimeout = atoi(ppszCmdTokens[2]);
  1020. int iExitStatus = 0;
  1021. if (SysExec(ppszCmdTokens[3], &ppszCmdTokens[3], iWaitTimeout, iPriority,
  1022.     &iExitStatus) < 0) {
  1023. ErrorPush();
  1024. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1025. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1026. ErrLogMessage(LOG_LEV_MESSAGE,
  1027.       "USMAIL FILTER Prg = "%s" From = "%s" To = "%s" Failed !n",
  1028.       ppszCmdTokens[3], pszMailFrom, pszRcptTo);
  1029. QueUtErrLogMessage(hQueue, hMessage,
  1030.    "USMAIL FILTER Prg = "%s" From = "%s" To = "%s" Failed !n",
  1031.    ppszCmdTokens[3], pszMailFrom, pszRcptTo);
  1032. return (ErrorPop());
  1033. }
  1034. ///////////////////////////////////////////////////////////////////////////////
  1035. //  Log Mailer operation
  1036. ///////////////////////////////////////////////////////////////////////////////
  1037. if (SMAILLogEnabled(hShbSMAIL))
  1038. USmlLogMessage(hFSpool, "FILTER", ppszCmdTokens[3]);
  1039. ///////////////////////////////////////////////////////////////////////////////
  1040. //  Separate code from flags
  1041. ///////////////////////////////////////////////////////////////////////////////
  1042. int iExitFlags = iExitStatus & FILTER_FLAGS_MASK;
  1043. iExitStatus &= ~FILTER_FLAGS_MASK;
  1044. if ((iExitStatus == FILTER_OUT_EXITCODE) ||
  1045.     (iExitStatus == FILTER_OUT_NN_EXITCODE) ||
  1046.     (iExitStatus == FILTER_OUT_NNF_EXITCODE)) {
  1047. ///////////////////////////////////////////////////////////////////////////////
  1048. //  Filter out message
  1049. ///////////////////////////////////////////////////////////////////////////////
  1050. char *pszRejMsg = FilGetFilterRejMessage(USmlGetSpoolFilePath(hFSpool));
  1051. if (iExitStatus == FILTER_OUT_EXITCODE)
  1052. QueUtNotifyPermErrDelivery(hQueue, hMessage, NULL,
  1053.    (pszRejMsg != NULL) ? pszRejMsg :
  1054.    ErrGetErrorString(ERR_FILTERED_MESSAGE),
  1055.    NULL, true);
  1056. else if (iExitStatus == FILTER_OUT_NN_EXITCODE)
  1057. QueCleanupMessage(hQueue, hMessage,
  1058.   !QueUtRemoveSpoolErrors());
  1059. else
  1060. QueCleanupMessage(hQueue, hMessage, false);
  1061. if (pszRejMsg != NULL)
  1062. SysFree(pszRejMsg);
  1063. ErrSetErrorCode(ERR_FILTERED_MESSAGE);
  1064. return (ERR_FILTERED_MESSAGE);
  1065. } else if (iExitStatus == FILTER_MODIFY_EXITCODE) {
  1066. ///////////////////////////////////////////////////////////////////////////////
  1067. //  Filter modified the message, we need to reload the spool handle
  1068. ///////////////////////////////////////////////////////////////////////////////
  1069. if (USmlReloadHandle(hFSpool) < 0) {
  1070. ErrorPush();
  1071. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1072. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1073. SysLogMessage(LOG_LEV_MESSAGE,
  1074.       "Filter error [ Modified message corrupted ]: Sender = "%s" Recipient = "%s" (%s)n",
  1075.       pszMailFrom, pszRcptTo,
  1076.       ppszCmdTokens[3]);
  1077. QueUtErrLogMessage(hQueue, hMessage,
  1078.    "Filter error [ Modified message corrupted ]: Sender = "%s" Recipient = "%s" (%s)n",
  1079.    pszMailFrom, pszRcptTo,
  1080.    ppszCmdTokens[3]);
  1081. QueCleanupMessage(hQueue, hMessage, true);
  1082. return (ErrorPop());
  1083. }
  1084. }
  1085. return ((iExitFlags & FILTER_FLAGS_BREAK) ? SMAIL_STOP_PROCESSING: 0);
  1086. }
  1087. static int SMAILCmd_smtp(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  1088.  char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  1089.  SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  1090. {
  1091. if (iNumTokens != 1) {
  1092. ErrSetErrorCode(ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1093. return (ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1094. }
  1095. SMTPError SMTPE;
  1096. USmtpInitError(&SMTPE);
  1097. if (SMAILRemoteMsgSMTPSend(hSvrConfig, hShbSMAIL, hFSpool, hQueue, hMessage,
  1098.    pszDestDomain, &SMTPE) < 0) {
  1099. ///////////////////////////////////////////////////////////////////////////////
  1100. //  If we get an SMTP fatal error We must return <0 , otherwise >0 to give
  1101. //  XMail to ability to resume the command
  1102. ///////////////////////////////////////////////////////////////////////////////
  1103. int iReturnCode = USmtpIsFatalError(&SMTPE) ? ErrGetErrorCode() :
  1104.     -ErrGetErrorCode();
  1105. ///////////////////////////////////////////////////////////////////////////////
  1106. //  If a permanent SMTP error has been detected, then notify the message sender
  1107. ///////////////////////////////////////////////////////////////////////////////
  1108. if (USmtpIsFatalError(&SMTPE))
  1109. QueUtNotifyPermErrDelivery(hQueue, hMessage, hFSpool,
  1110.    USmtpGetErrorMessage(&SMTPE),
  1111.    USmtpGetErrorServer(&SMTPE), false);
  1112. USmtpCleanupError(&SMTPE);
  1113. return (iReturnCode);
  1114. }
  1115. USmtpCleanupError(&SMTPE);
  1116. return (0);
  1117. }
  1118. static int SMAILCmd_smtprelay(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  1119.       char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  1120.       SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  1121. {
  1122. ///////////////////////////////////////////////////////////////////////////////
  1123. //  Apply filters ...
  1124. ///////////////////////////////////////////////////////////////////////////////
  1125. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_OUTBOUND) < 0)
  1126. return (ErrGetErrorCode());
  1127. if (iNumTokens != 2) {
  1128. ErrSetErrorCode(ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1129. return (ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1130. }
  1131. char **ppszRelays = NULL;
  1132. if (ppszCmdTokens[1][0] == '#') {
  1133. if ((ppszRelays = StrTokenize(ppszCmdTokens[1] + 1, ",")) != NULL) {
  1134. int iRelayCount = StrStringsCount(ppszRelays);
  1135. srand((unsigned int) time(NULL));
  1136. for (int ii = 0; ii < (iRelayCount / 2); ii++) {
  1137. int iSwap1 = rand() % iRelayCount;
  1138. int iSwap2 = rand() % iRelayCount;
  1139. char *pszRly1 = ppszRelays[iSwap1];
  1140. char *pszRly2 = ppszRelays[iSwap2];
  1141. ppszRelays[iSwap1] = pszRly2;
  1142. ppszRelays[iSwap2] = pszRly1;
  1143. }
  1144. }
  1145. } else
  1146. ppszRelays = StrTokenize(ppszCmdTokens[1], ",");
  1147. if (ppszRelays == NULL)
  1148. return (ErrGetErrorCode());
  1149. ///////////////////////////////////////////////////////////////////////////////
  1150. //  This function retrieve the spool file message section and sync the content.
  1151. //  This is necessary before sending the file
  1152. ///////////////////////////////////////////////////////////////////////////////
  1153. FileSection FS;
  1154. if (USmlGetMsgFileSection(hFSpool, FS) < 0) {
  1155. ErrorPush();
  1156. StrFreeStrings(ppszRelays);
  1157. return (ErrorPop());
  1158. }
  1159. ///////////////////////////////////////////////////////////////////////////////
  1160. //  Get spool file infos
  1161. ///////////////////////////////////////////////////////////////////////////////
  1162. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  1163. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1164. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1165. char const *pszSendMailFrom = USmlSendMailFrom(hFSpool);
  1166. char const *pszSendRcptTo = USmlSendRcptTo(hFSpool);
  1167. char const *pszSpoolFilePath = USmlGetSpoolFilePath(hFSpool);
  1168. ///////////////////////////////////////////////////////////////////////////////
  1169. //  Get HELO domain
  1170. ///////////////////////////////////////////////////////////////////////////////
  1171. char szHeloDomain[MAX_HOST_NAME] = "";
  1172. SvrConfigVar("HeloDomain", szHeloDomain, sizeof(szHeloDomain) - 1, hSvrConfig, "");
  1173. char const *pszHeloDomain = IsEmptyString(szHeloDomain) ? NULL : szHeloDomain;
  1174. SMTPError SMTPE;
  1175. USmtpInitError(&SMTPE);
  1176. ///////////////////////////////////////////////////////////////////////////////
  1177. //  By initializing this to zero makes XMail to discharge all mail for domains
  1178. //  that have an empty relay list
  1179. ///////////////////////////////////////////////////////////////////////////////
  1180. int iReturnCode = 0;
  1181. for (int ss = 0; ppszRelays[ss] != NULL; ss++) {
  1182. SysLogMessage(LOG_LEV_MESSAGE,
  1183.       "SMAIL SMTP-Send RLYS = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  1184.       ppszRelays[ss], pszSMTPDomain, pszMailFrom, pszRcptTo);
  1185. USmtpCleanupError(&SMTPE);
  1186. if (USmtpSendMail(ppszRelays[ss], pszHeloDomain, pszSendMailFrom, pszSendRcptTo,
  1187.   &FS, &SMTPE) == 0) {
  1188. ///////////////////////////////////////////////////////////////////////////////
  1189. //  Log Mailer operation
  1190. ///////////////////////////////////////////////////////////////////////////////
  1191. if (SMAILLogEnabled(hShbSMAIL))
  1192. USmlLogMessage(hFSpool, "RLYS", ppszRelays[ss]);
  1193. USmtpCleanupError(&SMTPE);
  1194. StrFreeStrings(ppszRelays);
  1195. return (0);
  1196. }
  1197. int iErrorCode = ErrGetErrorCode();
  1198. char szSmtpError[512] = "";
  1199. USmtpGetSMTPError(&SMTPE, szSmtpError, sizeof(szSmtpError));
  1200. ErrLogMessage(LOG_LEV_MESSAGE,
  1201.       "SMAIL SMTP-Send RLYS = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  1202.       "%s = "%s"n"
  1203.       "%s = "%s"n", ppszRelays[ss], pszSMTPDomain, pszMailFrom,
  1204.       pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError, SMTP_SERVER_VARNAME,
  1205.       USmtpGetErrorServer(&SMTPE));
  1206. QueUtErrLogMessage(hQueue, hMessage,
  1207.    "SMAIL SMTP-Send RLYS = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  1208.    "%s = "%s"n"
  1209.    "%s = "%s"n", ppszRelays[ss], pszSMTPDomain, pszMailFrom,
  1210.    pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError,
  1211.    SMTP_SERVER_VARNAME, USmtpGetErrorServer(&SMTPE));
  1212. ///////////////////////////////////////////////////////////////////////////////
  1213. //  If a permanent SMTP error has been detected, then notify the message sender
  1214. ///////////////////////////////////////////////////////////////////////////////
  1215. if (USmtpIsFatalError(&SMTPE))
  1216. QueUtNotifyPermErrDelivery(hQueue, hMessage, hFSpool,
  1217.    USmtpGetErrorMessage(&SMTPE),
  1218.    USmtpGetErrorServer(&SMTPE), false);
  1219. iReturnCode = USmtpIsFatalError(&SMTPE) ? iErrorCode : -iErrorCode;
  1220. }
  1221. USmtpCleanupError(&SMTPE);
  1222. StrFreeStrings(ppszRelays);
  1223. return (iReturnCode);
  1224. }
  1225. static int SMAILCmd_redirect(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  1226.      char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  1227.      SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  1228. {
  1229. if (iNumTokens < 2) {
  1230. ErrSetErrorCode(ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1231. return (ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1232. }
  1233. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  1234. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  1235. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  1236. int iFromDomains = StrStringsCount(ppszFrom);
  1237. int iRcptDomains = StrStringsCount(ppszRcpt);
  1238. char szLocalUser[MAX_ADDR_NAME] = "";
  1239. char szLocalDomain[MAX_ADDR_NAME] = "";
  1240. if ((iRcptDomains < 1) ||
  1241.     (USmtpSplitEmailAddr(ppszRcpt[iRcptDomains - 1], szLocalUser, szLocalDomain) < 0))
  1242. return (ErrGetErrorCode());
  1243. for (int ii = 1; ppszCmdTokens[ii] != NULL; ii++) {
  1244. ///////////////////////////////////////////////////////////////////////////////
  1245. //  Get message handle
  1246. ///////////////////////////////////////////////////////////////////////////////
  1247. QMSG_HANDLE hRedirMessage = QueCreateMessage(hSpoolQueue);
  1248. if (hRedirMessage == INVALID_QMSG_HANDLE)
  1249. return (ErrGetErrorCode());
  1250. char szQueueFilePath[SYS_MAX_PATH] = "";
  1251. QueGetFilePath(hSpoolQueue, hRedirMessage, szQueueFilePath);
  1252. char szAliasAddr[MAX_ADDR_NAME] = "";
  1253. if (strchr(ppszCmdTokens[ii], '@') == NULL)
  1254. SysSNPrintf(szAliasAddr, sizeof(szAliasAddr) - 1, "%s@%s",
  1255.     szLocalUser, ppszCmdTokens[ii]);
  1256. else
  1257. StrSNCpy(szAliasAddr, ppszCmdTokens[ii]);
  1258. if (USmlCreateSpoolFile(hFSpool, NULL, szAliasAddr, szQueueFilePath, NULL) < 0) {
  1259. ErrorPush();
  1260. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1261. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1262. return (ErrorPop());
  1263. }
  1264. ///////////////////////////////////////////////////////////////////////////////
  1265. //  Transfer file to the spool
  1266. ///////////////////////////////////////////////////////////////////////////////
  1267. if (QueCommitMessage(hSpoolQueue, hRedirMessage) < 0) {
  1268. ErrorPush();
  1269. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1270. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1271. return (ErrorPop());
  1272. }
  1273. }
  1274. return (0);
  1275. }
  1276. static int SMAILCmd_lredirect(SVRCFG_HANDLE hSvrConfig, SHB_HANDLE hShbSMAIL,
  1277.       char const *pszDestDomain, char **ppszCmdTokens, int iNumTokens,
  1278.       SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage)
  1279. {
  1280. if (iNumTokens < 2) {
  1281. ErrSetErrorCode(ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1282. return (ERR_BAD_DOMAIN_PROC_CMD_SYNTAX);
  1283. }
  1284. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  1285. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  1286. int iFromDomains = StrStringsCount(ppszFrom);
  1287. int iRcptDomains = StrStringsCount(ppszRcpt);
  1288. char szLocalUser[MAX_ADDR_NAME] = "";
  1289. char szLocalDomain[MAX_ADDR_NAME] = "";
  1290. if ((iRcptDomains < 1) ||
  1291.     (USmtpSplitEmailAddr(ppszRcpt[iRcptDomains - 1], szLocalUser, szLocalDomain) < 0))
  1292. return (ErrGetErrorCode());
  1293. for (int ii = 1; ppszCmdTokens[ii] != NULL; ii++) {
  1294. ///////////////////////////////////////////////////////////////////////////////
  1295. //  Get message handle
  1296. ///////////////////////////////////////////////////////////////////////////////
  1297. QMSG_HANDLE hRedirMessage = QueCreateMessage(hSpoolQueue);
  1298. if (hRedirMessage == INVALID_QMSG_HANDLE)
  1299. return (ErrGetErrorCode());
  1300. char szQueueFilePath[SYS_MAX_PATH] = "";
  1301. QueGetFilePath(hSpoolQueue, hRedirMessage, szQueueFilePath);
  1302. char szAliasAddr[MAX_ADDR_NAME] = "";
  1303. if (strchr(ppszCmdTokens[ii], '@') == NULL)
  1304. SysSNPrintf(szAliasAddr, sizeof(szAliasAddr) - 1, "%s@%s",
  1305.     szLocalUser, ppszCmdTokens[ii]);
  1306. else
  1307. StrSNCpy(szAliasAddr, ppszCmdTokens[ii]);
  1308. if (USmlCreateSpoolFile(hFSpool, ppszRcpt[iRcptDomains - 1], szAliasAddr,
  1309. szQueueFilePath, NULL) < 0) {
  1310. ErrorPush();
  1311. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1312. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1313. return (ErrorPop());
  1314. }
  1315. ///////////////////////////////////////////////////////////////////////////////
  1316. //  Transfer file to the spool
  1317. ///////////////////////////////////////////////////////////////////////////////
  1318. if (QueCommitMessage(hSpoolQueue, hRedirMessage) < 0) {
  1319. ErrorPush();
  1320. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1321. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1322. return (ErrorPop());
  1323. }
  1324. }
  1325. return (0);
  1326. }