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

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 "StrUtils.h"
  26. #include "SList.h"
  27. #include "ShBlocks.h"
  28. #include "ResLocks.h"
  29. #include "BuffSock.h"
  30. #include "UsrUtils.h"
  31. #include "SvrUtils.h"
  32. #include "MailConfig.h"
  33. #include "MessQueue.h"
  34. #include "SMAILUtils.h"
  35. #include "QueueUtils.h"
  36. #include "ExtAliases.h"
  37. #include "MiscUtils.h"
  38. #include "MailDomains.h"
  39. #include "Filter.h"
  40. #include "SMTPSvr.h"
  41. #include "SMTPUtils.h"
  42. #include "AppDefines.h"
  43. #include "MailSvr.h"
  44. #define SFF_HEADER_MODIFIED             (1 << 0)
  45. #define STD_TAG_BUFFER_LENGTH           1024
  46. #define CUSTOM_CMD_LINE_MAX             512
  47. #define SMAIL_DOMAIN_PROC_DIR           "custdomains"
  48. #define SMAIL_CMDALIAS_DIR              "cmdaliases"
  49. #define SMAIL_DEFAULT_FILTER            ".tab"
  50. #define SMAIL_LOG_FILE                  "smail"
  51. #define MAX_MTA_OPS                     16
  52. #define ADDRESS_TOKENIZER               ","
  53. #define SMAIL_EXTERNAL_EXIT_BREAK       16
  54. #define SMAIL_STOP_PROCESSING           3111965L
  55. struct SpoolFileData {
  56. char **ppszInfo;
  57. char **ppszFrom;
  58. char *pszMailFrom;
  59. char *pszSendMailFrom;
  60. char **ppszRcpt;
  61. char *pszRcptTo;
  62. char *pszSendRcptTo;
  63. char *pszRelayDomain;
  64. char szSMTPDomain[MAX_ADDR_NAME];
  65. char szMessageID[128];
  66. char szMessFilePath[SYS_MAX_PATH];
  67. unsigned long ulMessageOffset;
  68. unsigned long ulMailDataOffset;
  69. char szSpoolFile[SYS_MAX_PATH];
  70. HSLIST hTagList;
  71. unsigned long ulFlags;
  72. };
  73. struct MessageTagData {
  74. LISTLINK LL;
  75. char *pszTagName;
  76. char *pszTagData;
  77. };
  78. static MessageTagData *USmlAllocTag(char const *pszTagName, char const *pszTagData);
  79. static void USmlFreeTag(MessageTagData * pMTD);
  80. static MessageTagData *USmlFindTag(HSLIST & hTagList, char const *pszTagName,
  81.    TAG_POSITION & TagPosition);
  82. static int USmlAddTag(HSLIST & hTagList, char const *pszTagName,
  83.       char const *pszTagData, int iUpdate = 0);
  84. static void USmlFreeTagsList(HSLIST & hTagList);
  85. static int USmlLoadTags(FILE * pSpoolFile, HSLIST & hTagList);
  86. static int USmlDumpHeaders(FILE * pMsgFile, HSLIST & hTagList);
  87. static void USmlFreeData(SpoolFileData * pSFD);
  88. static void USmlInitHandle(SpoolFileData * pSFD);
  89. static SpoolFileData *USmlAllocEmptyHandle(void);
  90. static int USmlLoadHandle(SpoolFileData * pSFD, const char *pszMessFilePath);
  91. static int USmlFlushMessageFile(SpoolFileData * pSFD);
  92. static int USmlGetMailProcessFile(UserInfo * pUI, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
  93.   char *pszMPFilePath);
  94. static int USmlProcessCustomMailingFile(SVRCFG_HANDLE hSvrConfig, UserInfo * pUI,
  95. SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  96. QMSG_HANDLE hMessage, char const *pszMPFile,
  97. LocalMailProcConfig & LMPC);
  98. static int USmlCmdMacroSubstitutes(char **ppszCmdTokens, UserInfo * pUI, SPLF_HANDLE hFSpool);
  99. static int USmlCmd_external(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  100.     UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  101.     QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC);
  102. static int USmlCmd_filter(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  103.   UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  104.   QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC);
  105. static int USmlCmd_mailbox(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  106.    UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  107.    QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC);
  108. static int USmlCmd_redirect(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  109.     UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  110.     QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC);
  111. static int USmlCmd_lredirect(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  112.      UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  113.      QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC);
  114. static int USmlCmd_smtprelay(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  115.      UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  116.      QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC);
  117. static int USmlLogMessage(char const *pszSMTPDomain, char const *pszMessageID,
  118.   char const *pszSmtpMessageID, char const *pszFrom, char const *pszRcpt,
  119.   char const *pszMedium, char const *pszParam);
  120. static int USmlExtractFromAddress(HSLIST & hTagList, char *pszFromAddr, int iMaxAddress);
  121. static char const *USmlAddressFromAtPtr(char const *pszAt, char const *pszBase,
  122. char *pszAddress, int iMaxAddress);
  123. static char const *USmlAddSingleAddress(char const *pszCurr, char const *pszBase,
  124. DynString * pAddrDS, char const *const *ppszMatchDomains,
  125. int *piAdded);
  126. static int USmlAddAddresses(char const *pszAddrList, DynString * pAddrDS,
  127.     char const *const *ppszMatchDomains);
  128. static char **USmlGetAddressList(HSLIST & hTagList, char const *const *ppszMatchDomains,
  129.  char const *const *ppszAddrTags);
  130. static int USmlExtractToAddress(HSLIST & hTagList, char *pszToAddr, int iMaxAddress);
  131. static char **USmlBuildTargetRcptList(char const *pszRcptTo, HSLIST & hTagList,
  132.       const char *pszFetchHdrTags);
  133. static int USmlCreateSpoolFile(FILE * pMailFile, char const *const *ppszInfo,
  134.        char const *pszMailFrom, char const *pszRcptTo,
  135.        char const *pszSpoolFile);
  136. int USmlLoadSpoolFileHeader(char const *pszSpoolFile, SpoolFileHeader & SFH)
  137. {
  138. ZeroData(SFH);
  139. FILE *pSpoolFile = fopen(pszSpoolFile, "rb");
  140. if (pSpoolFile == NULL) {
  141. ErrSetErrorCode(ERR_SPOOL_FILE_NOT_FOUND, pszSpoolFile);
  142. return (ERR_SPOOL_FILE_NOT_FOUND);
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////
  145. //  Build spool file name
  146. ///////////////////////////////////////////////////////////////////////////////
  147. char szFName[SYS_MAX_PATH] = "";
  148. char szExt[SYS_MAX_PATH] = "";
  149. char szSpoolLine[MAX_SPOOL_LINE] = "";
  150. MscSplitPath(pszSpoolFile, NULL, szFName, szExt);
  151. SysSNPrintf(SFH.szSpoolFile, sizeof(SFH.szSpoolFile) - 1, "%s%s", szFName, szExt);
  152. ///////////////////////////////////////////////////////////////////////////////
  153. //  Read info ( 1st row of the spool file )
  154. ///////////////////////////////////////////////////////////////////////////////
  155. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  156.     ((SFH.ppszInfo = StrTokenize(szSpoolLine, ";")) == NULL) ||
  157.     (StrStringsCount(SFH.ppszInfo) < smiMax)) {
  158. if (SFH.ppszInfo != NULL)
  159. StrFreeStrings(SFH.ppszInfo);
  160. fclose(pSpoolFile);
  161. ZeroData(SFH);
  162. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszSpoolFile);
  163. return (ERR_SPOOL_FILE_NOT_FOUND);
  164. }
  165. ///////////////////////////////////////////////////////////////////////////////
  166. //  Read SMTP domain ( 2nd row of the spool file )
  167. ///////////////////////////////////////////////////////////////////////////////
  168. if (MscGetString(pSpoolFile, SFH.szSMTPDomain, sizeof(SFH.szSMTPDomain) - 1) == NULL) {
  169. StrFreeStrings(SFH.ppszInfo);
  170. fclose(pSpoolFile);
  171. ZeroData(SFH);
  172. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszSpoolFile);
  173. return (ERR_SPOOL_FILE_NOT_FOUND);
  174. }
  175. ///////////////////////////////////////////////////////////////////////////////
  176. //  Read message ID ( 3rd row of the spool file )
  177. ///////////////////////////////////////////////////////////////////////////////
  178. if (MscGetString(pSpoolFile, SFH.szMessageID, sizeof(SFH.szMessageID) - 1) == NULL) {
  179. StrFreeStrings(SFH.ppszInfo);
  180. fclose(pSpoolFile);
  181. ZeroData(SFH);
  182. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszSpoolFile);
  183. return (ERR_SPOOL_FILE_NOT_FOUND);
  184. }
  185. ///////////////////////////////////////////////////////////////////////////////
  186. //  Read "MAIL FROM:" ( 4th row of the spool file )
  187. ///////////////////////////////////////////////////////////////////////////////
  188. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  189.     (StrINComp(szSpoolLine, MAIL_FROM_STR) != 0) ||
  190.     ((SFH.ppszFrom = USmtpGetPathStrings(szSpoolLine)) == NULL)) {
  191. StrFreeStrings(SFH.ppszInfo);
  192. fclose(pSpoolFile);
  193. ZeroData(SFH);
  194. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszSpoolFile);
  195. return (ERR_INVALID_SPOOL_FILE);
  196. }
  197. ///////////////////////////////////////////////////////////////////////////////
  198. //  Read "RCPT TO:" ( 5th row of the spool file )
  199. ///////////////////////////////////////////////////////////////////////////////
  200. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  201.     (StrINComp(szSpoolLine, RCPT_TO_STR) != 0) ||
  202.     ((SFH.ppszRcpt = USmtpGetPathStrings(szSpoolLine)) == NULL)) {
  203. StrFreeStrings(SFH.ppszFrom);
  204. StrFreeStrings(SFH.ppszInfo);
  205. fclose(pSpoolFile);
  206. ZeroData(SFH);
  207. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszSpoolFile);
  208. return (ERR_INVALID_SPOOL_FILE);
  209. }
  210. fclose(pSpoolFile);
  211. return (0);
  212. }
  213. void USmlCleanupSpoolFileHeader(SpoolFileHeader & SFH)
  214. {
  215. if (SFH.ppszInfo != NULL)
  216. StrFreeStrings(SFH.ppszInfo);
  217. if (SFH.ppszRcpt != NULL)
  218. StrFreeStrings(SFH.ppszRcpt);
  219. if (SFH.ppszFrom != NULL)
  220. StrFreeStrings(SFH.ppszFrom);
  221. ZeroData(SFH);
  222. }
  223. static MessageTagData *USmlAllocTag(char const *pszTagName, char const *pszTagData)
  224. {
  225. MessageTagData *pMTD = (MessageTagData *) SysAlloc(sizeof(MessageTagData));
  226. if (pMTD == NULL)
  227. return (NULL);
  228. ListLinkInit(pMTD);
  229. pMTD->pszTagName = SysStrDup(pszTagName);
  230. pMTD->pszTagData = SysStrDup(pszTagData);
  231. return (pMTD);
  232. }
  233. static void USmlFreeTag(MessageTagData * pMTD)
  234. {
  235. SysFree(pMTD->pszTagName);
  236. SysFree(pMTD->pszTagData);
  237. SysFree(pMTD);
  238. }
  239. static MessageTagData *USmlFindTag(HSLIST & hTagList, char const *pszTagName,
  240.    TAG_POSITION & TagPosition)
  241. {
  242. MessageTagData *pMTD = (TagPosition == TAG_POSITION_INIT) ?
  243. (MessageTagData *) ListFirst(hTagList) : (MessageTagData *) TagPosition;
  244. for (; pMTD != INVALID_SLIST_PTR; pMTD = (MessageTagData *)
  245.      ListNext(hTagList, (PLISTLINK) pMTD)) {
  246. if ((pszTagName == NULL) || (stricmp(pMTD->pszTagName, pszTagName) == 0)) {
  247. TagPosition = (TAG_POSITION) ListNext(hTagList, (PLISTLINK) pMTD);
  248. return (pMTD);
  249. }
  250. }
  251. TagPosition = (TAG_POSITION) INVALID_SLIST_PTR;
  252. return (NULL);
  253. }
  254. static int USmlAddTag(HSLIST & hTagList, char const *pszTagName,
  255.       char const *pszTagData, int iUpdate)
  256. {
  257. if (!iUpdate) {
  258. MessageTagData *pMTD = USmlAllocTag(pszTagName, pszTagData);
  259. if (pMTD == NULL)
  260. return (ErrGetErrorCode());
  261. ListAddTail(hTagList, (PLISTLINK) pMTD);
  262. } else {
  263. TAG_POSITION TagPosition = TAG_POSITION_INIT;
  264. MessageTagData *pMTD = USmlFindTag(hTagList, pszTagName, TagPosition);
  265. if (pMTD != NULL) {
  266. SysFree(pMTD->pszTagData);
  267. pMTD->pszTagData = SysStrDup(pszTagData);
  268. } else {
  269. if ((pMTD = USmlAllocTag(pszTagName, pszTagData)) == NULL)
  270. return (ErrGetErrorCode());
  271. ListAddTail(hTagList, (PLISTLINK) pMTD);
  272. }
  273. }
  274. return (0);
  275. }
  276. static void USmlFreeTagsList(HSLIST & hTagList)
  277. {
  278. MessageTagData *pMTD;
  279. while ((pMTD = (MessageTagData *) ListRemove(hTagList)) != INVALID_SLIST_PTR)
  280. USmlFreeTag(pMTD);
  281. }
  282. static int USmlLoadTags(FILE * pSpoolFile, HSLIST & hTagList)
  283. {
  284. DynString TagDS;
  285. StrDynInit(&TagDS);
  286. unsigned long ulFilePos = (unsigned long) ftell(pSpoolFile);
  287. char szSpoolLine[MAX_SPOOL_LINE] = "";
  288. char szTagName[256] = "";
  289. while (MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) != NULL) {
  290. if (IsEmptyString(szSpoolLine)) {
  291. if (StrDynSize(&TagDS) > 0) {
  292. if (USmlAddTag(hTagList, szTagName, StrDynGet(&TagDS)) < 0) {
  293. ErrorPush();
  294. StrDynFree(&TagDS);
  295. fseek(pSpoolFile, ulFilePos, SEEK_SET);
  296. return (ErrorPop());
  297. }
  298. SetEmptyString(szTagName);
  299. StrDynTruncate(&TagDS);
  300. }
  301. break;
  302. }
  303. if ((szSpoolLine[0] == ' ') || (szSpoolLine[0] == 't')) {
  304. if (IsEmptyString(szTagName)) {
  305. StrDynFree(&TagDS);
  306. fseek(pSpoolFile, ulFilePos, SEEK_SET);
  307. ErrSetErrorCode(ERR_INVALID_MESSAGE_FORMAT);
  308. return (ERR_INVALID_MESSAGE_FORMAT);
  309. }
  310. if ((StrDynAdd(&TagDS, "rn") < 0) ||
  311.     (StrDynAdd(&TagDS, szSpoolLine) < 0)) {
  312. ErrorPush();
  313. StrDynFree(&TagDS);
  314. fseek(pSpoolFile, ulFilePos, SEEK_SET);
  315. return (ErrorPop());
  316. }
  317. } else {
  318. if (StrDynSize(&TagDS) > 0) {
  319. if (USmlAddTag(hTagList, szTagName, StrDynGet(&TagDS)) < 0) {
  320. ErrorPush();
  321. StrDynFree(&TagDS);
  322. fseek(pSpoolFile, ulFilePos, SEEK_SET);
  323. return (ErrorPop());
  324. }
  325. SetEmptyString(szTagName);
  326. StrDynTruncate(&TagDS);
  327. }
  328. char *pszEndTag = strchr(szSpoolLine, ':');
  329. if (pszEndTag == NULL) {
  330. StrDynFree(&TagDS);
  331. fseek(pSpoolFile, ulFilePos, SEEK_SET);
  332. ErrSetErrorCode(ERR_INVALID_MESSAGE_FORMAT);
  333. return (ERR_INVALID_MESSAGE_FORMAT);
  334. }
  335. int iNameLength = Min((int) (pszEndTag - szSpoolLine),
  336.       sizeof(szTagName) - 1);
  337. char *pszTagValue = pszEndTag + 1;
  338. strncpy(szTagName, szSpoolLine, iNameLength);
  339. szTagName[iNameLength] = '';
  340. StrSkipSpaces(pszTagValue);
  341. if (StrDynAdd(&TagDS, pszTagValue) < 0) {
  342. ErrorPush();
  343. StrDynFree(&TagDS);
  344. fseek(pSpoolFile, ulFilePos, SEEK_SET);
  345. return (ErrorPop());
  346. }
  347. }
  348. ulFilePos = (unsigned long) ftell(pSpoolFile);
  349. }
  350. StrDynFree(&TagDS);
  351. return (0);
  352. }
  353. static int USmlDumpHeaders(FILE * pMsgFile, HSLIST & hTagList)
  354. {
  355. MessageTagData *pMTD = (MessageTagData *) ListFirst(hTagList);
  356. for (; pMTD != INVALID_SLIST_PTR; pMTD = (MessageTagData *)
  357.      ListNext(hTagList, (PLISTLINK) pMTD)) {
  358. fprintf(pMsgFile, "%s: %srn", pMTD->pszTagName, pMTD->pszTagData);
  359. }
  360. return (0);
  361. }
  362. static void USmlFreeData(SpoolFileData * pSFD)
  363. {
  364. USmlFreeTagsList(pSFD->hTagList);
  365. if (pSFD->ppszInfo != NULL)
  366. StrFreeStrings(pSFD->ppszInfo);
  367. if (pSFD->ppszFrom != NULL)
  368. StrFreeStrings(pSFD->ppszFrom);
  369. if (pSFD->pszMailFrom != NULL)
  370. SysFree(pSFD->pszMailFrom);
  371. if (pSFD->pszSendMailFrom != NULL)
  372. SysFree(pSFD->pszSendMailFrom);
  373. if (pSFD->ppszRcpt != NULL)
  374. StrFreeStrings(pSFD->ppszRcpt);
  375. if (pSFD->pszRcptTo != NULL)
  376. SysFree(pSFD->pszRcptTo);
  377. if (pSFD->pszSendRcptTo != NULL)
  378. SysFree(pSFD->pszSendRcptTo);
  379. if (pSFD->pszRelayDomain != NULL)
  380. SysFree(pSFD->pszRelayDomain);
  381. }
  382. char *USmlAddrConcat(char const *const *ppszStrings)
  383. {
  384. int ii;
  385. int iStrCount = StrStringsCount(ppszStrings);
  386. int iSumLength = 0;
  387. for (ii = 0; ii < iStrCount; ii++)
  388. iSumLength += strlen(ppszStrings[ii]) + 1;
  389. char *pszConcat = (char *) SysAlloc(iSumLength + 1);
  390. if (pszConcat == NULL)
  391. return (NULL);
  392. SetEmptyString(pszConcat);
  393. for (ii = 0; ii < iStrCount; ii++) {
  394. if (ii > 0)
  395. strcat(pszConcat, (ii == (iStrCount - 1)) ? ":" : ",");
  396. strcat(pszConcat, ppszStrings[ii]);
  397. }
  398. return (pszConcat);
  399. }
  400. char *USmlBuildSendMailFrom(char const *const *ppszFrom, char const *const *ppszRcpt)
  401. {
  402. int iRcptCount = StrStringsCount(ppszRcpt);
  403. int iFromCount = StrStringsCount(ppszFrom);
  404. if (iRcptCount == 0) {
  405. ErrSetErrorCode(ERR_BAD_FORWARD_PATH);
  406. return (NULL);
  407. }
  408. if (iRcptCount == 1)
  409. return (USmlAddrConcat(ppszFrom));
  410. int ii, iSumLength = strlen(ppszRcpt[0]) + 1;
  411. for (ii = 0; ii < iFromCount; ii++)
  412. iSumLength += strlen(ppszFrom[ii]) + 1;
  413. char *pszConcat = (char *) SysAlloc(iSumLength + 1);
  414. if (pszConcat == NULL)
  415. return (NULL);
  416. strcpy(pszConcat, ppszRcpt[0]);
  417. for (ii = 0; ii < iFromCount; ii++) {
  418. strcat(pszConcat, (ii == (iFromCount - 1)) ? ":" : ",");
  419. strcat(pszConcat, ppszFrom[ii]);
  420. }
  421. return (pszConcat);
  422. }
  423. char *USmlBuildSendRcptTo(char const *const *ppszFrom, char const *const *ppszRcpt)
  424. {
  425. int iRcptCount = StrStringsCount(ppszRcpt);
  426. int iFromCount = StrStringsCount(ppszFrom);
  427. if (iRcptCount == 0) {
  428. ErrSetErrorCode(ERR_BAD_FORWARD_PATH);
  429. return (NULL);
  430. }
  431. if (iRcptCount == 1)
  432. return (USmlAddrConcat(ppszRcpt));
  433. int ii;
  434. int iSumLength = 0;
  435. for (ii = 1; ii < iRcptCount; ii++)
  436. iSumLength += strlen(ppszRcpt[ii]) + 1;
  437. char *pszConcat = (char *) SysAlloc(iSumLength + 1);
  438. if (pszConcat == NULL)
  439. return (NULL);
  440. SetEmptyString(pszConcat);
  441. for (ii = 1; ii < iRcptCount; ii++) {
  442. if (ii > 1)
  443. strcat(pszConcat, (ii == (iRcptCount - 1)) ? ":" : ",");
  444. strcat(pszConcat, ppszRcpt[ii]);
  445. }
  446. return (pszConcat);
  447. }
  448. static int USmlLoadHandle(SpoolFileData * pSFD, const char *pszMessFilePath)
  449. {
  450. char szFName[SYS_MAX_PATH] = "";
  451. char szExt[SYS_MAX_PATH] = "";
  452. StrSNCpy(pSFD->szMessFilePath, pszMessFilePath);
  453. MscSplitPath(pszMessFilePath, NULL, szFName, szExt);
  454. SysSNPrintf(pSFD->szSpoolFile, sizeof(pSFD->szSpoolFile) - 1, "%s%s", szFName, szExt);
  455. FILE *pSpoolFile = fopen(pszMessFilePath, "rb");
  456. if (pSpoolFile == NULL) {
  457. ErrSetErrorCode(ERR_SPOOL_FILE_NOT_FOUND);
  458. return (ERR_SPOOL_FILE_NOT_FOUND);
  459. }
  460. char szSpoolLine[MAX_SPOOL_LINE] = "";
  461. ///////////////////////////////////////////////////////////////////////////////
  462. //  Read info ( 1st row of the spool file )
  463. ///////////////////////////////////////////////////////////////////////////////
  464. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  465.     ((pSFD->ppszInfo = StrTokenize(szSpoolLine, ";")) == NULL) ||
  466.     (StrStringsCount(pSFD->ppszInfo) < smiMax)) {
  467. fclose(pSpoolFile);
  468. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  469. return (ERR_INVALID_SPOOL_FILE);
  470. }
  471. ///////////////////////////////////////////////////////////////////////////////
  472. //  Read SMTP domain ( 2nd row of the spool file )
  473. ///////////////////////////////////////////////////////////////////////////////
  474. if (MscGetString(pSpoolFile, pSFD->szSMTPDomain, sizeof(pSFD->szSMTPDomain) - 1) == NULL) {
  475. fclose(pSpoolFile);
  476. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  477. return (ERR_INVALID_SPOOL_FILE);
  478. }
  479. ///////////////////////////////////////////////////////////////////////////////
  480. //  Read message ID ( 3rd row of the spool file )
  481. ///////////////////////////////////////////////////////////////////////////////
  482. if (MscGetString(pSpoolFile, pSFD->szMessageID, sizeof(pSFD->szMessageID) - 1) == NULL) {
  483. fclose(pSpoolFile);
  484. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  485. return (ERR_INVALID_SPOOL_FILE);
  486. }
  487. ///////////////////////////////////////////////////////////////////////////////
  488. //  Read "MAIL FROM:" ( 4th row of the spool file )
  489. ///////////////////////////////////////////////////////////////////////////////
  490. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  491.     (StrINComp(szSpoolLine, MAIL_FROM_STR) != 0)) {
  492. fclose(pSpoolFile);
  493. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  494. return (ERR_INVALID_SPOOL_FILE);
  495. }
  496. if ((pSFD->ppszFrom = USmtpGetPathStrings(szSpoolLine)) == NULL) {
  497. fclose(pSpoolFile);
  498. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  499. return (ERR_INVALID_SPOOL_FILE);
  500. }
  501. ///////////////////////////////////////////////////////////////////////////////
  502. //  Read "RCPT TO:" ( 5th row of the spool file )
  503. ///////////////////////////////////////////////////////////////////////////////
  504. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  505.     (StrINComp(szSpoolLine, RCPT_TO_STR) != 0)) {
  506. fclose(pSpoolFile);
  507. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  508. return (ERR_INVALID_SPOOL_FILE);
  509. }
  510. if ((pSFD->ppszRcpt = USmtpGetPathStrings(szSpoolLine)) == NULL) {
  511. fclose(pSpoolFile);
  512. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  513. return (ERR_INVALID_SPOOL_FILE);
  514. }
  515. ///////////////////////////////////////////////////////////////////////////////
  516. //  Check the presence of the init data mark ( 5th row of the spool file )
  517. ///////////////////////////////////////////////////////////////////////////////
  518. if ((MscGetString(pSpoolFile, szSpoolLine, sizeof(szSpoolLine) - 1) == NULL) ||
  519.     (strncmp(szSpoolLine, SPOOL_FILE_DATA_START, strlen(SPOOL_FILE_DATA_START)) != 0)) {
  520. fclose(pSpoolFile);
  521. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  522. return (ERR_INVALID_SPOOL_FILE);
  523. }
  524. ///////////////////////////////////////////////////////////////////////////////
  525. //  Get real message position
  526. ///////////////////////////////////////////////////////////////////////////////
  527. pSFD->ulMessageOffset = (unsigned long) ftell(pSpoolFile);
  528. ///////////////////////////////////////////////////////////////////////////////
  529. //  Build address strings
  530. ///////////////////////////////////////////////////////////////////////////////
  531. if (((pSFD->pszMailFrom = USmlAddrConcat(pSFD->ppszFrom)) == NULL) ||
  532.     ((pSFD->pszSendMailFrom =
  533.       USmlBuildSendMailFrom(pSFD->ppszFrom, pSFD->ppszRcpt)) == NULL) ||
  534.     ((pSFD->pszRcptTo = (char *) USmlAddrConcat(pSFD->ppszRcpt)) == NULL) ||
  535.     ((pSFD->pszSendRcptTo =
  536.       USmlBuildSendRcptTo(pSFD->ppszFrom, pSFD->ppszRcpt)) == NULL)) {
  537. fclose(pSpoolFile);
  538. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  539. return (ERR_INVALID_SPOOL_FILE);
  540. }
  541. ///////////////////////////////////////////////////////////////////////////////
  542. //  Check if it's a relay message
  543. ///////////////////////////////////////////////////////////////////////////////
  544. if (StrStringsCount(pSFD->ppszRcpt) > 1) {
  545. char szRelayDomain[MAX_ADDR_NAME] = "";
  546. if (USmtpSplitEmailAddr(pSFD->ppszRcpt[0], NULL, szRelayDomain) < 0) {
  547. fclose(pSpoolFile);
  548. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE);
  549. return (ERR_INVALID_SPOOL_FILE);
  550. }
  551. pSFD->pszRelayDomain = SysStrDup(szRelayDomain);
  552. }
  553. ///////////////////////////////////////////////////////////////////////////////
  554. //  Load message tags
  555. ///////////////////////////////////////////////////////////////////////////////
  556. if (USmlLoadTags(pSpoolFile, pSFD->hTagList) < 0)
  557. SysLogMessage(LOG_LEV_MESSAGE, "Invalid headers section : %sn",
  558.       pSFD->szSpoolFile);
  559. ///////////////////////////////////////////////////////////////////////////////
  560. //  Get spool file position
  561. ///////////////////////////////////////////////////////////////////////////////
  562. pSFD->ulMailDataOffset = (unsigned long) ftell(pSpoolFile);
  563. fclose(pSpoolFile);
  564. return (0);
  565. }
  566. static void USmlInitHandle(SpoolFileData * pSFD)
  567. {
  568. pSFD->ppszInfo = NULL;
  569. pSFD->ppszFrom = NULL;
  570. pSFD->pszMailFrom = NULL;
  571. pSFD->pszSendMailFrom = NULL;
  572. pSFD->ppszRcpt = NULL;
  573. pSFD->pszRcptTo = NULL;
  574. pSFD->pszSendRcptTo = NULL;
  575. pSFD->pszRelayDomain = NULL;
  576. SetEmptyString(pSFD->szSMTPDomain);
  577. pSFD->ulFlags = 0;
  578. ListInit(pSFD->hTagList);
  579. }
  580. static SpoolFileData *USmlAllocEmptyHandle(void)
  581. {
  582. ///////////////////////////////////////////////////////////////////////////////
  583. //  Structure allocation and initialization
  584. ///////////////////////////////////////////////////////////////////////////////
  585. SpoolFileData *pSFD = (SpoolFileData *) SysAlloc(sizeof(SpoolFileData));
  586. if (pSFD != NULL)
  587. USmlInitHandle(pSFD);
  588. return (pSFD);
  589. }
  590. SPLF_HANDLE USmlCreateHandle(const char *pszMessFilePath)
  591. {
  592. ///////////////////////////////////////////////////////////////////////////////
  593. //  Structure allocation and initialization
  594. ///////////////////////////////////////////////////////////////////////////////
  595. SpoolFileData *pSFD = USmlAllocEmptyHandle();
  596. if (pSFD == NULL)
  597. return (INVALID_SPLF_HANDLE);
  598. if (USmlLoadHandle(pSFD, pszMessFilePath) < 0) {
  599. USmlFreeData(pSFD);
  600. SysFree(pSFD);
  601. return (INVALID_SPLF_HANDLE);
  602. }
  603. return ((SPLF_HANDLE) pSFD);
  604. }
  605. void USmlCloseHandle(SPLF_HANDLE hFSpool)
  606. {
  607. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  608. USmlFreeData(pSFD);
  609. SysFree(pSFD);
  610. }
  611. int USmlReloadHandle(SPLF_HANDLE hFSpool)
  612. {
  613. ///////////////////////////////////////////////////////////////////////////////
  614. //  Structure allocation and initialization
  615. ///////////////////////////////////////////////////////////////////////////////
  616. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  617. SpoolFileData *pNewSFD = USmlAllocEmptyHandle();
  618. if (pNewSFD == NULL)
  619. return (ErrGetErrorCode());
  620. ///////////////////////////////////////////////////////////////////////////////
  621. //  Load the new spool file data
  622. ///////////////////////////////////////////////////////////////////////////////
  623. if (USmlLoadHandle(pNewSFD, pSFD->szMessFilePath) < 0) {
  624. ErrorPush();
  625. USmlFreeData(pNewSFD);
  626. SysFree(pNewSFD);
  627. return (ErrorPop());
  628. }
  629. ///////////////////////////////////////////////////////////////////////////////
  630. //  Free the original structure data and load the new one
  631. ///////////////////////////////////////////////////////////////////////////////
  632. USmlFreeData(pSFD);
  633. *pSFD = *pNewSFD;
  634. ///////////////////////////////////////////////////////////////////////////////
  635. //  We don't have to call USmlFreeData() since its content has been tranfered
  636. //  to the original structure to replace the old information
  637. ///////////////////////////////////////////////////////////////////////////////
  638. SysFree(pNewSFD);
  639. return (0);
  640. }
  641. char const *USmlGetRelayDomain(SPLF_HANDLE hFSpool)
  642. {
  643. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  644. return (pSFD->pszRelayDomain);
  645. }
  646. char const *USmlGetSpoolFilePath(SPLF_HANDLE hFSpool)
  647. {
  648. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  649. return (pSFD->szMessFilePath);
  650. }
  651. char const *USmlGetSpoolFile(SPLF_HANDLE hFSpool)
  652. {
  653. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  654. return (pSFD->szSpoolFile);
  655. }
  656. char const *USmlGetSMTPDomain(SPLF_HANDLE hFSpool)
  657. {
  658. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  659. return (pSFD->szSMTPDomain);
  660. }
  661. char const *USmlGetSmtpMessageID(SPLF_HANDLE hFSpool)
  662. {
  663. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  664. return (pSFD->szMessageID);
  665. }
  666. char const *const *USmlGetInfo(SPLF_HANDLE hFSpool)
  667. {
  668. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  669. return (pSFD->ppszInfo);
  670. }
  671. char const *const *USmlGetMailFrom(SPLF_HANDLE hFSpool)
  672. {
  673. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  674. return (pSFD->ppszFrom);
  675. }
  676. char const *USmlMailFrom(SPLF_HANDLE hFSpool)
  677. {
  678. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  679. return (pSFD->pszMailFrom);
  680. }
  681. char const *USmlSendMailFrom(SPLF_HANDLE hFSpool)
  682. {
  683. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  684. return (pSFD->pszSendMailFrom);
  685. }
  686. char const *const *USmlGetRcptTo(SPLF_HANDLE hFSpool)
  687. {
  688. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  689. return (pSFD->ppszRcpt);
  690. }
  691. char const *USmlRcptTo(SPLF_HANDLE hFSpool)
  692. {
  693. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  694. return (pSFD->pszRcptTo);
  695. }
  696. char const *USmlSendRcptTo(SPLF_HANDLE hFSpool)
  697. {
  698. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  699. return (pSFD->pszSendRcptTo);
  700. }
  701. static int USmlFlushMessageFile(SpoolFileData * pSFD)
  702. {
  703. char szTmpMsgFile[SYS_MAX_PATH] = "";
  704. SysSNPrintf(szTmpMsgFile, sizeof(szTmpMsgFile) - 1, "%s.flush", pSFD->szMessFilePath);
  705. ///////////////////////////////////////////////////////////////////////////////
  706. //  Create temporary file
  707. ///////////////////////////////////////////////////////////////////////////////
  708. FILE *pMsgFile = fopen(szTmpMsgFile, "wb");
  709. if (pMsgFile == NULL) {
  710. ErrSetErrorCode(ERR_FILE_CREATE, szTmpMsgFile);
  711. return (ERR_FILE_CREATE);
  712. }
  713. ///////////////////////////////////////////////////////////////////////////////
  714. //  Open message file
  715. ///////////////////////////////////////////////////////////////////////////////
  716. FILE *pMessFile = fopen(pSFD->szMessFilePath, "rb");
  717. if (pMessFile == NULL) {
  718. fclose(pMsgFile);
  719. CheckRemoveFile(szTmpMsgFile);
  720. ErrSetErrorCode(ERR_FILE_OPEN, pSFD->szMessFilePath);
  721. return (ERR_FILE_OPEN);
  722. }
  723. ///////////////////////////////////////////////////////////////////////////////
  724. //  Dump info section ( start = 0 - bytes = ulMessageOffset )
  725. ///////////////////////////////////////////////////////////////////////////////
  726. if (MscCopyFile(pMsgFile, pMessFile, 0, pSFD->ulMessageOffset) < 0) {
  727. ErrorPush();
  728. fclose(pMessFile);
  729. fclose(pMsgFile);
  730. CheckRemoveFile(szTmpMsgFile);
  731. return (ErrorPop());
  732. }
  733. ///////////////////////////////////////////////////////////////////////////////
  734. //  Dump message headers
  735. ///////////////////////////////////////////////////////////////////////////////
  736. if (USmlDumpHeaders(pMsgFile, pSFD->hTagList) < 0) {
  737. ErrorPush();
  738. fclose(pMessFile);
  739. fclose(pMsgFile);
  740. CheckRemoveFile(szTmpMsgFile);
  741. return (ErrorPop());
  742. }
  743. fprintf(pMsgFile, "rn");
  744. ///////////////////////////////////////////////////////////////////////////////
  745. //  Get the new message body offset
  746. ///////////////////////////////////////////////////////////////////////////////
  747. unsigned long ulMailDataOffset = (unsigned long) ftell(pMsgFile);
  748. ///////////////////////////////////////////////////////////////////////////////
  749. //  Dump message data ( start = ulMailDataOffset - bytes = -1 [EOF] )
  750. ///////////////////////////////////////////////////////////////////////////////
  751. if (MscCopyFile(pMsgFile, pMessFile, pSFD->ulMailDataOffset, (unsigned long) -1) < 0) {
  752. ErrorPush();
  753. fclose(pMessFile);
  754. fclose(pMsgFile);
  755. CheckRemoveFile(szTmpMsgFile);
  756. return (ErrorPop());
  757. }
  758. fclose(pMessFile);
  759. if (SysFileSync(pMsgFile) < 0) {
  760. ErrorPush();
  761. fclose(pMsgFile);
  762. CheckRemoveFile(szTmpMsgFile);
  763. return (ErrorPop());
  764. }
  765. if (fclose(pMsgFile)) {
  766. CheckRemoveFile(szTmpMsgFile);
  767. ErrSetErrorCode(ERR_FILE_WRITE, szTmpMsgFile);
  768. return (ERR_FILE_WRITE);
  769. }
  770. ///////////////////////////////////////////////////////////////////////////////
  771. //  Move the file
  772. ///////////////////////////////////////////////////////////////////////////////
  773. if ((SysRemove(pSFD->szMessFilePath) < 0) ||
  774.     (SysMoveFile(szTmpMsgFile, pSFD->szMessFilePath) < 0)) {
  775. ErrorPush();
  776. CheckRemoveFile(szTmpMsgFile);
  777. return (ErrorPop());
  778. }
  779. ///////////////////////////////////////////////////////////////////////////////
  780. //  Set the new message body offset
  781. ///////////////////////////////////////////////////////////////////////////////
  782. pSFD->ulMailDataOffset = ulMailDataOffset;
  783. return (0);
  784. }
  785. int USmlSyncChanges(SPLF_HANDLE hFSpool)
  786. {
  787. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  788. if (pSFD->ulFlags & SFF_HEADER_MODIFIED) {
  789. if (USmlFlushMessageFile(pSFD) == 0)
  790. pSFD->ulFlags &= ~SFF_HEADER_MODIFIED;
  791. }
  792. return (0);
  793. }
  794. int USmlGetMsgFileSection(SPLF_HANDLE hFSpool, FileSection & FS)
  795. {
  796. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  797. ///////////////////////////////////////////////////////////////////////////////
  798. //  Sync message file
  799. ///////////////////////////////////////////////////////////////////////////////
  800. if (USmlSyncChanges(hFSpool) < 0)
  801. return (ErrGetErrorCode());
  802. ///////////////////////////////////////////////////////////////////////////////
  803. //  Setup file section fields
  804. ///////////////////////////////////////////////////////////////////////////////
  805. ZeroData(FS);
  806. StrSNCpy(FS.szFilePath, pSFD->szMessFilePath);
  807. FS.ulStartOffset = pSFD->ulMessageOffset;
  808. FS.ulEndOffset = (unsigned long) -1;
  809. return (0);
  810. }
  811. int USmlWriteMailFile(SPLF_HANDLE hFSpool, FILE * pMsgFile)
  812. {
  813. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  814. ///////////////////////////////////////////////////////////////////////////////
  815. //  Dump message tags
  816. ///////////////////////////////////////////////////////////////////////////////
  817. if (USmlDumpHeaders(pMsgFile, pSFD->hTagList) < 0)
  818. return (ErrGetErrorCode());
  819. fprintf(pMsgFile, "rn");
  820. ///////////////////////////////////////////////////////////////////////////////
  821. //  Dump message data
  822. ///////////////////////////////////////////////////////////////////////////////
  823. FILE *pMessFile = fopen(pSFD->szMessFilePath, "rb");
  824. if (pMessFile == NULL) {
  825. ErrSetErrorCode(ERR_FILE_OPEN, pSFD->szMessFilePath);
  826. return (ERR_FILE_OPEN);
  827. }
  828. if (MscCopyFile(pMsgFile, pMessFile, pSFD->ulMailDataOffset, (unsigned long) -1) < 0) {
  829. ErrorPush();
  830. fclose(pMessFile);
  831. return (ErrorPop());
  832. }
  833. fclose(pMessFile);
  834. return (0);
  835. }
  836. char *USmlGetTag(SPLF_HANDLE hFSpool, char const *pszTagName, TAG_POSITION & TagPosition)
  837. {
  838. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  839. MessageTagData *pMTD = USmlFindTag(pSFD->hTagList, pszTagName, TagPosition);
  840. return ((pMTD != NULL) ? SysStrDup(pMTD->pszTagData) : NULL);
  841. }
  842. int USmlAddTag(SPLF_HANDLE hFSpool, char const *pszTagName, char const *pszTagData, int iUpdate)
  843. {
  844. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  845. if (USmlAddTag(pSFD->hTagList, pszTagName, pszTagData, iUpdate) < 0)
  846. return (ErrGetErrorCode());
  847. pSFD->ulFlags |= SFF_HEADER_MODIFIED;
  848. return (0);
  849. }
  850. int USmlSetTagAddress(SPLF_HANDLE hFSpool, char const *pszTagName, char const *pszAddress)
  851. {
  852. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  853. TAG_POSITION TagPosition = TAG_POSITION_INIT;
  854. char *pszOldAddress = USmlGetTag(hFSpool, pszTagName, TagPosition);
  855. if (pszOldAddress == NULL) {
  856. char szTagData[512] = "";
  857. SysSNPrintf(szTagData, sizeof(szTagData) - 1, "<%s>", pszAddress);
  858. if (USmlAddTag(pSFD->hTagList, pszTagName, szTagData, 1) < 0)
  859. return (ErrGetErrorCode());
  860. } else {
  861. char *pszOpen = strrchr(pszOldAddress, '<');
  862. if (pszOpen != NULL) {
  863. ///////////////////////////////////////////////////////////////////////////////
  864. //  Case : NAME <ADDRESS>
  865. ///////////////////////////////////////////////////////////////////////////////
  866. char *pszClose = strrchr(pszOpen + 1, '>');
  867. if (pszClose == NULL) {
  868. SysFree(pszOldAddress);
  869. ErrSetErrorCode(ERR_INVALID_MESSAGE_FORMAT);
  870. return (ERR_INVALID_MESSAGE_FORMAT);
  871. }
  872. DynString DS;
  873. StrDynInit(&DS);
  874. StrDynAdd(&DS, pszOldAddress, (int) (pszOpen - pszOldAddress) + 1);
  875. StrDynAdd(&DS, pszAddress);
  876. StrDynAdd(&DS, pszClose);
  877. SysFree(pszOldAddress);
  878. if (USmlAddTag(pSFD->hTagList, pszTagName, StrDynGet(&DS), 1) < 0) {
  879. ErrorPush();
  880. StrDynFree(&DS);
  881. return (ErrorPop());
  882. }
  883. StrDynFree(&DS);
  884. } else {
  885. ///////////////////////////////////////////////////////////////////////////////
  886. //  Case : ADDRESS
  887. ///////////////////////////////////////////////////////////////////////////////
  888. SysFree(pszOldAddress);
  889. if (USmlAddTag(pSFD->hTagList, pszTagName, pszAddress, 1) < 0)
  890. return (ErrGetErrorCode());
  891. }
  892. }
  893. return (0);
  894. }
  895. int USmlMapAddress(char const *pszAddress, char *pszDomain, char *pszName)
  896. {
  897. char szRmtDomain[MAX_ADDR_NAME] = "";
  898. char szRmtName[MAX_ADDR_NAME] = "";
  899. if (USmtpSplitEmailAddr(pszAddress, szRmtName, szRmtDomain) < 0)
  900. return (ErrGetErrorCode());
  901. ExtAlias *pExtAlias = ExAlGetAlias(szRmtDomain, szRmtName);
  902. if (pExtAlias == NULL)
  903. return (ErrGetErrorCode());
  904. strcpy(pszDomain, pExtAlias->pszDomain);
  905. strcpy(pszName, pExtAlias->pszName);
  906. ExAlFreeAlias(pExtAlias);
  907. return (0);
  908. }
  909. int USmlCreateMBFile(UserInfo * pUI, char const *pszFileName, SPLF_HANDLE hFSpool)
  910. {
  911. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  912. FILE *pMBFile = fopen(pszFileName, "wb");
  913. if (pMBFile == NULL) {
  914. ErrSetErrorCode(ERR_FILE_CREATE, pszFileName);
  915. return (ERR_FILE_CREATE);
  916. }
  917. ///////////////////////////////////////////////////////////////////////////////
  918. //  Check the existence of the return path string ( PSYNC messages have )
  919. ///////////////////////////////////////////////////////////////////////////////
  920. TAG_POSITION TagPosition = TAG_POSITION_INIT;
  921. char *pszReturnPath = USmlGetTag(hFSpool, "Return-Path", TagPosition);
  922. if (pszReturnPath == NULL) {
  923. ///////////////////////////////////////////////////////////////////////////////
  924. //  Build return path string
  925. ///////////////////////////////////////////////////////////////////////////////
  926. int iFromDomains = StrStringsCount(ppszFrom);
  927. char szDomain[MAX_ADDR_NAME] = "";
  928. char szName[MAX_ADDR_NAME] = "";
  929. char szReturnPath[1024] = "Return-Path: <>";
  930. if ((iFromDomains == 0) ||
  931.     (USmlMapAddress(ppszFrom[iFromDomains - 1], szDomain, szName) < 0)) {
  932. char *pszRetPath = USmlAddrConcat(ppszFrom);
  933. if (pszRetPath != NULL) {
  934. int iRetLength = strlen(pszRetPath);
  935. int iExtraLength = CStringSize("Return-Path: <>");
  936. if (iRetLength > (int) (sizeof(szReturnPath) - iExtraLength - 2))
  937. pszRetPath[sizeof(szReturnPath) - iExtraLength - 2] =
  938.     '';
  939. SysSNPrintf(szReturnPath, sizeof(szReturnPath) - 1,
  940.     "Return-Path: <%s>", pszRetPath);
  941. SysFree(pszRetPath);
  942. }
  943. } else {
  944. SysSNPrintf(szReturnPath, sizeof(szReturnPath) - 1,
  945.     "Return-Path: <%s@%s>", szName, szDomain);
  946. char szAddress[MAX_ADDR_NAME] = "";
  947. SysSNPrintf(szAddress, sizeof(szAddress) - 1, "%s@%s", szName, szDomain);
  948. USmlSetTagAddress(hFSpool, "Reply-To", szAddress);
  949. }
  950. fprintf(pMBFile, "%srn", szReturnPath);
  951. ///////////////////////////////////////////////////////////////////////////////
  952. //  Add "Delivered-To:" tag
  953. ///////////////////////////////////////////////////////////////////////////////
  954. char szUserAddress[MAX_ADDR_NAME] = "";
  955. UsrGetAddress(pUI, szUserAddress);
  956. fprintf(pMBFile, "Delivered-To: %srn", szUserAddress);
  957. } else
  958. SysFree(pszReturnPath);
  959. ///////////////////////////////////////////////////////////////////////////////
  960. //  Write mail file
  961. ///////////////////////////////////////////////////////////////////////////////
  962. if (USmlWriteMailFile(hFSpool, pMBFile) < 0) {
  963. ErrorPush();
  964. fclose(pMBFile);
  965. SysRemove(pszFileName);
  966. return (ErrorPop());
  967. }
  968. fclose(pMBFile);
  969. return (0);
  970. }
  971. int USmlVCreateSpoolFile(SPLF_HANDLE hFSpool, char const *pszFromUser,
  972.  char const *pszRcptUser, char const *pszFileName, va_list Headers)
  973. {
  974. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  975. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  976. char const *const *ppszInfo = USmlGetInfo(hFSpool);
  977. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  978. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  979. FILE *pSpoolFile = fopen(pszFileName, "wb");
  980. if (pSpoolFile == NULL) {
  981. ErrSetErrorCode(ERR_FILE_CREATE);
  982. return (ERR_FILE_CREATE);
  983. }
  984. ///////////////////////////////////////////////////////////////////////////////
  985. //  Write info line
  986. ///////////////////////////////////////////////////////////////////////////////
  987. USmtpWriteInfoLine(pSpoolFile, ppszInfo[smiClientAddr],
  988.    ppszInfo[smiServerAddr], ppszInfo[smiTime]);
  989. ///////////////////////////////////////////////////////////////////////////////
  990. //  Write SMTP domain
  991. ///////////////////////////////////////////////////////////////////////////////
  992. fprintf(pSpoolFile, "%srn", pszSMTPDomain);
  993. ///////////////////////////////////////////////////////////////////////////////
  994. //  Write message ID
  995. ///////////////////////////////////////////////////////////////////////////////
  996. fprintf(pSpoolFile, "%srn", pszSmtpMessageID);
  997. ///////////////////////////////////////////////////////////////////////////////
  998. //  Write "MAIL FROM:"
  999. ///////////////////////////////////////////////////////////////////////////////
  1000. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1001. fprintf(pSpoolFile, "MAIL FROM: <%s>rn",
  1002. (pszFromUser != NULL) ? pszFromUser : pszMailFrom);
  1003. ///////////////////////////////////////////////////////////////////////////////
  1004. //  Write "RCPT TO:"
  1005. ///////////////////////////////////////////////////////////////////////////////
  1006. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1007. fprintf(pSpoolFile, "RCPT TO: <%s>rn", (pszRcptUser != NULL) ? pszRcptUser : pszRcptTo);
  1008. ///////////////////////////////////////////////////////////////////////////////
  1009. //  Write SPOOL_FILE_DATA_START
  1010. ///////////////////////////////////////////////////////////////////////////////
  1011. fprintf(pSpoolFile, "%srn", SPOOL_FILE_DATA_START);
  1012. ///////////////////////////////////////////////////////////////////////////////
  1013. //  Write extra RFC822 headers
  1014. ///////////////////////////////////////////////////////////////////////////////
  1015. char const *pszHeader = NULL;
  1016. while ((pszHeader = va_arg(Headers, char *)) != NULL) {
  1017. char const *pszValue = va_arg(Headers, char *);
  1018. if (pszValue == NULL)
  1019. break;
  1020. if (!IsEmptyString(pszHeader))
  1021. fprintf(pSpoolFile, "%s: %srn", pszHeader, pszValue);
  1022. }
  1023. ///////////////////////////////////////////////////////////////////////////////
  1024. //  Than write mail data
  1025. ///////////////////////////////////////////////////////////////////////////////
  1026. if (USmlWriteMailFile(hFSpool, pSpoolFile) < 0) {
  1027. ErrorPush();
  1028. fclose(pSpoolFile);
  1029. SysRemove(pszFileName);
  1030. return (ErrorPop());
  1031. }
  1032. fclose(pSpoolFile);
  1033. return (0);
  1034. }
  1035. int USmlCreateSpoolFile(SPLF_HANDLE hFSpool, char const *pszFromUser,
  1036. char const *pszRcptUser, char const *pszFileName, ...)
  1037. {
  1038. va_list Headers;
  1039. va_start(Headers, pszFileName);
  1040. int iCreateResult = USmlVCreateSpoolFile(hFSpool, pszFromUser,
  1041.  pszRcptUser, pszFileName, Headers);
  1042. va_end(Headers);
  1043. return (iCreateResult);
  1044. }
  1045. static int USmlGetMailProcessFile(UserInfo * pUI, QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
  1046.   char *pszMPFilePath)
  1047. {
  1048. ///////////////////////////////////////////////////////////////////////////////
  1049. //  Get the custom spool file associated with this message
  1050. ///////////////////////////////////////////////////////////////////////////////
  1051. if (USmlGetUserCustomSpoolFile(hQueue, hMessage, pszMPFilePath) < 0)
  1052. return (ErrGetErrorCode());
  1053. ///////////////////////////////////////////////////////////////////////////////
  1054. //  If the file already exist inside the spool, just return the latest
  1055. ///////////////////////////////////////////////////////////////////////////////
  1056. if (SysExistFile(pszMPFilePath))
  1057. return (0);
  1058. ///////////////////////////////////////////////////////////////////////////////
  1059. //  Try to get a new copy from the user one. It'll fail if the account is not
  1060. //  handled with a custom mail processing
  1061. ///////////////////////////////////////////////////////////////////////////////
  1062. return (UsrGetMailProcessFile(pUI, pszMPFilePath));
  1063. }
  1064. int USmlProcessLocalUserMessage(SVRCFG_HANDLE hSvrConfig, UserInfo * pUI, SPLF_HANDLE hFSpool,
  1065. QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
  1066. LocalMailProcConfig & LMPC)
  1067. {
  1068. ///////////////////////////////////////////////////////////////////////////////
  1069. //  Exist user custom message processing ?
  1070. ///////////////////////////////////////////////////////////////////////////////
  1071. char szMPFile[SYS_MAX_PATH] = "";
  1072. if (USmlGetMailProcessFile(pUI, hQueue, hMessage, szMPFile) < 0) {
  1073. ///////////////////////////////////////////////////////////////////////////////
  1074. //  Apply filters ...
  1075. ///////////////////////////////////////////////////////////////////////////////
  1076. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_INBOUND) < 0)
  1077. return (ErrGetErrorCode());
  1078. ///////////////////////////////////////////////////////////////////////////////
  1079. //  Create mailbox file ...
  1080. ///////////////////////////////////////////////////////////////////////////////
  1081. char szMBFile[SYS_MAX_PATH] = "";
  1082. SysGetTmpFile(szMBFile);
  1083. if (USmlCreateMBFile(pUI, szMBFile, hFSpool) < 0)
  1084. return (ErrGetErrorCode());
  1085. ///////////////////////////////////////////////////////////////////////////////
  1086. //  and send it home
  1087. ///////////////////////////////////////////////////////////////////////////////
  1088. char const *pszMessageID = USmlGetSpoolFile(hFSpool);
  1089. if (UsrMoveToMailBox(pUI, szMBFile, pszMessageID) < 0) {
  1090. ErrorPush();
  1091. SysRemove(szMBFile);
  1092. return (ErrorPop());
  1093. }
  1094. ///////////////////////////////////////////////////////////////////////////////
  1095. //  Log operation
  1096. ///////////////////////////////////////////////////////////////////////////////
  1097. if (LMPC.ulFlags & LMPCF_LOG_ENABLED) {
  1098. char szLocalAddress[MAX_ADDR_NAME] = "";
  1099. USmlLogMessage(hFSpool, "LOCAL", UsrGetAddress(pUI, szLocalAddress));
  1100. }
  1101. } else {
  1102. ///////////////////////////////////////////////////////////////////////////////
  1103. //  Process custom mailings
  1104. ///////////////////////////////////////////////////////////////////////////////
  1105. if (USmlProcessCustomMailingFile(hSvrConfig, pUI, hFSpool, hQueue, hMessage,
  1106.  szMPFile, LMPC) < 0)
  1107. return (ErrGetErrorCode());
  1108. }
  1109. return (0);
  1110. }
  1111. static int USmlProcessCustomMailingFile(SVRCFG_HANDLE hSvrConfig, UserInfo * pUI,
  1112. SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1113. QMSG_HANDLE hMessage, char const *pszMPFile,
  1114. LocalMailProcConfig & LMPC)
  1115. {
  1116. ///////////////////////////////////////////////////////////////////////////////
  1117. //  Open the mail processing file
  1118. ///////////////////////////////////////////////////////////////////////////////
  1119. FILE *pMPFile = fopen(pszMPFile, "rt");
  1120. if (pMPFile == NULL) {
  1121. ErrSetErrorCode(ERR_FILE_OPEN, pszMPFile);
  1122. return (ERR_FILE_OPEN);
  1123. }
  1124. ///////////////////////////////////////////////////////////////////////////////
  1125. //  Create pushback command file
  1126. ///////////////////////////////////////////////////////////////////////////////
  1127. char szTmpFile[SYS_MAX_PATH] = "";
  1128. SysGetTmpFile(szTmpFile);
  1129. FILE *pPushBFile = fopen(szTmpFile, "wt");
  1130. if (pPushBFile == NULL) {
  1131. fclose(pMPFile);
  1132. ErrSetErrorCode(ERR_FILE_CREATE, szTmpFile);
  1133. return (ERR_FILE_CREATE);
  1134. }
  1135. int iPushBackCmds = 0;
  1136. char szCmdLine[CUSTOM_CMD_LINE_MAX] = "";
  1137. while (MscGetConfigLine(szCmdLine, sizeof(szCmdLine) - 1, pMPFile) != NULL) {
  1138. char **ppszCmdTokens = StrGetTabLineStrings(szCmdLine);
  1139. if (ppszCmdTokens == NULL)
  1140. continue;
  1141. int iFieldsCount = StrStringsCount(ppszCmdTokens);
  1142. if (iFieldsCount > 0) {
  1143. ///////////////////////////////////////////////////////////////////////////////
  1144. //  Do command line macro substitution
  1145. ///////////////////////////////////////////////////////////////////////////////
  1146. USmlCmdMacroSubstitutes(ppszCmdTokens, pUI, hFSpool);
  1147. int iCmdResult = 0;
  1148. if (stricmp(ppszCmdTokens[0], "external") == 0)
  1149. iCmdResult =
  1150. USmlCmd_external(ppszCmdTokens, iFieldsCount, hSvrConfig, pUI,
  1151.  hFSpool, hQueue, hMessage, LMPC);
  1152. else if (stricmp(ppszCmdTokens[0], "filter") == 0)
  1153. iCmdResult =
  1154. USmlCmd_filter(ppszCmdTokens, iFieldsCount, hSvrConfig, pUI,
  1155.        hFSpool, hQueue, hMessage, LMPC);
  1156. else if (stricmp(ppszCmdTokens[0], "mailbox") == 0)
  1157. iCmdResult =
  1158. USmlCmd_mailbox(ppszCmdTokens, iFieldsCount, hSvrConfig, pUI,
  1159. hFSpool, hQueue, hMessage, LMPC);
  1160. else if (stricmp(ppszCmdTokens[0], "redirect") == 0)
  1161. iCmdResult =
  1162. USmlCmd_redirect(ppszCmdTokens, iFieldsCount, hSvrConfig, pUI,
  1163.  hFSpool, hQueue, hMessage, LMPC);
  1164. else if (stricmp(ppszCmdTokens[0], "lredirect") == 0)
  1165. iCmdResult =
  1166. USmlCmd_lredirect(ppszCmdTokens, iFieldsCount, hSvrConfig,
  1167.   pUI, hFSpool, hQueue, hMessage, LMPC);
  1168. else if (stricmp(ppszCmdTokens[0], "smtprelay") == 0)
  1169. iCmdResult =
  1170. USmlCmd_smtprelay(ppszCmdTokens, iFieldsCount, hSvrConfig,
  1171.   pUI, hFSpool, hQueue, hMessage, LMPC);
  1172. else {
  1173. SysLogMessage(LOG_LEV_ERROR,
  1174.       "Invalid command "%s" in file "%s"n",
  1175.       ppszCmdTokens[0], pszMPFile);
  1176. }
  1177. ///////////////////////////////////////////////////////////////////////////////
  1178. //  Check for the stop-processing error code
  1179. ///////////////////////////////////////////////////////////////////////////////
  1180. if (iCmdResult == SMAIL_STOP_PROCESSING) {
  1181. StrFreeStrings(ppszCmdTokens);
  1182. break;
  1183. }
  1184. ///////////////////////////////////////////////////////////////////////////////
  1185. //  Test if we must save a failed command
  1186. //  <0 = Error ; ==0 = Success ; >0 = Transient error ( save the command )
  1187. ///////////////////////////////////////////////////////////////////////////////
  1188. if (iCmdResult > 0) {
  1189. fprintf(pPushBFile, "%sn", szCmdLine);
  1190. ++iPushBackCmds;
  1191. }
  1192. ///////////////////////////////////////////////////////////////////////////////
  1193. //  An error code might result if filters blocked the message. If this is the
  1194. //  case QueCheckMessage() will return error and we MUST stop processing
  1195. ///////////////////////////////////////////////////////////////////////////////
  1196. if ((iCmdResult < 0) && (QueCheckMessage(hQueue, hMessage) < 0)) {
  1197. ErrorPush();
  1198. StrFreeStrings(ppszCmdTokens);
  1199. fclose(pPushBFile);
  1200. fclose(pMPFile);
  1201. SysRemove(szTmpFile);
  1202. return (ErrorPop());
  1203. }
  1204. }
  1205. StrFreeStrings(ppszCmdTokens);
  1206. }
  1207. fclose(pPushBFile);
  1208. fclose(pMPFile);
  1209. SysRemove(pszMPFile);
  1210. if (iPushBackCmds > 0) {
  1211. ///////////////////////////////////////////////////////////////////////////////
  1212. //  If commands left out of processing, push them into the custom file
  1213. ///////////////////////////////////////////////////////////////////////////////
  1214. if (MscMoveFile(szTmpFile, pszMPFile) < 0)
  1215. return (ErrGetErrorCode());
  1216. ErrSetErrorCode(ERR_INCOMPLETE_PROCESSING);
  1217. return (ERR_INCOMPLETE_PROCESSING);
  1218. }
  1219. SysRemove(szTmpFile);
  1220. return (0);
  1221. }
  1222. static int USmlCmdMacroSubstitutes(char **ppszCmdTokens, UserInfo * pUI, SPLF_HANDLE hFSpool)
  1223. {
  1224. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  1225. char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
  1226. char const *const *ppszRcpt = USmlGetRcptTo(hFSpool);
  1227. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  1228. char const *pszMessageID = USmlGetSpoolFile(hFSpool);
  1229. int iFromDomains = StrStringsCount(ppszFrom);
  1230. int iRcptDomains = StrStringsCount(ppszRcpt);
  1231. FileSection FS;
  1232. ///////////////////////////////////////////////////////////////////////////////
  1233. //  This function retrieve the spool file message section and sync the content.
  1234. //  This is necessary before passing the file name to external commands.
  1235. ///////////////////////////////////////////////////////////////////////////////
  1236. if (USmlGetMsgFileSection(hFSpool, FS) < 0)
  1237. return (ErrGetErrorCode());
  1238. for (int ii = 0; ppszCmdTokens[ii] != NULL; ii++) {
  1239. if (strcmp(ppszCmdTokens[ii], "@@FROM") == 0) {
  1240. char *pszNewValue =
  1241. SysStrDup((iFromDomains > 0) ? ppszFrom[iFromDomains - 1] : "");
  1242. if (pszNewValue == NULL)
  1243. return (ErrGetErrorCode());
  1244. SysFree(ppszCmdTokens[ii]);
  1245. ppszCmdTokens[ii] = pszNewValue;
  1246. } else if (strcmp(ppszCmdTokens[ii], "@@RCPT") == 0) {
  1247. char *pszNewValue =
  1248. SysStrDup((iRcptDomains > 0) ? ppszRcpt[iRcptDomains - 1] : "");
  1249. if (pszNewValue == NULL)
  1250. return (ErrGetErrorCode());
  1251. SysFree(ppszCmdTokens[ii]);
  1252. ppszCmdTokens[ii] = pszNewValue;
  1253. } else if (strcmp(ppszCmdTokens[ii], "@@RRCPT") == 0) {
  1254. char szUserAddress[MAX_ADDR_NAME] = "";
  1255. UsrGetAddress(pUI, szUserAddress);
  1256. char *pszNewValue = SysStrDup(szUserAddress);
  1257. if (pszNewValue == NULL)
  1258. return (ErrGetErrorCode());
  1259. SysFree(ppszCmdTokens[ii]);
  1260. ppszCmdTokens[ii] = pszNewValue;
  1261. } else if (strcmp(ppszCmdTokens[ii], "@@FILE") == 0) {
  1262. char *pszNewValue = SysStrDup(FS.szFilePath);
  1263. if (pszNewValue == NULL)
  1264. return (ErrGetErrorCode());
  1265. SysFree(ppszCmdTokens[ii]);
  1266. ppszCmdTokens[ii] = pszNewValue;
  1267. } else if (strcmp(ppszCmdTokens[ii], "@@MSGID") == 0) {
  1268. char *pszNewValue = SysStrDup(pszMessageID);
  1269. if (pszNewValue == NULL)
  1270. return (ErrGetErrorCode());
  1271. SysFree(ppszCmdTokens[ii]);
  1272. ppszCmdTokens[ii] = pszNewValue;
  1273. } else if (strcmp(ppszCmdTokens[ii], "@@MSGREF") == 0) {
  1274. char *pszNewValue = SysStrDup(pszSmtpMessageID);
  1275. if (pszNewValue == NULL)
  1276. return (ErrGetErrorCode());
  1277. SysFree(ppszCmdTokens[ii]);
  1278. ppszCmdTokens[ii] = pszNewValue;
  1279. } else if (strcmp(ppszCmdTokens[ii], "@@TMPFILE") == 0) {
  1280. char szTmpFile[SYS_MAX_PATH] = "";
  1281. SysGetTmpFile(szTmpFile);
  1282. if (MscCopyFile(szTmpFile, FS.szFilePath) < 0) {
  1283. ErrorPush();
  1284. CheckRemoveFile(szTmpFile);
  1285. return (ErrorPop());
  1286. }
  1287. char *pszNewValue = SysStrDup(szTmpFile);
  1288. if (pszNewValue == NULL)
  1289. return (ErrGetErrorCode());
  1290. SysFree(ppszCmdTokens[ii]);
  1291. ppszCmdTokens[ii] = pszNewValue;
  1292. } else if (strcmp(ppszCmdTokens[ii], "@@USERAUTH") == 0) {
  1293. char szAuthName[MAX_ADDR_NAME] = "-";
  1294. USmlMessageAuth(hFSpool, szAuthName, sizeof(szAuthName) - 1);
  1295. char *pszNewValue = SysStrDup(szAuthName);
  1296. if (pszNewValue == NULL)
  1297. return (ErrGetErrorCode());
  1298. SysFree(ppszCmdTokens[ii]);
  1299. ppszCmdTokens[ii] = pszNewValue;
  1300. }
  1301. }
  1302. return (0);
  1303. }
  1304. static int USmlCmd_external(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  1305.     UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1306.     QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC)
  1307. {
  1308. ///////////////////////////////////////////////////////////////////////////////
  1309. //  Apply filters ...
  1310. ///////////////////////////////////////////////////////////////////////////////
  1311. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_INBOUND) < 0)
  1312. return (ErrGetErrorCode());
  1313. if (iNumTokens < 5) {
  1314. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1315. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1316. }
  1317. int iPriority = atoi(ppszCmdTokens[1]);
  1318. int iWaitTimeout = atoi(ppszCmdTokens[2]);
  1319. int iExitStatus = 0;
  1320. if (SysExec(ppszCmdTokens[3], &ppszCmdTokens[3], iWaitTimeout, iPriority,
  1321.     &iExitStatus) < 0) {
  1322. ErrorPush();
  1323. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1324. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1325. ErrLogMessage(LOG_LEV_MESSAGE,
  1326.       "USMAIL EXTRN-Send Prg = "%s" From = "%s" To = "%s" Failed !n",
  1327.       ppszCmdTokens[3], pszMailFrom, pszRcptTo);
  1328. QueUtErrLogMessage(hQueue, hMessage,
  1329.    "USMAIL EXTRN-Send Prg = "%s" From = "%s" To = "%s" Failed !n",
  1330.    ppszCmdTokens[3], pszMailFrom, pszRcptTo);
  1331. return (ErrorPop());
  1332. }
  1333. ///////////////////////////////////////////////////////////////////////////////
  1334. //  Log operation
  1335. ///////////////////////////////////////////////////////////////////////////////
  1336. if (LMPC.ulFlags & LMPCF_LOG_ENABLED)
  1337. USmlLogMessage(hFSpool, "EXTRN", ppszCmdTokens[3]);
  1338. return ((iExitStatus == SMAIL_EXTERNAL_EXIT_BREAK) ? SMAIL_STOP_PROCESSING: 0);
  1339. }
  1340. static int USmlCmd_filter(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  1341.   UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1342.   QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC)
  1343. {
  1344. if (iNumTokens < 5) {
  1345. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1346. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1347. }
  1348. int iPriority = atoi(ppszCmdTokens[1]);
  1349. int iWaitTimeout = atoi(ppszCmdTokens[2]);
  1350. int iExitStatus = 0;
  1351. if (SysExec(ppszCmdTokens[3], &ppszCmdTokens[3], iWaitTimeout, iPriority,
  1352.     &iExitStatus) < 0) {
  1353. ErrorPush();
  1354. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1355. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1356. ErrLogMessage(LOG_LEV_MESSAGE,
  1357.       "USMAIL FILTER Prg = "%s" From = "%s" To = "%s" Failed !n",
  1358.       ppszCmdTokens[3], pszMailFrom, pszRcptTo);
  1359. QueUtErrLogMessage(hQueue, hMessage,
  1360.    "USMAIL FILTER Prg = "%s" From = "%s" To = "%s" Failed !n",
  1361.    ppszCmdTokens[3], pszMailFrom, pszRcptTo);
  1362. return (ErrorPop());
  1363. }
  1364. ///////////////////////////////////////////////////////////////////////////////
  1365. //  Log operation
  1366. ///////////////////////////////////////////////////////////////////////////////
  1367. if (LMPC.ulFlags & LMPCF_LOG_ENABLED)
  1368. USmlLogMessage(hFSpool, "FILTER", ppszCmdTokens[3]);
  1369. ///////////////////////////////////////////////////////////////////////////////
  1370. //  Separate code from flags
  1371. ///////////////////////////////////////////////////////////////////////////////
  1372. int iExitFlags = iExitStatus & FILTER_FLAGS_MASK;
  1373. iExitStatus &= ~FILTER_FLAGS_MASK;
  1374. if ((iExitStatus == FILTER_OUT_EXITCODE) ||
  1375.     (iExitStatus == FILTER_OUT_NN_EXITCODE) ||
  1376.     (iExitStatus == FILTER_OUT_NNF_EXITCODE)) {
  1377. ///////////////////////////////////////////////////////////////////////////////
  1378. //  Filter out message
  1379. ///////////////////////////////////////////////////////////////////////////////
  1380. char *pszRejMsg = FilGetFilterRejMessage(USmlGetSpoolFilePath(hFSpool));
  1381. if (iExitStatus == FILTER_OUT_EXITCODE)
  1382. QueUtNotifyPermErrDelivery(hQueue, hMessage, NULL,
  1383.    (pszRejMsg != NULL) ? pszRejMsg :
  1384.    ErrGetErrorString(ERR_FILTERED_MESSAGE),
  1385.    NULL, true);
  1386. else if (iExitStatus == FILTER_OUT_NN_EXITCODE)
  1387. QueCleanupMessage(hQueue, hMessage,
  1388.   !QueUtRemoveSpoolErrors());
  1389. else
  1390. QueCleanupMessage(hQueue, hMessage, false);
  1391. if (pszRejMsg != NULL)
  1392. SysFree(pszRejMsg);
  1393. ErrSetErrorCode(ERR_FILTERED_MESSAGE);
  1394. return (ERR_FILTERED_MESSAGE);
  1395. } else if (iExitStatus == FILTER_MODIFY_EXITCODE) {
  1396. ///////////////////////////////////////////////////////////////////////////////
  1397. //  Filter modified the message, we need to reload the spool handle
  1398. ///////////////////////////////////////////////////////////////////////////////
  1399. if (USmlReloadHandle(hFSpool) < 0) {
  1400. ErrorPush();
  1401. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1402. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1403. SysLogMessage(LOG_LEV_MESSAGE,
  1404.       "Filter error [ Modified message corrupted ]: Sender = "%s" Recipient = "%s" (%s)n",
  1405.       pszMailFrom, pszRcptTo,
  1406.       ppszCmdTokens[3]);
  1407. QueUtErrLogMessage(hQueue, hMessage,
  1408.    "Filter error [ Modified message corrupted ]: Sender = "%s" Recipient = "%s" (%s)n",
  1409.    pszMailFrom, pszRcptTo,
  1410.    ppszCmdTokens[3]);
  1411. QueCleanupMessage(hQueue, hMessage, true);
  1412. return (ErrorPop());
  1413. }
  1414. }
  1415. return ((iExitFlags & FILTER_FLAGS_BREAK) ? SMAIL_STOP_PROCESSING: 0);
  1416. }
  1417. static int USmlCmd_mailbox(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  1418.    UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1419.    QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC)
  1420. {
  1421. ///////////////////////////////////////////////////////////////////////////////
  1422. //  Apply filters ...
  1423. ///////////////////////////////////////////////////////////////////////////////
  1424. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_INBOUND) < 0)
  1425. return (ErrGetErrorCode());
  1426. if (iNumTokens != 1) {
  1427. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1428. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1429. }
  1430. ///////////////////////////////////////////////////////////////////////////////
  1431. //  Create mailbox file ...
  1432. ///////////////////////////////////////////////////////////////////////////////
  1433. char szMBFile[SYS_MAX_PATH] = "";
  1434. SysGetTmpFile(szMBFile);
  1435. if (USmlCreateMBFile(pUI, szMBFile, hFSpool) < 0)
  1436. return (ErrGetErrorCode());
  1437. ///////////////////////////////////////////////////////////////////////////////
  1438. //  and send it home
  1439. ///////////////////////////////////////////////////////////////////////////////
  1440. char const *pszMessageID = USmlGetSpoolFile(hFSpool);
  1441. if (UsrMoveToMailBox(pUI, szMBFile, pszMessageID) < 0) {
  1442. ErrorPush();
  1443. SysRemove(szMBFile);
  1444. return (ErrorPop());
  1445. }
  1446. ///////////////////////////////////////////////////////////////////////////////
  1447. //  Log operation
  1448. ///////////////////////////////////////////////////////////////////////////////
  1449. if (LMPC.ulFlags & LMPCF_LOG_ENABLED) {
  1450. char szLocalAddress[MAX_ADDR_NAME] = "";
  1451. USmlLogMessage(hFSpool, "LOCAL", UsrGetAddress(pUI, szLocalAddress));
  1452. }
  1453. return (0);
  1454. }
  1455. static int USmlCmd_redirect(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  1456.     UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1457.     QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC)
  1458. {
  1459. if (iNumTokens < 2) {
  1460. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1461. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1462. }
  1463. char szUserAddress[MAX_ADDR_NAME] = "";
  1464. UsrGetAddress(pUI, szUserAddress);
  1465. ///////////////////////////////////////////////////////////////////////////////
  1466. //  Redirection loop
  1467. ///////////////////////////////////////////////////////////////////////////////
  1468. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  1469. for (int ii = 1; ppszCmdTokens[ii] != NULL; ii++) {
  1470. ///////////////////////////////////////////////////////////////////////////////
  1471. //  Get message handle
  1472. ///////////////////////////////////////////////////////////////////////////////
  1473. QMSG_HANDLE hRedirMessage = QueCreateMessage(hSpoolQueue);
  1474. if (hRedirMessage == INVALID_QMSG_HANDLE)
  1475. return (ErrGetErrorCode());
  1476. char szQueueFilePath[SYS_MAX_PATH] = "";
  1477. QueGetFilePath(hSpoolQueue, hRedirMessage, szQueueFilePath);
  1478. char szAliasAddr[MAX_ADDR_NAME] = "";
  1479. if (strchr(ppszCmdTokens[ii], '@') == NULL)
  1480. SysSNPrintf(szAliasAddr, sizeof(szAliasAddr) - 1, "%s@%s",
  1481.     pUI->pszName, ppszCmdTokens[ii]);
  1482. else
  1483. StrSNCpy(szAliasAddr, ppszCmdTokens[ii]);
  1484. if (USmlCreateSpoolFile(hFSpool, NULL, szAliasAddr, szQueueFilePath,
  1485. "X-Deliver-To", szUserAddress, NULL) < 0) {
  1486. ErrorPush();
  1487. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1488. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1489. return (ErrorPop());
  1490. }
  1491. ///////////////////////////////////////////////////////////////////////////////
  1492. //  Transfer file to the spool
  1493. ///////////////////////////////////////////////////////////////////////////////
  1494. if (QueCommitMessage(hSpoolQueue, hRedirMessage) < 0) {
  1495. ErrorPush();
  1496. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1497. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1498. return (ErrorPop());
  1499. }
  1500. ///////////////////////////////////////////////////////////////////////////////
  1501. //  Log the redir operation
  1502. ///////////////////////////////////////////////////////////////////////////////
  1503. if (LMPC.ulFlags & LMPCF_LOG_ENABLED)
  1504. USmlLogMessage(hFSpool, "REDIR", ppszCmdTokens[ii]);
  1505. }
  1506. return (0);
  1507. }
  1508. static int USmlCmd_lredirect(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  1509.      UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1510.      QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC)
  1511. {
  1512. if (iNumTokens < 2) {
  1513. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1514. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1515. }
  1516. char szUserAddress[MAX_ADDR_NAME] = "";
  1517. UsrGetAddress(pUI, szUserAddress);
  1518. ///////////////////////////////////////////////////////////////////////////////
  1519. //  Redirection loop
  1520. ///////////////////////////////////////////////////////////////////////////////
  1521. for (int ii = 1; ppszCmdTokens[ii] != NULL; ii++) {
  1522. ///////////////////////////////////////////////////////////////////////////////
  1523. //  Get message handle
  1524. ///////////////////////////////////////////////////////////////////////////////
  1525. QMSG_HANDLE hRedirMessage = QueCreateMessage(hSpoolQueue);
  1526. if (hRedirMessage == INVALID_QMSG_HANDLE)
  1527. return (ErrGetErrorCode());
  1528. char szQueueFilePath[SYS_MAX_PATH] = "";
  1529. QueGetFilePath(hSpoolQueue, hRedirMessage, szQueueFilePath);
  1530. char szAliasAddr[MAX_ADDR_NAME] = "";
  1531. if (strchr(ppszCmdTokens[ii], '@') == NULL)
  1532. SysSNPrintf(szAliasAddr, sizeof(szAliasAddr) - 1, "%s@%s",
  1533.     pUI->pszName, ppszCmdTokens[ii]);
  1534. else
  1535. StrSNCpy(szAliasAddr, ppszCmdTokens[ii]);
  1536. if (USmlCreateSpoolFile(hFSpool, szUserAddress, szAliasAddr, szQueueFilePath,
  1537. "X-Deliver-To", szUserAddress, NULL) < 0) {
  1538. ErrorPush();
  1539. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1540. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1541. return (ErrorPop());
  1542. }
  1543. ///////////////////////////////////////////////////////////////////////////////
  1544. //  Transfer file to the spool
  1545. ///////////////////////////////////////////////////////////////////////////////
  1546. if (QueCommitMessage(hSpoolQueue, hRedirMessage) < 0) {
  1547. ErrorPush();
  1548. QueCleanupMessage(hSpoolQueue, hRedirMessage);
  1549. QueCloseMessage(hSpoolQueue, hRedirMessage);
  1550. return (ErrorPop());
  1551. }
  1552. ///////////////////////////////////////////////////////////////////////////////
  1553. //  Log the redir operation
  1554. ///////////////////////////////////////////////////////////////////////////////
  1555. if (LMPC.ulFlags & LMPCF_LOG_ENABLED)
  1556. USmlLogMessage(hFSpool, "LREDIR", ppszCmdTokens[ii]);
  1557. }
  1558. return (0);
  1559. }
  1560. static int USmlCmd_smtprelay(char **ppszCmdTokens, int iNumTokens, SVRCFG_HANDLE hSvrConfig,
  1561.      UserInfo * pUI, SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1562.      QMSG_HANDLE hMessage, LocalMailProcConfig & LMPC)
  1563. {
  1564. ///////////////////////////////////////////////////////////////////////////////
  1565. //  Apply filters ...
  1566. ///////////////////////////////////////////////////////////////////////////////
  1567. if (FilFilterMessage(hFSpool, hQueue, hMessage, FILTER_MODE_OUTBOUND) < 0)
  1568. return (ErrGetErrorCode());
  1569. if (iNumTokens < 2) {
  1570. ErrSetErrorCode(ERR_BAD_MAILPROC_CMD_SYNTAX);
  1571. return (ERR_BAD_MAILPROC_CMD_SYNTAX);
  1572. }
  1573. char **ppszRelays = NULL;
  1574. if (ppszCmdTokens[1][0] == '#') {
  1575. if ((ppszRelays = StrTokenize(ppszCmdTokens[1] + 1, ",")) != NULL) {
  1576. int iRelayCount = StrStringsCount(ppszRelays);
  1577. srand((unsigned int) time(NULL));
  1578. for (int ii = 0; ii < (iRelayCount / 2); ii++) {
  1579. int iSwap1 = rand() % iRelayCount;
  1580. int iSwap2 = rand() % iRelayCount;
  1581. char *pszRly1 = ppszRelays[iSwap1];
  1582. char *pszRly2 = ppszRelays[iSwap2];
  1583. ppszRelays[iSwap1] = pszRly2;
  1584. ppszRelays[iSwap2] = pszRly1;
  1585. }
  1586. }
  1587. } else
  1588. ppszRelays = StrTokenize(ppszCmdTokens[1], ",");
  1589. if (ppszRelays == NULL)
  1590. return (ErrGetErrorCode());
  1591. ///////////////////////////////////////////////////////////////////////////////
  1592. //  This function retrieve the spool file message section and sync the content.
  1593. //  This is necessary before sending the file
  1594. ///////////////////////////////////////////////////////////////////////////////
  1595. FileSection FS;
  1596. if (USmlGetMsgFileSection(hFSpool, FS) < 0) {
  1597. ErrorPush();
  1598. StrFreeStrings(ppszRelays);
  1599. return (ErrorPop());
  1600. }
  1601. ///////////////////////////////////////////////////////////////////////////////
  1602. //  Get spool file infos
  1603. ///////////////////////////////////////////////////////////////////////////////
  1604. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  1605. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1606. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1607. char const *pszSendMailFrom = USmlSendMailFrom(hFSpool);
  1608. char const *pszSendRcptTo = USmlSendRcptTo(hFSpool);
  1609. char const *pszSpoolFilePath = USmlGetSpoolFilePath(hFSpool);
  1610. ///////////////////////////////////////////////////////////////////////////////
  1611. //  Get HELO domain
  1612. ///////////////////////////////////////////////////////////////////////////////
  1613. char szHeloDomain[MAX_HOST_NAME] = "";
  1614. SvrConfigVar("HeloDomain", szHeloDomain, sizeof(szHeloDomain) - 1, hSvrConfig, "");
  1615. char const *pszHeloDomain = IsEmptyString(szHeloDomain) ? NULL : szHeloDomain;
  1616. SMTPError SMTPE;
  1617. USmtpInitError(&SMTPE);
  1618. ///////////////////////////////////////////////////////////////////////////////
  1619. //  By initializing this to zero makes XMail to discharge all mail for domains
  1620. //  that have an empty relay list
  1621. ///////////////////////////////////////////////////////////////////////////////
  1622. int iReturnCode = 0;
  1623. for (int ss = 0; ppszRelays[ss] != NULL; ss++) {
  1624. SysLogMessage(LOG_LEV_MESSAGE,
  1625.       "USMAIL SMTP-Send RLYS = "%s" SMTP = "%s" From = "%s" To = "%s"n",
  1626.       ppszRelays[ss], pszSMTPDomain, pszMailFrom, pszRcptTo);
  1627. USmtpCleanupError(&SMTPE);
  1628. if (USmtpSendMail(ppszRelays[ss], pszHeloDomain, pszSendMailFrom, pszSendRcptTo,
  1629.   &FS, &SMTPE) == 0) {
  1630. ///////////////////////////////////////////////////////////////////////////////
  1631. //  Log Mailer operation
  1632. ///////////////////////////////////////////////////////////////////////////////
  1633. if (LMPC.ulFlags & LMPCF_LOG_ENABLED)
  1634. USmlLogMessage(hFSpool, "RLYS", ppszRelays[ss]);
  1635. USmtpCleanupError(&SMTPE);
  1636. StrFreeStrings(ppszRelays);
  1637. return (0);
  1638. }
  1639. int iErrorCode = ErrGetErrorCode();
  1640. char szSmtpError[512] = "";
  1641. USmtpGetSMTPError(&SMTPE, szSmtpError, sizeof(szSmtpError));
  1642. ErrLogMessage(LOG_LEV_MESSAGE,
  1643.       "USMAIL SMTP-Send RLYS = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  1644.       "%s = "%s"n", ppszRelays[ss], pszSMTPDomain, pszMailFrom,
  1645.       pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError);
  1646. QueUtErrLogMessage(hQueue, hMessage,
  1647.    "USMAIL SMTP-Send RLYS = "%s" SMTP = "%s" From = "%s" To = "%s" Failed !n"
  1648.    "%s = "%s"n", ppszRelays[ss], pszSMTPDomain, pszMailFrom,
  1649.    pszRcptTo, SMTP_ERROR_VARNAME, szSmtpError);
  1650. ///////////////////////////////////////////////////////////////////////////////
  1651. //  If a permanent SMTP error has been detected, then notify the message sender
  1652. ///////////////////////////////////////////////////////////////////////////////
  1653. if (USmtpIsFatalError(&SMTPE))
  1654. QueUtNotifyPermErrDelivery(hQueue, hMessage, hFSpool,
  1655.    USmtpGetErrorMessage(&SMTPE),
  1656.    USmtpGetErrorServer(&SMTPE), false);
  1657. iReturnCode = USmtpIsFatalError(&SMTPE) ? iErrorCode : -iErrorCode;
  1658. }
  1659. USmtpCleanupError(&SMTPE);
  1660. StrFreeStrings(ppszRelays);
  1661. return (iReturnCode);
  1662. }
  1663. int USmlGetDomainCustomDir(char *pszCustomDir, int iMaxPath, int iFinalSlash)
  1664. {
  1665. CfgGetRootPath(pszCustomDir, iMaxPath);
  1666. StrNCat(pszCustomDir, SMAIL_DOMAIN_PROC_DIR, iMaxPath);
  1667. if (iFinalSlash)
  1668. AppendSlash(pszCustomDir);
  1669. return (0);
  1670. }
  1671. int USmlGetCmdAliasDir(char *pszAliasDir, int iMaxPath, int iFinalSlash)
  1672. {
  1673. CfgGetRootPath(pszAliasDir, iMaxPath);
  1674. StrNCat(pszAliasDir, SMAIL_CMDALIAS_DIR, iMaxPath);
  1675. if (iFinalSlash)
  1676. AppendSlash(pszAliasDir);
  1677. return (0);
  1678. }
  1679. int USmlGetCmdAliasFile(char const *pszDomain, char const *pszUser, char *pszAliasFile)
  1680. {
  1681. char szAliasDir[SYS_MAX_PATH] = "";
  1682. USmlGetCmdAliasDir(szAliasDir, sizeof(szAliasDir), 1);
  1683. SysSNPrintf(pszAliasFile, SYS_MAX_PATH - 1, "%s%s%s%s.tab",
  1684.     szAliasDir, pszDomain, SYS_SLASH_STR, pszUser);
  1685. StrLower(pszAliasFile + strlen(szAliasDir));
  1686. return (0);
  1687. }
  1688. int USmlIsCmdAliasAccount(char const *pszDomain, char const *pszUser, char *pszAliasFile)
  1689. {
  1690. char szAliasFile[SYS_MAX_PATH] = "";
  1691. if (pszAliasFile == NULL)
  1692. pszAliasFile = szAliasFile;
  1693. if (USmlGetCmdAliasFile(pszDomain, pszUser, pszAliasFile) < 0)
  1694. return (ErrGetErrorCode());
  1695. if (!SysExistFile(pszAliasFile)) {
  1696. ErrSetErrorCode(ERR_NOT_A_CMD_ALIAS);
  1697. return (ERR_NOT_A_CMD_ALIAS);
  1698. }
  1699. return (0);
  1700. }
  1701. int USmlCreateCmdAliasDomainDir(char const *pszDomain)
  1702. {
  1703. char szAliasDir[SYS_MAX_PATH] = "";
  1704. char szDomainAliasDir[SYS_MAX_PATH] = "";
  1705. USmlGetCmdAliasDir(szAliasDir, sizeof(szAliasDir), 1);
  1706. SysSNPrintf(szDomainAliasDir, sizeof(szDomainAliasDir) - 1, "%s%s",
  1707.     szAliasDir, pszDomain);
  1708. StrLower(szDomainAliasDir + strlen(szAliasDir));
  1709. if (SysMakeDir(szDomainAliasDir) < 0)
  1710. return (ErrGetErrorCode());
  1711. return (0);
  1712. }
  1713. int USmlDeleteCmdAliasDomainDir(char const *pszDomain)
  1714. {
  1715. char szAliasDir[SYS_MAX_PATH] = "";
  1716. char szDomainAliasDir[SYS_MAX_PATH] = "";
  1717. USmlGetCmdAliasDir(szAliasDir, sizeof(szAliasDir), 1);
  1718. SysSNPrintf(szDomainAliasDir, sizeof(szDomainAliasDir) - 1, "%s%s",
  1719.     szAliasDir, pszDomain);
  1720. StrLower(szDomainAliasDir + strlen(szAliasDir));
  1721. if (SysExistDir(szDomainAliasDir)) {
  1722. if (MscClearDirectory(szDomainAliasDir) < 0)
  1723. return (ErrGetErrorCode());
  1724. if (SysRemoveDir(szDomainAliasDir) < 0)
  1725. return (ErrGetErrorCode());
  1726. }
  1727. return (0);
  1728. }
  1729. int USmlGetCmdAliasSpoolFile(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, char *pszAliasFilePath)
  1730. {
  1731. return (QueGetFilePath(hQueue, hMessage, pszAliasFilePath, QUEUE_CUST_DIR));
  1732. }
  1733. int USmlGetCmdAliasCustomFile(SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1734.       QMSG_HANDLE hMessage, char const *pszDomain, char const *pszUser,
  1735.       char *pszAliasFilePath)
  1736. {
  1737. ///////////////////////////////////////////////////////////////////////////////
  1738. //  Check if exist a spooled copy
  1739. ///////////////////////////////////////////////////////////////////////////////
  1740. char const *pszSpoolFilePath = USmlGetSpoolFilePath(hFSpool);
  1741. USmlGetCmdAliasSpoolFile(hQueue, hMessage, pszAliasFilePath);
  1742. if (SysExistFile(pszAliasFilePath))
  1743. return (0);
  1744. ///////////////////////////////////////////////////////////////////////////////
  1745. //  Check if this is a cmd alias
  1746. ///////////////////////////////////////////////////////////////////////////////
  1747. char szAliasFile[SYS_MAX_PATH] = "";
  1748. if (USmlIsCmdAliasAccount(pszDomain, pszUser, szAliasFile) < 0)
  1749. return (ErrGetErrorCode());
  1750. RLCK_HANDLE hResLock = RLckLockSH(szAliasFile);
  1751. if (hResLock == INVALID_RLCK_HANDLE)
  1752. return (ErrGetErrorCode());
  1753. ///////////////////////////////////////////////////////////////////////////////
  1754. //  Make a copy into the spool
  1755. ///////////////////////////////////////////////////////////////////////////////
  1756. if (MscCopyFile(pszAliasFilePath, szAliasFile) < 0) {
  1757. ErrorPush();
  1758. RLckUnlockSH(hResLock);
  1759. return (ErrorPop());
  1760. }
  1761. RLckUnlockSH(hResLock);
  1762. return (0);
  1763. }
  1764. int USmlDomainCustomFileName(char const *pszDestDomain, char *pszCustFilePath)
  1765. {
  1766. ///////////////////////////////////////////////////////////////////////////////
  1767. //  Make domain name lower case
  1768. ///////////////////////////////////////////////////////////////////////////////
  1769. char szDestDomain[MAX_HOST_NAME] = "";
  1770. StrSNCpy(szDestDomain, pszDestDomain);
  1771. StrLower(szDestDomain);
  1772. ///////////////////////////////////////////////////////////////////////////////
  1773. //  Build file name
  1774. ///////////////////////////////////////////////////////////////////////////////
  1775. char szCustomDir[SYS_MAX_PATH] = "";
  1776. USmlGetDomainCustomDir(szCustomDir, sizeof(szCustomDir), 1);
  1777. SysSNPrintf(pszCustFilePath, SYS_MAX_PATH - 1, "%s%s.tab", szCustomDir, szDestDomain);
  1778. return (0);
  1779. }
  1780. int USmlGetDomainCustomFile(char const *pszDestDomain, char *pszCustFilePath)
  1781. {
  1782. ///////////////////////////////////////////////////////////////////////////////
  1783. //  Make domain name lower case
  1784. ///////////////////////////////////////////////////////////////////////////////
  1785. char szDestDomain[MAX_HOST_NAME] = "";
  1786. StrSNCpy(szDestDomain, pszDestDomain);
  1787. StrLower(szDestDomain);
  1788. ///////////////////////////////////////////////////////////////////////////////
  1789. //  Lookup custom files
  1790. ///////////////////////////////////////////////////////////////////////////////
  1791. char szCustomDir[SYS_MAX_PATH] = "";
  1792. USmlGetDomainCustomDir(szCustomDir, sizeof(szCustomDir), 1);
  1793. for (char const *pszSubDom = szDestDomain; pszSubDom != NULL;
  1794.      pszSubDom = strchr(pszSubDom + 1, '.')) {
  1795. SysSNPrintf(pszCustFilePath, SYS_MAX_PATH - 1, "%s%s.tab", szCustomDir,
  1796.     pszSubDom);
  1797. if (SysExistFile(pszCustFilePath))
  1798. return (0);
  1799. }
  1800. SysSNPrintf(pszCustFilePath, SYS_MAX_PATH - 1, "%s.tab", szCustomDir);
  1801. if (SysExistFile(pszCustFilePath))
  1802. return (0);
  1803. ErrSetErrorCode(ERR_NOT_A_CUSTOM_DOMAIN);
  1804. return (ERR_NOT_A_CUSTOM_DOMAIN);
  1805. }
  1806. int USmlGetDomainCustomSpoolFile(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, char *pszCustFilePath)
  1807. {
  1808. return (QueGetFilePath(hQueue, hMessage, pszCustFilePath, QUEUE_CUST_DIR));
  1809. }
  1810. int USmlGetUserCustomSpoolFile(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, char *pszCustFilePath)
  1811. {
  1812. return (QueGetFilePath(hQueue, hMessage, pszCustFilePath, QUEUE_MPRC_DIR));
  1813. }
  1814. int USmlGetDomainMsgCustomFile(SPLF_HANDLE hFSpool, QUEUE_HANDLE hQueue,
  1815.        QMSG_HANDLE hMessage, char const *pszDestDomain,
  1816.        char *pszCustFilePath)
  1817. {
  1818. ///////////////////////////////////////////////////////////////////////////////
  1819. //  Check if exist a spooled copy
  1820. ///////////////////////////////////////////////////////////////////////////////
  1821. char const *pszSpoolFilePath = USmlGetSpoolFilePath(hFSpool);
  1822. USmlGetDomainCustomSpoolFile(hQueue, hMessage, pszCustFilePath);
  1823. if (SysExistFile(pszCustFilePath))
  1824. return (0);
  1825. ///////////////////////////////////////////////////////////////////////////////
  1826. //  Check if this is a custom domain
  1827. ///////////////////////////////////////////////////////////////////////////////
  1828. char szCustDomainFile[SYS_MAX_PATH] = "";
  1829. if (USmlGetDomainCustomFile(pszDestDomain, szCustDomainFile) < 0)
  1830. return (ErrGetErrorCode());
  1831. RLCK_HANDLE hResLock = RLckLockSH(szCustDomainFile);
  1832. if (hResLock == INVALID_RLCK_HANDLE)
  1833. return (ErrGetErrorCode());
  1834. ///////////////////////////////////////////////////////////////////////////////
  1835. //  Make a copy into the spool
  1836. ///////////////////////////////////////////////////////////////////////////////
  1837. if (MscCopyFile(pszCustFilePath, szCustDomainFile) < 0) {
  1838. ErrorPush();
  1839. RLckUnlockSH(hResLock);
  1840. return (ErrorPop());
  1841. }
  1842. RLckUnlockSH(hResLock);
  1843. return (0);
  1844. }
  1845. int USmlGetCustomDomainFile(char const *pszDestDomain, char const *pszCustFilePath)
  1846. {
  1847. ///////////////////////////////////////////////////////////////////////////////
  1848. //  Check if this is a custom domain
  1849. ///////////////////////////////////////////////////////////////////////////////
  1850. char szCustDomainFile[SYS_MAX_PATH] = "";
  1851. if (USmlGetDomainCustomFile(pszDestDomain, szCustDomainFile) < 0)
  1852. return (ErrGetErrorCode());
  1853. char szResLock[SYS_MAX_PATH] = "";
  1854. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(szCustDomainFile, szResLock,
  1855.   sizeof(szResLock)));
  1856. if (hResLock == INVALID_RLCK_HANDLE)
  1857. return (ErrGetErrorCode());
  1858. ///////////////////////////////////////////////////////////////////////////////
  1859. //  Make a copy onto user supplied file
  1860. ///////////////////////////////////////////////////////////////////////////////
  1861. if (MscCopyFile(pszCustFilePath, szCustDomainFile) < 0) {
  1862. ErrorPush();
  1863. RLckUnlockSH(hResLock);
  1864. return (ErrorPop());
  1865. }
  1866. RLckUnlockSH(hResLock);
  1867. return (0);
  1868. }
  1869. int USmlSetCustomDomainFile(char const *pszDestDomain, char const *pszCustFilePath)
  1870. {
  1871. ///////////////////////////////////////////////////////////////////////////////
  1872. //  Check if this is a custom domain
  1873. ///////////////////////////////////////////////////////////////////////////////
  1874. char szCustDomainFile[SYS_MAX_PATH] = "";
  1875. USmlDomainCustomFileName(pszDestDomain, szCustDomainFile);
  1876. char szResLock[SYS_MAX_PATH] = "";
  1877. RLCK_HANDLE hResLock = RLckLockEX(CfgGetBasedPath(szCustDomainFile, szResLock,
  1878.   sizeof(szResLock)));
  1879. if (hResLock == INVALID_RLCK_HANDLE)
  1880. return (ErrGetErrorCode());
  1881. if (pszCustFilePath != NULL) {
  1882. ///////////////////////////////////////////////////////////////////////////////
  1883. //  Overwrite current file
  1884. ///////////////////////////////////////////////////////////////////////////////
  1885. if (MscCopyFile(szCustDomainFile, pszCustFilePath) < 0) {
  1886. ErrorPush();
  1887. RLckUnlockEX(hResLock);
  1888. return (ErrorPop());
  1889. }
  1890. } else
  1891. SysRemove(szCustDomainFile);
  1892. RLckUnlockEX(hResLock);
  1893. return (0);
  1894. }
  1895. int USmlCustomizedDomain(char const *pszDestDomain)
  1896. {
  1897. char szCustFilePath[SYS_MAX_PATH] = "";
  1898. return (USmlGetDomainCustomFile(pszDestDomain, szCustFilePath));
  1899. }
  1900. static int USmlLogMessage(char const *pszSMTPDomain, char const *pszMessageID,
  1901.   char const *pszSmtpMessageID, char const *pszFrom, char const *pszRcpt,
  1902.   char const *pszMedium, char const *pszParam)
  1903. {
  1904. char szTime[256] = "";
  1905. MscGetTimeNbrString(szTime, sizeof(szTime) - 1);
  1906. RLCK_HANDLE hResLock = RLckLockEX(SVR_LOGS_DIR SYS_SLASH_STR SMAIL_LOG_FILE);
  1907. if (hResLock == INVALID_RLCK_HANDLE)
  1908. return (ErrGetErrorCode());
  1909. MscFileLog(SMAIL_LOG_FILE, ""%s""
  1910.    "t"%s""
  1911.    "t"%s""
  1912.    "t"%s""
  1913.    "t"%s""
  1914.    "t"%s""
  1915.    "t"%s""
  1916.    "t"%s""
  1917.    "n", pszSMTPDomain, pszMessageID, pszSmtpMessageID, pszFrom, pszRcpt,
  1918.    pszMedium, pszParam, szTime);
  1919. RLckUnlockEX(hResLock);
  1920. return (0);
  1921. }
  1922. int USmlLogMessage(SPLF_HANDLE hFSpool, char const *pszMedium, char const *pszParam)
  1923. {
  1924. char const *pszSMTPDomain = USmlGetSMTPDomain(hFSpool);
  1925. char const *pszSmtpMessageID = USmlGetSmtpMessageID(hFSpool);
  1926. char const *pszMessageID = USmlGetSpoolFile(hFSpool);
  1927. char const *pszMailFrom = USmlMailFrom(hFSpool);
  1928. char const *pszRcptTo = USmlRcptTo(hFSpool);
  1929. USmlLogMessage(pszSMTPDomain, pszMessageID, pszSmtpMessageID, pszMailFrom, pszRcptTo,
  1930.        pszMedium, pszParam);
  1931. return (0);
  1932. }
  1933. int USmlParseAddress(char const *pszAddress, char *pszPreAddr,
  1934.      int iMaxPreAddress, char *pszEmailAddr, int iMaxAddress)
  1935. {
  1936. for (; (*pszAddress == ' ') || (*pszAddress == 't'); pszAddress++);
  1937. if (*pszAddress == '') {
  1938. ErrSetErrorCode(ERR_BAD_TAG_ADDRESS);
  1939. return (ERR_BAD_TAG_ADDRESS);
  1940. }
  1941. char const *pszOpen = strrchr(pszAddress, '<');
  1942. if (pszOpen != NULL) {
  1943. if (pszPreAddr != NULL) {
  1944. int iPreCount = Min((int) (pszOpen - pszAddress), iMaxPreAddress - 1);
  1945. strncpy(pszPreAddr, pszAddress, iPreCount);
  1946. pszPreAddr[iPreCount] = '';
  1947. StrTrim(pszPreAddr, " t");
  1948. }
  1949. if (pszEmailAddr != NULL) {
  1950. char const *pszClose = strrchr(pszAddress, '>');
  1951. if (pszClose == NULL) {
  1952. ErrSetErrorCode(ERR_BAD_TAG_ADDRESS);
  1953. return (ERR_BAD_TAG_ADDRESS);
  1954. }
  1955. int iEmailCount = (int) Min((pszClose - pszOpen) - 1, iMaxAddress - 1);
  1956. if (iEmailCount < 0) {
  1957. ErrSetErrorCode(ERR_BAD_TAG_ADDRESS);
  1958. return (ERR_BAD_TAG_ADDRESS);
  1959. }
  1960. strncpy(pszEmailAddr, pszOpen + 1, iEmailCount);
  1961. pszEmailAddr[iEmailCount] = '';
  1962. StrTrim(pszEmailAddr, " t");
  1963. }
  1964. } else {
  1965. if (pszPreAddr != NULL)
  1966. SetEmptyString(pszPreAddr);
  1967. if (pszEmailAddr != NULL) {
  1968. strncpy(pszEmailAddr, pszAddress, iMaxAddress - 1);
  1969. pszEmailAddr[iMaxAddress - 1] = '';
  1970. StrTrim(pszEmailAddr, " t");
  1971. }
  1972. }
  1973. return (0);
  1974. }
  1975. static int USmlExtractFromAddress(HSLIST & hTagList, char *pszFromAddr, int iMaxAddress)
  1976. {
  1977. ///////////////////////////////////////////////////////////////////////////////
  1978. //  Try to discover the "Return-Path" ( or eventually "From" ) tag to setup
  1979. //  the "MAIL FROM: <>" part of the spool message
  1980. ///////////////////////////////////////////////////////////////////////////////
  1981. TAG_POSITION TagPosition = TAG_POSITION_INIT;
  1982. MessageTagData *pMTD = USmlFindTag(hTagList, "Return-Path", TagPosition);
  1983. if ((pMTD != NULL) &&
  1984.     (USmlParseAddress(pMTD->pszTagData, NULL, 0, pszFromAddr, iMaxAddress) == 0))
  1985. return (0);
  1986. TagPosition = TAG_POSITION_INIT;
  1987. if (((pMTD = USmlFindTag(hTagList, "From", TagPosition)) != NULL) &&
  1988.     (USmlParseAddress(pMTD->pszTagData, NULL, 0, pszFromAddr, iMaxAddress) == 0))
  1989. return (0);
  1990. ErrSetErrorCode(ERR_MAILFROM_UNKNOWN);
  1991. return (ERR_MAILFROM_UNKNOWN);
  1992. }
  1993. static char const *USmlAddressFromAtPtr(char const *pszAt, char const *pszBase,
  1994. char *pszAddress, int iMaxAddress)
  1995. {
  1996. char const *pszStart = pszAt;
  1997. for (; (pszStart >= pszBase) && (strchr("<> t,":;'rn", *pszStart) == NULL);
  1998.      pszStart--);
  1999. ++pszStart;
  2000. char const *pszEnd = pszAt + 1;
  2001. for (; (*pszEnd != '') && (strchr("<> t,":;'rn", *pszEnd) == NULL); pszEnd++);
  2002. int iAddrLength = Min((int) (pszEnd - pszStart), iMaxAddress - 1);
  2003. strncpy(pszAddress, pszStart, iAddrLength);
  2004. pszAddress[iAddrLength] = '';
  2005. return (pszEnd);
  2006. }
  2007. static char const *USmlAddSingleAddress(char const *pszCurr, char const *pszBase,
  2008. DynString * pAddrDS, char const *const *ppszMatchDomains,
  2009. int *piAdded)
  2010. {
  2011. *piAdded = 0;
  2012. char const *pszAt = strchr(pszCurr, '@');
  2013. if (pszAt == NULL)
  2014. return (NULL);
  2015. char szAddress[MAX_SMTP_ADDRESS] = "";
  2016. char szDomain[MAX_ADDR_NAME] = "";
  2017. if (((pszCurr = USmlAddressFromAtPtr(pszAt, pszBase, szAddress,
  2018.      sizeof(szAddress) - 1)) != NULL) &&
  2019.     (USmtpSplitEmailAddr(szAddress, NULL, szDomain) == 0) &&
  2020.     ((ppszMatchDomains == NULL) || StrStringsIMatch(ppszMatchDomains, szDomain)) &&
  2021.     (StrIStr(StrDynGet(pAddrDS), szAddress) == NULL)) {
  2022. if (StrDynSize(pAddrDS) > 0)
  2023. StrDynAdd(pAddrDS, ADDRESS_TOKENIZER);
  2024. StrDynAdd(pAddrDS, szAddress);
  2025. ++(*piAdded);
  2026. }
  2027. return (pszCurr);
  2028. }
  2029. static int USmlAddAddresses(char const *pszAddrList, DynString * pAddrDS,
  2030.     char const *const *ppszMatchDomains)
  2031. {
  2032. int iAddrAdded = 0;
  2033. int iAdded;
  2034. char const *pszCurr = pszAddrList;
  2035. for (; (pszCurr != NULL) && (*pszCurr != '');) {
  2036. pszCurr =
  2037.     USmlAddSingleAddress(pszCurr, pszAddrList, pAddrDS, ppszMatchDomains,
  2038.  &iAdded);
  2039. if (iAdded)
  2040. ++iAddrAdded;
  2041. }
  2042. return (iAddrAdded);
  2043. }
  2044. static char **USmlGetAddressList(HSLIST & hTagList, char const *const *ppszMatchDomains,
  2045.  char const *const *ppszAddrTags)
  2046. {
  2047. DynString AddrDS;
  2048. StrDynInit(&AddrDS);
  2049. for (int ii = 0; ppszAddrTags[ii] != NULL; ii++) {
  2050. char const *pszHdrTag = (strchr("+", ppszAddrTags[ii][0]) != NULL) ?
  2051.     ppszAddrTags[ii] + 1 : ppszAddrTags[ii];
  2052. TAG_POSITION TagPosition = TAG_POSITION_INIT;
  2053. MessageTagData *pMTD = USmlFindTag(hTagList, pszHdrTag, TagPosition);
  2054. for (; pMTD != NULL; pMTD = USmlFindTag(hTagList, pszHdrTag, TagPosition)) {
  2055. int iAddrAdded = USmlAddAddresses(pMTD->pszTagData, &AddrDS,
  2056.   ppszMatchDomains);
  2057. ///////////////////////////////////////////////////////////////////////////////
  2058. //  Exclusive tag detected, stop the scan
  2059. ///////////////////////////////////////////////////////////////////////////////
  2060. if ((iAddrAdded > 0) && (ppszAddrTags[ii][0] == '+'))
  2061. goto BuildAddrList;
  2062. }
  2063. }
  2064. ///////////////////////////////////////////////////////////////////////////////
  2065. //  Yes, i know, goto's might be bad. Not in this case though ...
  2066. ///////////////////////////////////////////////////////////////////////////////
  2067.       BuildAddrList:
  2068. char **ppszAddresses = StrTokenize(StrDynGet(&AddrDS), ADDRESS_TOKENIZER);
  2069. StrDynFree(&AddrDS);
  2070. return (ppszAddresses);
  2071. }
  2072. static int USmlExtractToAddress(HSLIST & hTagList, char *pszToAddr, int iMaxAddress)
  2073. {
  2074. ///////////////////////////////////////////////////////////////////////////////
  2075. //  Try to extract the "To:" tag from the mail headers
  2076. ///////////////////////////////////////////////////////////////////////////////
  2077. TAG_POSITION TagPosition = TAG_POSITION_INIT;
  2078. MessageTagData *pMTD = USmlFindTag(hTagList, "To", TagPosition);
  2079. if ((pMTD == NULL) ||
  2080.     (USmlParseAddress(pMTD->pszTagData, NULL, 0, pszToAddr, iMaxAddress) < 0)) {
  2081. ErrSetErrorCode(ERR_RCPTTO_UNKNOWN);
  2082. return (ERR_RCPTTO_UNKNOWN);
  2083. }
  2084. return (0);
  2085. }
  2086. static char **USmlBuildTargetRcptList(char const *pszRcptTo, HSLIST & hTagList,
  2087.       const char *pszFetchHdrTags)
  2088. {
  2089. char **ppszRcptList = NULL;
  2090. char **ppszAddrTags = NULL;
  2091. if ((pszFetchHdrTags != NULL) &&
  2092.     ((ppszAddrTags = StrTokenize(pszFetchHdrTags, ",")) == NULL))
  2093. return (NULL);
  2094. if (pszRcptTo == NULL) {
  2095. if (ppszAddrTags == NULL) {
  2096. ErrSetErrorCode(ERR_NO_HDR_FETCH_TAGS);
  2097. return (NULL);
  2098. }
  2099. ///////////////////////////////////////////////////////////////////////////////
  2100. //  If the recipient is NULL try to extract addresses from the message using
  2101. //  the supplied tag string
  2102. ///////////////////////////////////////////////////////////////////////////////
  2103. if ((ppszRcptList = USmlGetAddressList(hTagList, NULL, ppszAddrTags)) == NULL) {
  2104. StrFreeStrings(ppszAddrTags);
  2105. return (NULL);
  2106. }
  2107. } else if (*pszRcptTo == '?') {
  2108. if (ppszAddrTags == NULL) {
  2109. ErrSetErrorCode(ERR_NO_HDR_FETCH_TAGS);
  2110. return (NULL);
  2111. }
  2112. ///////////////////////////////////////////////////////////////////////////////
  2113. //  Extract matching domains
  2114. ///////////////////////////////////////////////////////////////////////////////
  2115. char **ppszDomains = StrTokenize(pszRcptTo, ",");
  2116. if (ppszDomains == NULL) {
  2117. StrFreeStrings(ppszAddrTags);
  2118. return (NULL);
  2119. }
  2120. ///////////////////////////////////////////////////////////////////////////////
  2121. //  We need to masquerade incoming domain. In this case "pszRcptTo" is made by
  2122. //  "?" + masquerade-domain
  2123. ///////////////////////////////////////////////////////////////////////////////
  2124. if ((ppszRcptList =
  2125.      USmlGetAddressList(hTagList, &ppszDomains[1], ppszAddrTags)) == NULL) {
  2126. StrFreeStrings(ppszDomains);
  2127. StrFreeStrings(ppszAddrTags);
  2128. return (NULL);
  2129. }
  2130. int iAddrCount = StrStringsCount(ppszRcptList);
  2131. for (int ii = 0; ii < iAddrCount; ii++) {
  2132. char szToUser[MAX_ADDR_NAME] = "";
  2133. char szRecipient[MAX_ADDR_NAME] = "";
  2134. if (USmtpSplitEmailAddr(ppszRcptList[ii], szToUser, NULL) == 0) {
  2135. SysSNPrintf(szRecipient, sizeof(szRecipient) - 1, "%s@%s",
  2136.     szToUser, ppszDomains[0] + 1);
  2137. SysFree(ppszRcptList[ii]);
  2138. ppszRcptList[ii] = SysStrDup(szRecipient);
  2139. }
  2140. }
  2141. StrFreeStrings(ppszDomains);
  2142. } else if (*pszRcptTo == '&') {
  2143. if (ppszAddrTags == NULL) {
  2144. ErrSetErrorCode(ERR_NO_HDR_FETCH_TAGS);
  2145. return (NULL);
  2146. }
  2147. ///////////////////////////////////////////////////////////////////////////////
  2148. //  Extract matching domains
  2149. ///////////////////////////////////////////////////////////////////////////////
  2150. char **ppszDomains = StrTokenize(pszRcptTo, ",");
  2151. if (ppszDomains == NULL) {
  2152. StrFreeStrings(ppszAddrTags);
  2153. return (NULL);
  2154. }
  2155. ///////////////////////////////////////////////////////////////////////////////
  2156. //  We need to masquerade incoming domain. In this case "pszRcptTo" is made by
  2157. //  "&" + add-domain
  2158. ///////////////////////////////////////////////////////////////////////////////
  2159. if ((ppszRcptList =
  2160.      USmlGetAddressList(hTagList, &ppszDomains[1], ppszAddrTags)) == NULL) {
  2161. StrFreeStrings(ppszDomains);
  2162. StrFreeStrings(ppszAddrTags);
  2163. return (NULL);
  2164. }
  2165. int iAddrCount = StrStringsCount(ppszRcptList);
  2166. for (int ii = 0; ii < iAddrCount; ii++) {
  2167. char szRecipient[MAX_ADDR_NAME] = "";
  2168. SysSNPrintf(szRecipient, sizeof(szRecipient) - 1, "%s%s",
  2169.     ppszRcptList[ii], ppszDomains[0] + 1);
  2170. SysFree(ppszRcptList[ii]);
  2171. ppszRcptList[ii] = SysStrDup(szRecipient);
  2172. }
  2173. StrFreeStrings(ppszDomains);
  2174. } else
  2175. ppszRcptList = StrBuildList(pszRcptTo, NULL);
  2176. if (ppszAddrTags != NULL)
  2177. StrFreeStrings(ppszAddrTags);
  2178. return (ppszRcptList);
  2179. }
  2180. int USmlDeliverFetchedMsg(char const *pszSyncAddr, const char *pszFetchHdrTags,
  2181.   char const *pszMailFile)
  2182. {
  2183. FILE *pMailFile = fopen(pszMailFile, "rb");
  2184. if (pMailFile == NULL) {
  2185. ErrSetErrorCode(ERR_FILE_OPEN);
  2186. return (ERR_FILE_OPEN);
  2187. }
  2188. ///////////////////////////////////////////////////////////////////////////////
  2189. //  Load message tags
  2190. ///////////////////////////////////////////////////////////////////////////////
  2191. HSLIST hTagList;
  2192. ListInit(hTagList);
  2193. USmlLoadTags(pMailFile, hTagList);
  2194. ///////////////////////////////////////////////////////////////////////////////
  2195. //  Extract "MAIL FROM: <>" address
  2196. ///////////////////////////////////////////////////////////////////////////////
  2197. char szFromAddr[MAX_SMTP_ADDRESS] = "";
  2198. USmlExtractFromAddress(hTagList, szFromAddr, sizeof(szFromAddr) - 1);
  2199. ///////////////////////////////////////////////////////////////////////////////
  2200. //  Extract recipient list
  2201. ///////////////////////////////////////////////////////////////////////////////
  2202. char **ppszRcptList = USmlBuildTargetRcptList(pszSyncAddr, hTagList, pszFetchHdrTags);
  2203. if (ppszRcptList == NULL) {
  2204. ErrorPush();
  2205. USmlFreeTagsList(hTagList);
  2206. fclose(pMailFile);
  2207. return (ErrorPop());
  2208. }
  2209. USmlFreeTagsList(hTagList);
  2210. ///////////////////////////////////////////////////////////////////////////////
  2211. //  Loop through extracted recipients and deliver
  2212. ///////////////////////////////////////////////////////////////////////////////
  2213. int iDeliverCount = 0;
  2214. int iAddrCount = StrStringsCount(ppszRcptList);
  2215. for (int ii = 0; ii < iAddrCount; ii++) {
  2216. ///////////////////////////////////////////////////////////////////////////////
  2217. //  Check address validity and skip invalid ( or not handled ) ones
  2218. ///////////////////////////////////////////////////////////////////////////////
  2219. char szDestDomain[MAX_HOST_NAME] = "";
  2220. if ((USmtpSplitEmailAddr(ppszRcptList[ii], NULL, szDestDomain) < 0) ||
  2221.     ((MDomIsHandledDomain(szDestDomain) < 0) &&
  2222.      (USmlCustomizedDomain(szDestDomain) < 0)))
  2223. continue;
  2224. ///////////////////////////////////////////////////////////////////////////////
  2225. //  Get message handle
  2226. ///////////////////////////////////////////////////////////////////////////////
  2227. QMSG_HANDLE hMessage = QueCreateMessage(hSpoolQueue);
  2228. if (hMessage == INVALID_QMSG_HANDLE) {
  2229. ErrorPush();
  2230. StrFreeStrings(ppszRcptList);
  2231. fclose(pMailFile);
  2232. return (ErrorPop());
  2233. }
  2234. char szQueueFilePath[SYS_MAX_PATH] = "";
  2235. QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
  2236. if (USmlCreateSpoolFile(pMailFile, NULL, szFromAddr,
  2237. ppszRcptList[ii], szQueueFilePath) < 0) {
  2238. ErrorPush();
  2239. QueCleanupMessage(hSpoolQueue, hMessage);
  2240. QueCloseMessage(hSpoolQueue, hMessage);
  2241. StrFreeStrings(ppszRcptList);
  2242. fclose(pMailFile);
  2243. return (ErrorPop());
  2244. }
  2245. ///////////////////////////////////////////////////////////////////////////////
  2246. //  Transfer file to the spool
  2247. ///////////////////////////////////////////////////////////////////////////////
  2248. if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
  2249. ErrorPush();
  2250. QueCleanupMessage(hSpoolQueue, hMessage);
  2251. QueCloseMessage(hSpoolQueue, hMessage);
  2252. StrFreeStrings(ppszRcptList);
  2253. fclose(pMailFile);
  2254. return (ErrorPop());
  2255. }
  2256. ++iDeliverCount;
  2257. }
  2258. StrFreeStrings(ppszRcptList);
  2259. fclose(pMailFile);
  2260. ///////////////////////////////////////////////////////////////////////////////
  2261. //  Check if the message has been delivered at least one time
  2262. ///////////////////////////////////////////////////////////////////////////////
  2263. if (iDeliverCount == 0) {
  2264. ErrSetErrorCode(ERR_FETCHMSG_UNDELIVERED);
  2265. return (ERR_FETCHMSG_UNDELIVERED);
  2266. }
  2267. return (0);
  2268. }
  2269. static int USmlCreateSpoolFile(FILE * pMailFile, char const *const *ppszInfo,
  2270.        char const *pszMailFrom, char const *pszRcptTo,
  2271.        char const *pszSpoolFile)
  2272. {
  2273. FILE *pSpoolFile = fopen(pszSpoolFile, "wb");
  2274. if (pSpoolFile == NULL) {
  2275. ErrSetErrorCode(ERR_FILE_CREATE, pszSpoolFile);
  2276. return (ERR_FILE_CREATE);
  2277. }
  2278. ///////////////////////////////////////////////////////////////////////////////
  2279. //  Write info line
  2280. ///////////////////////////////////////////////////////////////////////////////
  2281. if (ppszInfo != NULL)
  2282. USmtpWriteInfoLine(pSpoolFile, ppszInfo[smsgiClientAddr],
  2283.    ppszInfo[smsgiServerAddr], ppszInfo[smsgiTime]);
  2284. else {
  2285. char szTime[256] = "";
  2286. MscGetTimeStr(szTime, sizeof(szTime) - 1);
  2287. USmtpWriteInfoLine(pSpoolFile, LOCAL_ADDRESS_SQB ":0",
  2288.    LOCAL_ADDRESS_SQB ":0", szTime);
  2289. }
  2290. ///////////////////////////////////////////////////////////////////////////////
  2291. //  Write SMTP domain
  2292. ///////////////////////////////////////////////////////////////////////////////
  2293. char szSmtpDomain[MAX_HOST_NAME] = "";
  2294. if (USmtpSplitEmailAddr(pszRcptTo, NULL, szSmtpDomain) < 0) {
  2295. ErrorPush();
  2296. fclose(pSpoolFile);
  2297. SysRemove(pszSpoolFile);
  2298. return (ErrorPop());
  2299. }
  2300. fprintf(pSpoolFile, "%srn", szSmtpDomain);
  2301. ///////////////////////////////////////////////////////////////////////////////
  2302. //  Write message ID
  2303. ///////////////////////////////////////////////////////////////////////////////
  2304. SYS_UINT64 ullMessageID = 0;
  2305. if (SvrGetMessageID(&ullMessageID) < 0) {
  2306. ErrorPush();
  2307. fclose(pSpoolFile);
  2308. SysRemove(pszSpoolFile);
  2309. return (ErrorPop());
  2310. }
  2311. fprintf(pSpoolFile, "P" SYS_LLX_FMT "rn", ullMessageID);
  2312. ///////////////////////////////////////////////////////////////////////////////
  2313. //  Write "MAIL FROM:"
  2314. ///////////////////////////////////////////////////////////////////////////////
  2315. fprintf(pSpoolFile, "MAIL FROM: <%s>rn", pszMailFrom);
  2316. ///////////////////////////////////////////////////////////////////////////////
  2317. //  Write "RCPT TO:"
  2318. ///////////////////////////////////////////////////////////////////////////////
  2319. fprintf(pSpoolFile, "RCPT TO: <%s>rn", pszRcptTo);
  2320. ///////////////////////////////////////////////////////////////////////////////
  2321. //  Write SPOOL_FILE_DATA_START
  2322. ///////////////////////////////////////////////////////////////////////////////
  2323. fprintf(pSpoolFile, "%srn", SPOOL_FILE_DATA_START);
  2324. ///////////////////////////////////////////////////////////////////////////////
  2325. //  Write message body
  2326. ///////////////////////////////////////////////////////////////////////////////
  2327. if (MscCopyFile(pSpoolFile, pMailFile, 0, (unsigned long) -1) < 0) {
  2328. ErrorPush();
  2329. fclose(pSpoolFile);
  2330. SysRemove(pszSpoolFile);
  2331. return (ErrorPop());
  2332. }
  2333. fclose(pSpoolFile);
  2334. return (0);
  2335. }
  2336. int USmlMailLoopCheck(SPLF_HANDLE hFSpool, SVRCFG_HANDLE hSvrConfig)
  2337. {
  2338. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  2339. ///////////////////////////////////////////////////////////////////////////////
  2340. //  Count MTA ops
  2341. ///////////////////////////////////////////////////////////////////////////////
  2342. int iLoopsCount = 0;
  2343. int iMaxMTAOps = SvrGetConfigInt("MaxMTAOps", MAX_MTA_OPS, hSvrConfig);
  2344. MessageTagData *pMTD = (MessageTagData *) ListFirst(pSFD->hTagList);
  2345. for (; pMTD != INVALID_SLIST_PTR; pMTD = (MessageTagData *)
  2346.      ListNext(pSFD->hTagList, (PLISTLINK) pMTD))
  2347. if ((stricmp(pMTD->pszTagName, "Received") == 0) ||
  2348.     (stricmp(pMTD->pszTagName, "X-Deliver-To") == 0))
  2349. ++iLoopsCount;
  2350. ///////////////////////////////////////////////////////////////////////////////
  2351. //  Check MTA count
  2352. ///////////////////////////////////////////////////////////////////////////////
  2353. if (iLoopsCount > iMaxMTAOps) {
  2354. ErrSetErrorCode(ERR_MAIL_LOOP_DETECTED);
  2355. return (ERR_MAIL_LOOP_DETECTED);
  2356. }
  2357. return (0);
  2358. }
  2359. int USmlMessageAuth(SPLF_HANDLE hFSpool, char *pszAuthName, int iSize)
  2360. {
  2361. SpoolFileData *pSFD = (SpoolFileData *) hFSpool;
  2362. ///////////////////////////////////////////////////////////////////////////////
  2363. //  Looks for the "X-AuthUser" tag, that has to happen *before* the first
  2364. //  "Received" tag (to prevent forging)
  2365. ///////////////////////////////////////////////////////////////////////////////
  2366. MessageTagData *pMTD = (MessageTagData *) ListFirst(pSFD->hTagList);
  2367. for (; pMTD != INVALID_SLIST_PTR; pMTD = (MessageTagData *)
  2368.      ListNext(pSFD->hTagList, (PLISTLINK) pMTD)) {
  2369. if (stricmp(pMTD->pszTagName, "Received") == 0)
  2370. break;
  2371. if (stricmp(pMTD->pszTagName, "X-AuthUser") == 0) {
  2372. if (pszAuthName != NULL) {
  2373. StrNCpy(pszAuthName, pMTD->pszTagData, iSize);
  2374. StrTrim(pszAuthName, " trn");
  2375. }
  2376. return (0);
  2377. }
  2378. }
  2379. ErrSetErrorCode(ERR_NO_MESSAGE_AUTH);
  2380. return (ERR_NO_MESSAGE_AUTH);
  2381. }