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

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "SList.h"
  26. #include "ShBlocks.h"
  27. #include "StrUtils.h"
  28. #include "BuffSock.h"
  29. #include "MiscUtils.h"
  30. #include "ResLocks.h"
  31. #include "BuffSock.h"
  32. #include "MessQueue.h"
  33. #include "SvrUtils.h"
  34. #include "UsrUtils.h"
  35. #include "SMTPUtils.h"
  36. #include "SMAILUtils.h"
  37. #include "ExtAliases.h"
  38. #include "UsrMailList.h"
  39. #include "MailConfig.h"
  40. #include "LMAILSvr.h"
  41. #include "AppDefines.h"
  42. #include "MailSvr.h"
  43. #define LMAIL_SERVER_NAME           "[" APP_NAME_VERSION_STR " LMAIL Server]"
  44. #define LOCAL_SPOOL_DIR             "local"
  45. #define LMAIL_LOG_FILE              "lmail"
  46. static LMAILConfig *LMAILGetConfigCopy(SHB_HANDLE hShbLMAIL);
  47. static int LMAILThreadCountAdd(long lCount, SHB_HANDLE hShbLMAIL, LMAILConfig * pLMAILCfg = NULL);
  48. static int LMAILLogEnabled(SHB_HANDLE hShbLMAIL, LMAILConfig * pLMAILCfg = NULL);
  49. static int LMAILProcessLocalSpool(SHB_HANDLE hShbLMAIL, long lThreadId);
  50. static int LMAILGetFilesSnapShot(LMAILConfig * pLMAILCfg, long lThreadId, char *pszSSFileName);
  51. static int LMAILRemoveProcessed(LMAILConfig * pLMAILCfg, char const *pszListFileName);
  52. static int LMAILProcessList(LMAILConfig * pLMAILCfg, long lThreadId, char const *pszSSFileName);
  53. static int LMAILSubmitLocalFile(LMAILConfig * pLMAILCfg, const char *pszMailFile,
  54. long lThreadId, char const *pszSMTPDomain);
  55. static int LMAILAddReceived(FILE * pSpoolFile, char const *pszSMTPDomain,
  56.     char const *pszMailFrom, char const *pszRcptTo, char const *pszTime);
  57. static int LMAILLogMessage(char const *pszMailFile, char const *pszSMTPDomain,
  58.    char const *pszMessageID);
  59. char *LMAILGetSpoolDir(char *pszSpoolPath, int iMaxPath)
  60. {
  61. SvrGetSpoolDir(pszSpoolPath, iMaxPath);
  62. AppendSlash(pszSpoolPath);
  63. StrNCat(pszSpoolPath, LOCAL_SPOOL_DIR, iMaxPath);
  64. return (pszSpoolPath);
  65. }
  66. static LMAILConfig *LMAILGetConfigCopy(SHB_HANDLE hShbLMAIL)
  67. {
  68. LMAILConfig *pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
  69. if (pLMAILCfg == NULL)
  70. return (NULL);
  71. LMAILConfig *pNewLMAILCfg = (LMAILConfig *) SysAlloc(sizeof(LMAILConfig));
  72. if (pNewLMAILCfg != NULL)
  73. memcpy(pNewLMAILCfg, pLMAILCfg, sizeof(LMAILConfig));
  74. ShbUnlock(hShbLMAIL);
  75. return (pNewLMAILCfg);
  76. }
  77. static int LMAILThreadCountAdd(long lCount, SHB_HANDLE hShbLMAIL, LMAILConfig * pLMAILCfg)
  78. {
  79. int iDoUnlock = 0;
  80. if (pLMAILCfg == NULL) {
  81. if ((pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL)) == NULL)
  82. return (ErrGetErrorCode());
  83. ++iDoUnlock;
  84. }
  85. pLMAILCfg->lThreadCount += lCount;
  86. if (iDoUnlock)
  87. ShbUnlock(hShbLMAIL);
  88. return (0);
  89. }
  90. static int LMAILLogEnabled(SHB_HANDLE hShbLMAIL, LMAILConfig * pLMAILCfg)
  91. {
  92. int iDoUnlock = 0;
  93. if (pLMAILCfg == NULL) {
  94. if ((pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL)) == NULL)
  95. return (ErrGetErrorCode());
  96. ++iDoUnlock;
  97. }
  98. unsigned long ulFlags = pLMAILCfg->ulFlags;
  99. if (iDoUnlock)
  100. ShbUnlock(hShbLMAIL);
  101. return ((ulFlags & LMAILF_LOG_ENABLED) ? 1 : 0);
  102. }
  103. unsigned int LMAILThreadProc(void *pThreadData)
  104. {
  105. LMAILConfig *pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
  106. if (pLMAILCfg == NULL) {
  107. ErrorPush();
  108. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  109. return (ErrorPop());
  110. }
  111. ///////////////////////////////////////////////////////////////////////////////
  112. //  Get thread id and sleep timeout
  113. ///////////////////////////////////////////////////////////////////////////////
  114. int iSleepTimeout = pLMAILCfg->iSleepTimeout;
  115. long lThreadId = pLMAILCfg->lThreadCount;
  116. ///////////////////////////////////////////////////////////////////////////////
  117. //  Increase thread count
  118. ///////////////////////////////////////////////////////////////////////////////
  119. LMAILThreadCountAdd(+1, hShbLMAIL, pLMAILCfg);
  120. ShbUnlock(hShbLMAIL);
  121. SysLogMessage(LOG_LEV_MESSAGE, "LMAIL thread [%02ld] startedn", lThreadId);
  122. for (;;) {
  123. ///////////////////////////////////////////////////////////////////////////////
  124. //  Check shutdown condition
  125. ///////////////////////////////////////////////////////////////////////////////
  126. pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
  127. if ((pLMAILCfg == NULL) || (pLMAILCfg->ulFlags & LMAILF_STOP_SERVER)) {
  128. SysLogMessage(LOG_LEV_MESSAGE, "LMAIL thread [%02ld] exitingn",
  129.       lThreadId);
  130. if (pLMAILCfg != NULL)
  131. ShbUnlock(hShbLMAIL);
  132. break;
  133. }
  134. ShbUnlock(hShbLMAIL);
  135. ///////////////////////////////////////////////////////////////////////////////
  136. //  Process local spool files
  137. ///////////////////////////////////////////////////////////////////////////////
  138. int iProcessResult = LMAILProcessLocalSpool(hShbLMAIL, lThreadId);
  139. if (iProcessResult == ERR_NO_LOCAL_SPOOL_FILES)
  140. SysSleep(iSleepTimeout);
  141. }
  142. ///////////////////////////////////////////////////////////////////////////////
  143. //  Decrease thread count
  144. ///////////////////////////////////////////////////////////////////////////////
  145. LMAILThreadCountAdd(-1, hShbLMAIL);
  146. SysLogMessage(LOG_LEV_MESSAGE, "LMAIL thread [%02ld] stoppedn", lThreadId);
  147. return (0);
  148. }
  149. static int LMAILProcessLocalSpool(SHB_HANDLE hShbLMAIL, long lThreadId)
  150. {
  151. LMAILConfig *pLMAILCfg = LMAILGetConfigCopy(hShbLMAIL);
  152. if (pLMAILCfg == NULL)
  153. return (ErrGetErrorCode());
  154. char szSSFileName[SYS_MAX_PATH] = "";
  155. if (LMAILGetFilesSnapShot(pLMAILCfg, lThreadId, szSSFileName) < 0) {
  156. ErrorPush();
  157. SysFree(pLMAILCfg);
  158. return (ErrorPop());
  159. }
  160. if (LMAILProcessList(pLMAILCfg, lThreadId, szSSFileName) < 0) {
  161. ErrorPush();
  162. SysRemove(szSSFileName);
  163. SysFree(pLMAILCfg);
  164. return (ErrorPop());
  165. }
  166. LMAILRemoveProcessed(pLMAILCfg, szSSFileName);
  167. SysRemove(szSSFileName);
  168. SysFree(pLMAILCfg);
  169. return (0);
  170. }
  171. static int LMAILGetFilesSnapShot(LMAILConfig * pLMAILCfg, long lThreadId, char *pszSSFileName)
  172. {
  173. char szSpoolDir[SYS_MAX_PATH] = "";
  174. LMAILGetSpoolDir(szSpoolDir, sizeof(szSpoolDir));
  175. ///////////////////////////////////////////////////////////////////////////////
  176. //  Share lock local spool directory
  177. ///////////////////////////////////////////////////////////////////////////////
  178. char szResLock[SYS_MAX_PATH] = "";
  179. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(szSpoolDir, szResLock,
  180.   sizeof(szResLock)));
  181. if (hResLock == INVALID_RLCK_HANDLE)
  182. return (ErrGetErrorCode());
  183. SysGetTmpFile(pszSSFileName);
  184. FILE *pSSFile = fopen(pszSSFileName, "wb");
  185. if (pSSFile == NULL) {
  186. ErrorPush();
  187. RLckUnlockSH(hResLock);
  188. return (ErrorPop());
  189. }
  190. int iFileCount = 0;
  191. char szSpoolFileName[SYS_MAX_PATH] = "";
  192. FSCAN_HANDLE hFileScan = MscFirstFile(szSpoolDir, 0, szSpoolFileName);
  193. if (hFileScan != INVALID_FSCAN_HANDLE) {
  194. do {
  195. SYS_UINT32 uHashValue =
  196.     MscHashString(szSpoolFileName, strlen(szSpoolFileName));
  197. if ((uHashValue % (SYS_UINT32) pLMAILCfg->lNumThreads) ==
  198.     (SYS_UINT32) lThreadId) {
  199. fprintf(pSSFile, "%srn", szSpoolFileName);
  200. ++iFileCount;
  201. }
  202. } while (MscNextFile(hFileScan, szSpoolFileName));
  203. MscCloseFindFile(hFileScan);
  204. }
  205. fclose(pSSFile);
  206. RLckUnlockSH(hResLock);
  207. if (iFileCount == 0) {
  208. SysRemove(pszSSFileName);
  209. SetEmptyString(pszSSFileName);
  210. ErrSetErrorCode(ERR_NO_LOCAL_SPOOL_FILES);
  211. return (ERR_NO_LOCAL_SPOOL_FILES);
  212. }
  213. return (0);
  214. }
  215. static int LMAILRemoveProcessed(LMAILConfig * pLMAILCfg, char const *pszListFileName)
  216. {
  217. char szSpoolDir[SYS_MAX_PATH] = "";
  218. LMAILGetSpoolDir(szSpoolDir, sizeof(szSpoolDir));
  219. ///////////////////////////////////////////////////////////////////////////////
  220. //  Share lock local spool directory
  221. ///////////////////////////////////////////////////////////////////////////////
  222. char szResLock[SYS_MAX_PATH] = "";
  223. RLCK_HANDLE hResLock = RLckLockEX(CfgGetBasedPath(szSpoolDir, szResLock,
  224.   sizeof(szResLock)));
  225. if (hResLock == INVALID_RLCK_HANDLE)
  226. return (ErrGetErrorCode());
  227. FILE *pSSFile = fopen(pszListFileName, "rb");
  228. if (pSSFile == NULL) {
  229. ErrorPush();
  230. RLckUnlockEX(hResLock);
  231. return (ErrorPop());
  232. }
  233. char szSpoolFileName[SYS_MAX_PATH] = "";
  234. while (MscGetString(pSSFile, szSpoolFileName, sizeof(szSpoolFileName) - 1) != NULL) {
  235. char szSpoolFilePath[SYS_MAX_PATH] = "";
  236. sprintf(szSpoolFilePath, "%s%s%s", szSpoolDir, SYS_SLASH_STR, szSpoolFileName);
  237. CheckRemoveFile(szSpoolFilePath);
  238. }
  239. fclose(pSSFile);
  240. RLckUnlockEX(hResLock);
  241. return (0);
  242. }
  243. static int LMAILProcessList(LMAILConfig * pLMAILCfg, long lThreadId, char const *pszSSFileName)
  244. {
  245. char szSpoolDir[SYS_MAX_PATH] = "";
  246. LMAILGetSpoolDir(szSpoolDir, sizeof(szSpoolDir));
  247. ///////////////////////////////////////////////////////////////////////////////
  248. //  Retrieve SMTP domain
  249. ///////////////////////////////////////////////////////////////////////////////
  250. SVRCFG_HANDLE hSvrConfig = SvrGetConfigHandle();
  251. if (hSvrConfig == INVALID_SVRCFG_HANDLE)
  252. return (ErrGetErrorCode());
  253. char szSMTPDomain[MAX_HOST_NAME] = "localdomain";
  254. char *pszDefDomain = SvrGetConfigVar(hSvrConfig, "RootDomain");
  255. if (pszDefDomain != NULL) {
  256. StrSNCpy(szSMTPDomain, pszDefDomain);
  257. SysFree(pszDefDomain);
  258. }
  259. SvrReleaseConfigHandle(hSvrConfig);
  260. FILE *pSSFile = fopen(pszSSFileName, "rb");
  261. if (pSSFile == NULL)
  262. return (ErrGetErrorCode());
  263. char szSpoolFileName[SYS_MAX_PATH] = "";
  264. while (MscGetString(pSSFile, szSpoolFileName, sizeof(szSpoolFileName) - 1) != NULL) {
  265. char szSpoolFilePath[SYS_MAX_PATH] = "";
  266. sprintf(szSpoolFilePath, "%s%s%s", szSpoolDir, SYS_SLASH_STR, szSpoolFileName);
  267. if (LMAILSubmitLocalFile(pLMAILCfg, szSpoolFilePath, lThreadId, szSMTPDomain) < 0) {
  268. SysLogMessage(LOG_LEV_ERROR, "LMAIL [%02ld] error ( "%s" ): %sn",
  269.       lThreadId, ErrGetErrorString(), szSpoolFilePath);
  270. } else {
  271. SysLogMessage(LOG_LEV_MESSAGE, "LMAIL [%02ld] file processed: %sn",
  272.       lThreadId, szSpoolFilePath);
  273. }
  274. }
  275. fclose(pSSFile);
  276. return (0);
  277. }
  278. static int LMAILSubmitLocalFile(LMAILConfig * pLMAILCfg, const char *pszMailFile,
  279. long lThreadId, char const *pszSMTPDomain)
  280. {
  281. FILE *pMailFile = fopen(pszMailFile, "rb");
  282. if (pMailFile == NULL) {
  283. ErrSetErrorCode(ERR_FILE_OPEN);
  284. return (ERR_FILE_OPEN);
  285. }
  286. ///////////////////////////////////////////////////////////////////////////////
  287. //  Get a message ID
  288. ///////////////////////////////////////////////////////////////////////////////
  289. SYS_UINT64 uMessageID;
  290. char szMessageID[128] = "";
  291. if (SvrGetMessageID(&uMessageID) < 0) {
  292. ErrorPush();
  293. fclose(pMailFile);
  294. return (ErrorPop());
  295. }
  296. sprintf(szMessageID, "L" SYS_LLX_FMT, uMessageID);
  297. ///////////////////////////////////////////////////////////////////////////////
  298. //  Get current time
  299. ///////////////////////////////////////////////////////////////////////////////
  300. char szTime[256] = "";
  301. MscGetTimeStr(szTime, sizeof(szTime) - 1);
  302. ///////////////////////////////////////////////////////////////////////////////
  303. //  Log current opeartion
  304. ///////////////////////////////////////////////////////////////////////////////
  305. if (LMAILLogEnabled(SHB_INVALID_HANDLE, pLMAILCfg))
  306. LMAILLogMessage(pszMailFile, pszSMTPDomain, szMessageID);
  307. ///////////////////////////////////////////////////////////////////////////////
  308. //  Search mail data start
  309. ///////////////////////////////////////////////////////////////////////////////
  310. char szSpoolLine[MAX_SPOOL_LINE] = "";
  311. while (MscGetString(pMailFile, szSpoolLine, sizeof(szSpoolLine) - 1) != NULL)
  312. if (IsEmptyString(szSpoolLine))
  313. break;
  314. if (feof(pMailFile)) {
  315. fclose(pMailFile);
  316. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszMailFile);
  317. return (ERR_INVALID_SPOOL_FILE);
  318. }
  319. ///////////////////////////////////////////////////////////////////////////////
  320. //  Get the offset at which the message data begin and rewind the file
  321. ///////////////////////////////////////////////////////////////////////////////
  322. unsigned long ulMsgOffset = (unsigned long) ftell(pMailFile);
  323. rewind(pMailFile);
  324. ///////////////////////////////////////////////////////////////////////////////
  325. //  Read "MAIL FROM:" ( 1th row of the smtp-mail file )
  326. ///////////////////////////////////////////////////////////////////////////////
  327. char szMailFrom[MAX_SPOOL_LINE] = "";
  328. if ((MscGetString(pMailFile, szMailFrom, sizeof(szMailFrom) - 1) == NULL) ||
  329.     (StrINComp(szMailFrom, MAIL_FROM_STR) != 0)) {
  330. fclose(pMailFile);
  331. ErrSetErrorCode(ERR_INVALID_SPOOL_FILE, pszMailFile);
  332. return (ERR_INVALID_SPOOL_FILE);
  333. }
  334. ///////////////////////////////////////////////////////////////////////////////
  335. //  Read "RCPT TO:" ( 2nd[,...] row(s) of the local-mail file )
  336. ///////////////////////////////////////////////////////////////////////////////
  337. while ((MscGetString(pMailFile, szSpoolLine, sizeof(szSpoolLine) - 1) != NULL) &&
  338.        !IsEmptyString(szSpoolLine)) {
  339. ///////////////////////////////////////////////////////////////////////////////
  340. //  Get message handle
  341. ///////////////////////////////////////////////////////////////////////////////
  342. QMSG_HANDLE hMessage = QueCreateMessage(hSpoolQueue);
  343. if (hMessage == INVALID_QMSG_HANDLE) {
  344. ErrorPush();
  345. fclose(pMailFile);
  346. return (ErrorPop());
  347. }
  348. char szQueueFilePath[SYS_MAX_PATH] = "";
  349. QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
  350. FILE *pSpoolFile = fopen(szQueueFilePath, "wb");
  351. if (pSpoolFile == NULL) {
  352. QueCleanupMessage(hSpoolQueue, hMessage);
  353. QueCloseMessage(hSpoolQueue, hMessage);
  354. fclose(pMailFile);
  355. ErrSetErrorCode(ERR_FILE_CREATE);
  356. return (ERR_FILE_CREATE);
  357. }
  358. ///////////////////////////////////////////////////////////////////////////////
  359. //  Write info line
  360. ///////////////////////////////////////////////////////////////////////////////
  361. USmtpWriteInfoLine(pSpoolFile, LOCAL_ADDRESS_SQB ":0",
  362.    LOCAL_ADDRESS_SQB ":0", szTime);
  363. ///////////////////////////////////////////////////////////////////////////////
  364. //  Write SMTP domain
  365. ///////////////////////////////////////////////////////////////////////////////
  366. fprintf(pSpoolFile, "%srn", pszSMTPDomain);
  367. ///////////////////////////////////////////////////////////////////////////////
  368. //  Write message ID
  369. ///////////////////////////////////////////////////////////////////////////////
  370. fprintf(pSpoolFile, "%srn", szMessageID);
  371. ///////////////////////////////////////////////////////////////////////////////
  372. //  Write "MAIL FROM:"
  373. ///////////////////////////////////////////////////////////////////////////////
  374. fprintf(pSpoolFile, "%srn", szMailFrom);
  375. ///////////////////////////////////////////////////////////////////////////////
  376. //  Write "RCPT TO:"
  377. ///////////////////////////////////////////////////////////////////////////////
  378. fprintf(pSpoolFile, "%srn", szSpoolLine);
  379. ///////////////////////////////////////////////////////////////////////////////
  380. //  Write SPOOL_FILE_DATA_START
  381. ///////////////////////////////////////////////////////////////////////////////
  382. fprintf(pSpoolFile, "%srn", SPOOL_FILE_DATA_START);
  383. ///////////////////////////////////////////////////////////////////////////////
  384. //  Write "Received:" tag
  385. ///////////////////////////////////////////////////////////////////////////////
  386. LMAILAddReceived(pSpoolFile, pszSMTPDomain, szMailFrom, szSpoolLine, szTime);
  387. ///////////////////////////////////////////////////////////////////////////////
  388. //  Write mail data, saving and restoring the current file pointer
  389. ///////////////////////////////////////////////////////////////////////////////
  390. unsigned long ulCurrOffset = (unsigned long) ftell(pMailFile);
  391. if (MscCopyFile(pSpoolFile, pMailFile, ulMsgOffset, (unsigned long) -1) < 0) {
  392. ErrorPush();
  393. fclose(pSpoolFile);
  394. QueCleanupMessage(hSpoolQueue, hMessage);
  395. QueCloseMessage(hSpoolQueue, hMessage);
  396. fclose(pMailFile);
  397. return (ErrorPop());
  398. }
  399. if (SysFileSync(pSpoolFile) < 0) {
  400. ErrorPush();
  401. fclose(pSpoolFile);
  402. QueCleanupMessage(hSpoolQueue, hMessage);
  403. QueCloseMessage(hSpoolQueue, hMessage);
  404. fclose(pMailFile);
  405. return (ErrorPop());
  406. }
  407. if (fclose(pSpoolFile)) {
  408. QueCleanupMessage(hSpoolQueue, hMessage);
  409. QueCloseMessage(hSpoolQueue, hMessage);
  410. fclose(pMailFile);
  411. ErrSetErrorCode(ERR_FILE_WRITE, szQueueFilePath);
  412. return (ERR_FILE_WRITE);
  413. }
  414. fseek(pMailFile, ulCurrOffset, SEEK_SET);
  415. ///////////////////////////////////////////////////////////////////////////////
  416. //  Transfer file to the spool
  417. ///////////////////////////////////////////////////////////////////////////////
  418. if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
  419. ErrorPush();
  420. QueCleanupMessage(hSpoolQueue, hMessage);
  421. QueCloseMessage(hSpoolQueue, hMessage);
  422. fclose(pMailFile);
  423. return (ErrorPop());
  424. }
  425. }
  426. fclose(pMailFile);
  427. return (0);
  428. }
  429. static int LMAILAddReceived(FILE * pSpoolFile, char const *pszSMTPDomain,
  430.     char const *pszMailFrom, char const *pszRcptTo, char const *pszTime)
  431. {
  432. char szFrom[MAX_SMTP_ADDRESS] = "";
  433. char szRcpt[MAX_SMTP_ADDRESS] = "";
  434. if ((USmlParseAddress(pszMailFrom, NULL, 0, szFrom, sizeof(szFrom) - 1) < 0) ||
  435.     (USmlParseAddress(pszRcptTo, NULL, 0, szRcpt, sizeof(szRcpt) - 1) < 0))
  436. return (ErrGetErrorCode());
  437. ///////////////////////////////////////////////////////////////////////////////
  438. //  Add "Received:" tag
  439. ///////////////////////////////////////////////////////////////////////////////
  440. fprintf(pSpoolFile,
  441. "Received: from /spool/localrn"
  442. "tby %s with %srn"
  443. "tfor <%s> from <%s>;rn"
  444. "t%srn", pszSMTPDomain, LMAIL_SERVER_NAME, szRcpt, szFrom, pszTime);
  445. return (0);
  446. }
  447. static int LMAILLogMessage(char const *pszMailFile, char const *pszSMTPDomain,
  448.    char const *pszMessageID)
  449. {
  450. char szTime[256] = "";
  451. MscGetTimeNbrString(szTime, sizeof(szTime) - 1);
  452. char szLocalFile[SYS_MAX_PATH] = "";
  453. MscGetFileName(pszMailFile, szLocalFile);
  454. RLCK_HANDLE hResLock = RLckLockEX(SVR_LOGS_DIR SYS_SLASH_STR LMAIL_LOG_FILE);
  455. if (hResLock == INVALID_RLCK_HANDLE)
  456. return (ErrGetErrorCode());
  457. MscFileLog(LMAIL_LOG_FILE,
  458.    ""%s""
  459.    "t"%s""
  460.    "t"%s"" "t"%s"" "n", pszSMTPDomain, szLocalFile, pszMessageID, szTime);
  461. RLckUnlockEX(hResLock);
  462. return (0);
  463. }