QueueUtils.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:36k
- /*
- * XMail by Davide Libenzi ( Intranet and Internet mail server )
- * Copyright (C) 1999,..,2004 Davide Libenzi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Davide Libenzi <davidel@xmailserver.org>
- *
- */
- #include "SysInclude.h"
- #include "SysDep.h"
- #include "SvrDefines.h"
- #include "ShBlocks.h"
- #include "ResLocks.h"
- #include "StrUtils.h"
- #include "SList.h"
- #include "MD5.h"
- #include "Base64Enc.h"
- #include "BuffSock.h"
- #include "MessQueue.h"
- #include "MailConfig.h"
- #include "UsrUtils.h"
- #include "SvrUtils.h"
- #include "AppDefines.h"
- #include "MailSvr.h"
- #include "MiscUtils.h"
- #include "SMTPUtils.h"
- #include "SMAILUtils.h"
- #include "QueueUtils.h"
- #define QUE_SMTP_MAILER_ERROR_HDR "X-MailerError"
- #define QUE_MAILER_HDR "X-MailerServer"
- static int QueUtDumpFrozen(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, FILE * pListFile);
- static char *QueUtGetLogEntryVar(char const *pszLog, char const *pszVarName);
- static char *QueUtGetReplyAddress(SPLF_HANDLE hFSpool);
- static int QueUtTXErrorNotifySender(SPLF_HANDLE hFSpool, char const *pszAdminAddrVar,
- char const *pszReason, char const *pszText,
- char const *pszServer, char const *pszLogFile);
- static int QueUtTXErrorExNotifySender(SPLF_HANDLE hFSpool, char const *pszMessFilePath,
- char const *pszAdminAddrVar, char const *pszReason,
- char const *pszText, char const *pszServer,
- char const *pszLogFile);
- static int QueUtTXErrorNotifyRoot(SPLF_HANDLE hFSpool, char const *pszReason,
- char const *pszLogFile);
- static int QueUtTXErrorExNotifyRoot(SPLF_HANDLE hFSpool, char const *pszMessFilePath,
- char const *pszReason, char const *pszLogFile);
- static int QueUtBuildErrorRespose(char const *pszSMTPDomain, SPLF_HANDLE hFSpool,
- char const *pszFrom, char const *pszSmtpFrom, char const *pszTo,
- char const *pszResponseFile, char const *pszReason,
- char const *pszText, char const *pszServer, int iLinesExtra,
- char const *pszLogFile);
- static int QueUtDumpFrozen(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, FILE * pListFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Get message file path
- ///////////////////////////////////////////////////////////////////////////////
- char szQueueFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szQueueFilePath);
- ///////////////////////////////////////////////////////////////////////////////
- // Load spool file info and make a type check
- ///////////////////////////////////////////////////////////////////////////////
- SYS_FILE_INFO FI;
- if (SysGetFileInfo(szQueueFilePath, FI) < 0)
- return (ErrGetErrorCode());
- ///////////////////////////////////////////////////////////////////////////////
- // Load the spool file header
- ///////////////////////////////////////////////////////////////////////////////
- SpoolFileHeader SFH;
- if (USmlLoadSpoolFileHeader(szQueueFilePath, SFH) < 0)
- return (ErrGetErrorCode());
- char *pszFrom = USmlAddrConcat(SFH.ppszFrom);
- if (pszFrom == NULL) {
- ErrorPush();
- USmlCleanupSpoolFileHeader(SFH);
- return (ErrorPop());
- }
- char *pszRcpt = USmlAddrConcat(SFH.ppszRcpt);
- if (pszRcpt == NULL) {
- ErrorPush();
- SysFree(pszFrom);
- USmlCleanupSpoolFileHeader(SFH);
- return (ErrorPop());
- }
- char szTime[128] = "";
- MscGetTimeNbrString(szTime, sizeof(szTime) - 1, FI.tMod);
- fprintf(pListFile,
- ""%s"t"
- ""%d"t"
- ""%d"t"
- ""<%s>"t"
- ""<%s>"t"
- ""%s"t"
- ""%lu"n",
- QueGetFileName(hMessage), QueGetLevel1(hMessage), QueGetLevel2(hMessage),
- pszFrom, pszRcpt, szTime, FI.ulSize);
- SysFree(pszRcpt);
- SysFree(pszFrom);
- USmlCleanupSpoolFileHeader(SFH);
- return (0);
- }
- int QueUtGetFrozenList(QUEUE_HANDLE hQueue, char const *pszListFile)
- {
- int iNumDirsLevel = QueGetDirsLevel(hQueue);
- char const *pszRootPath = QueGetRootPath(hQueue);
- ///////////////////////////////////////////////////////////////////////////////
- // Creates the list file and start scanning the frozen queue
- ///////////////////////////////////////////////////////////////////////////////
- FILE *pListFile = fopen(pszListFile, "wt");
- if (pListFile == NULL) {
- ErrSetErrorCode(ERR_FILE_CREATE, pszListFile);
- return (ERR_FILE_CREATE);
- }
- for (int ii = 0; ii < iNumDirsLevel; ii++) {
- for (int jj = 0; jj < iNumDirsLevel; jj++) {
- char szCurrPath[SYS_MAX_PATH] = "";
- sprintf(szCurrPath, "%s%d%s%d%s%s",
- pszRootPath, ii, SYS_SLASH_STR, jj, SYS_SLASH_STR,
- QUEUE_FROZ_DIR);
- char szFrozFileName[SYS_MAX_PATH] = "";
- FSCAN_HANDLE hFileScan = MscFirstFile(szCurrPath, 0, szFrozFileName);
- if (hFileScan != INVALID_FSCAN_HANDLE) {
- do {
- if (!SYS_IS_VALID_FILENAME(szFrozFileName))
- continue;
- ///////////////////////////////////////////////////////////////////////////////
- // Create queue file handle
- ///////////////////////////////////////////////////////////////////////////////
- QMSG_HANDLE hMessage =
- QueGetHandle(hQueue, ii, jj, QUEUE_FROZ_DIR,
- szFrozFileName);
- if (hMessage != INVALID_QMSG_HANDLE) {
- QueUtDumpFrozen(hQueue, hMessage, pListFile);
- QueCloseMessage(hQueue, hMessage);
- }
- } while (MscNextFile(hFileScan, szFrozFileName));
- MscCloseFindFile(hFileScan);
- }
- }
- }
- fclose(pListFile);
- return (0);
- }
- int QueUtUnFreezeMessage(QUEUE_HANDLE hQueue, int iLevel1, int iLevel2,
- char const *pszMessageFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Create queue file handle
- ///////////////////////////////////////////////////////////////////////////////
- QMSG_HANDLE hMessage = QueGetHandle(hQueue, iLevel1, iLevel2, QUEUE_FROZ_DIR,
- pszMessageFile);
- if (hMessage == INVALID_QMSG_HANDLE)
- return (ErrGetErrorCode());
- ///////////////////////////////////////////////////////////////////////////////
- // Init message statistics
- ///////////////////////////////////////////////////////////////////////////////
- QueInitMessageStats(hQueue, hMessage);
- ///////////////////////////////////////////////////////////////////////////////
- // Try to re-commit the frozen message
- ///////////////////////////////////////////////////////////////////////////////
- if (QueCommitMessage(hQueue, hMessage) < 0) {
- ErrorPush();
- QueCloseMessage(hQueue, hMessage);
- return (ErrorPop());
- }
- return (0);
- }
- int QueUtDeleteFrozenMessage(QUEUE_HANDLE hQueue, int iLevel1, int iLevel2,
- char const *pszMessageFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Create queue file handle
- ///////////////////////////////////////////////////////////////////////////////
- QMSG_HANDLE hMessage = QueGetHandle(hQueue, iLevel1, iLevel2, QUEUE_FROZ_DIR,
- pszMessageFile);
- if (hMessage == INVALID_QMSG_HANDLE)
- return (ErrGetErrorCode());
- QueCleanupMessage(hQueue, hMessage);
- QueCloseMessage(hQueue, hMessage);
- return (0);
- }
- int QueUtGetFrozenMsgFile(QUEUE_HANDLE hQueue, int iLevel1, int iLevel2,
- char const *pszMessageFile, char const *pszOutFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Create queue file handle
- ///////////////////////////////////////////////////////////////////////////////
- QMSG_HANDLE hMessage = QueGetHandle(hQueue, iLevel1, iLevel2, QUEUE_FROZ_DIR,
- pszMessageFile);
- if (hMessage == INVALID_QMSG_HANDLE)
- return (ErrGetErrorCode());
- ///////////////////////////////////////////////////////////////////////////////
- // Get slog file path
- ///////////////////////////////////////////////////////////////////////////////
- char szQueueFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szQueueFilePath);
- ///////////////////////////////////////////////////////////////////////////////
- // Copy the requested file
- ///////////////////////////////////////////////////////////////////////////////
- if (MscCopyFile(pszOutFile, szQueueFilePath) < 0) {
- ErrorPush();
- QueCloseMessage(hQueue, hMessage);
- return (ErrorPop());
- }
- QueCloseMessage(hQueue, hMessage);
- return (0);
- }
- int QueUtGetFrozenLogFile(QUEUE_HANDLE hQueue, int iLevel1, int iLevel2,
- char const *pszMessageFile, char const *pszOutFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Create queue file handle
- ///////////////////////////////////////////////////////////////////////////////
- QMSG_HANDLE hMessage = QueGetHandle(hQueue, iLevel1, iLevel2, QUEUE_FROZ_DIR,
- pszMessageFile);
- if (hMessage == INVALID_QMSG_HANDLE)
- return (ErrGetErrorCode());
- ///////////////////////////////////////////////////////////////////////////////
- // Get slog file path
- ///////////////////////////////////////////////////////////////////////////////
- char szQueueFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szQueueFilePath, QUEUE_SLOG_DIR);
- ///////////////////////////////////////////////////////////////////////////////
- // Copy the requested file
- ///////////////////////////////////////////////////////////////////////////////
- if (MscCopyFile(pszOutFile, szQueueFilePath) < 0) {
- ErrorPush();
- QueCloseMessage(hQueue, hMessage);
- return (ErrorPop());
- }
- QueCloseMessage(hQueue, hMessage);
- return (0);
- }
- int QueUtErrLogMessage(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, char const *pszFormat, ...)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Get slog file path
- ///////////////////////////////////////////////////////////////////////////////
- char szSlogFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szSlogFilePath, QUEUE_SLOG_DIR);
- char *pszMessage = NULL;
- STRSPRINTF(pszMessage, pszFormat, pszFormat);
- if (pszMessage == NULL)
- return (ErrGetErrorCode());
- if (ErrFileLogString(szSlogFilePath, pszMessage) < 0) {
- SysFree(pszMessage);
- return (ErrGetErrorCode());
- }
- SysFree(pszMessage);
- return (0);
- }
- static char *QueUtGetLogEntryVar(char const *pszLog, char const *pszVarName)
- {
- char const *pszEPos;
- char const *pszEnd;
- if (((pszEPos = strstr(pszLog, pszVarName)) == NULL) ||
- ((pszEPos = strchr(pszEPos, '=')) == NULL))
- return (NULL);
- ++pszEPos;
- StrSkipSpaces(pszEPos);
- if (((pszEnd = strchr(pszEPos, 'r')) == NULL) &&
- ((pszEnd = strchr(pszEPos, 'n')) == NULL))
- pszEnd = pszEPos + strlen(pszEPos);
- if (*pszEPos == '"') {
- ++pszEPos;
- if (pszEnd[-1] == '"')
- pszEnd--;
- }
- int iVarLength = (int) (pszEnd - pszEPos);
- if (iVarLength <= 0)
- return (NULL);
- char *pszVarValue = (char *) SysAlloc(iVarLength + 1);
- if (pszVarValue != NULL) {
- memcpy(pszVarValue, pszEPos, iVarLength);
- pszVarValue[iVarLength] = ' ';
- }
- return (pszVarValue);
- }
- int QueUtGetLastLogInfo(char const *pszLogFilePath, QueLogInfo * pQLI)
- {
- char *pszEntry = QueLoadLastLogEntry(pszLogFilePath);
- pQLI->pszReason = pQLI->pszServer = NULL;
- if (pszEntry == NULL)
- return (ErrGetErrorCode());
- pQLI->pszReason = QueUtGetLogEntryVar(pszEntry, SMTP_ERROR_VARNAME);
- pQLI->pszServer = QueUtGetLogEntryVar(pszEntry, SMTP_SERVER_VARNAME);
- SysFree(pszEntry);
- return (0);
- }
- void QueUtFreeLastLogInfo(QueLogInfo * pQLI)
- {
- if (pQLI->pszServer != NULL)
- SysFree(pQLI->pszServer);
- if (pQLI->pszReason != NULL)
- SysFree(pQLI->pszReason);
- }
- bool QueUtRemoveSpoolErrors(void)
- {
- return (SvrTestConfigFlag("RemoveSpoolErrors", false));
- }
- int QueUtNotifyPermErrDelivery(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
- SPLF_HANDLE hFSpool, char const *pszReason,
- char const *pszServer, bool bCleanup)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Get message file path
- ///////////////////////////////////////////////////////////////////////////////
- char szQueueFilePath[SYS_MAX_PATH] = "";
- char szQueueLogFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szQueueFilePath);
- QueGetFilePath(hQueue, hMessage, szQueueLogFilePath, QUEUE_SLOG_DIR);
- ///////////////////////////////////////////////////////////////////////////////
- // Load log information from the slog file
- ///////////////////////////////////////////////////////////////////////////////
- bool bFreeLogInfo = false;
- QueLogInfo QLI;
- if ((pszReason == NULL) || (pszServer == NULL)) {
- QueUtGetLastLogInfo(szQueueLogFilePath, &QLI);
- if (pszReason == NULL)
- pszReason = QLI.pszReason;
- if (pszServer == NULL)
- pszServer = QLI.pszServer;
- bFreeLogInfo = true;
- }
- int iNotifyResult = QueUtTXErrorExNotifySender(hFSpool, szQueueFilePath,
- "ErrorsAdmin", pszReason, NULL,
- pszServer, szQueueLogFilePath);
- if (bCleanup)
- QueCleanupMessage(hQueue, hMessage, !QueUtRemoveSpoolErrors());
- if (bFreeLogInfo)
- QueUtFreeLastLogInfo(&QLI);
- return (0);
- }
- int QueUtNotifyTempErrDelivery(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
- SPLF_HANDLE hFSpool, char const *pszReason,
- char const *pszText, char const *pszServer)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Get message file path
- ///////////////////////////////////////////////////////////////////////////////
- char szQueueLogFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szQueueLogFilePath, QUEUE_SLOG_DIR);
- ///////////////////////////////////////////////////////////////////////////////
- // Load log information from the slog file
- ///////////////////////////////////////////////////////////////////////////////
- bool bFreeLogInfo = false;
- QueLogInfo QLI;
- if ((pszReason == NULL) || (pszServer == NULL)) {
- QueUtGetLastLogInfo(szQueueLogFilePath, &QLI);
- if (pszReason == NULL)
- pszReason = QLI.pszReason;
- if (pszServer == NULL)
- pszServer = QLI.pszServer;
- bFreeLogInfo = true;
- }
- int iNotifyResult = QueUtTXErrorNotifySender(hFSpool, "TempErrorsAdmin",
- pszReason, pszText, pszServer,
- szQueueLogFilePath);
- if (bFreeLogInfo)
- QueUtFreeLastLogInfo(&QLI);
- return (iNotifyResult);
- }
- int QueUtCleanupNotifyRoot(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage,
- SPLF_HANDLE hFSpool, char const *pszReason)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Get message file path
- ///////////////////////////////////////////////////////////////////////////////
- char szQueueFilePath[SYS_MAX_PATH] = "";
- char szQueueLogFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hQueue, hMessage, szQueueFilePath);
- QueGetFilePath(hQueue, hMessage, szQueueLogFilePath, QUEUE_SLOG_DIR);
- ///////////////////////////////////////////////////////////////////////////////
- // Load log information from the slog file
- ///////////////////////////////////////////////////////////////////////////////
- bool bFreeLogInfo = false;
- QueLogInfo QLI;
- if (pszReason == NULL) {
- QueUtGetLastLogInfo(szQueueLogFilePath, &QLI);
- pszReason = QLI.pszReason;
- bFreeLogInfo = true;
- }
- int iNotifyResult = QueUtTXErrorExNotifyRoot(hFSpool, szQueueFilePath, pszReason,
- szQueueLogFilePath);
- if (bFreeLogInfo)
- QueUtFreeLastLogInfo(&QLI);
- QueCleanupMessage(hQueue, hMessage, !QueUtRemoveSpoolErrors());
- return (0);
- }
- static char *QueUtGetReplyAddress(SPLF_HANDLE hFSpool)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Extract the sender
- ///////////////////////////////////////////////////////////////////////////////
- char const *const *ppszFrom = USmlGetMailFrom(hFSpool);
- int iFromDomains = StrStringsCount(ppszFrom);
- if (iFromDomains == 0) {
- ErrSetErrorCode(ERR_NULL_SENDER);
- return (NULL);
- }
- char const *pszSender = ppszFrom[iFromDomains - 1];
- char szSenderDomain[MAX_ADDR_NAME] = "";
- char szSenderName[MAX_ADDR_NAME] = "";
- if (USmtpSplitEmailAddr(pszSender, szSenderName, szSenderDomain) < 0)
- return (SysStrDup(pszSender));
- ///////////////////////////////////////////////////////////////////////////////
- // Lookup special reply-to header tags
- ///////////////////////////////////////////////////////////////////////////////
- return (SysStrDup(pszSender));
- }
- static int QueUtTXErrorNotifySender(SPLF_HANDLE hFSpool, char const *pszAdminAddrVar,
- char const *pszReason, char const *pszText,
- char const *pszServer, char const *pszLogFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Extract the sender
- ///////////////////////////////////////////////////////////////////////////////
- char *pszReplyTo = QueUtGetReplyAddress(hFSpool);
- if (pszReplyTo == NULL)
- return (ErrGetErrorCode());
- ///////////////////////////////////////////////////////////////////////////////
- // Load configuration handle
- ///////////////////////////////////////////////////////////////////////////////
- SVRCFG_HANDLE hSvrConfig = SvrGetConfigHandle();
- if (hSvrConfig == INVALID_SVRCFG_HANDLE) {
- ErrorPush();
- SysFree(pszReplyTo);
- return (ErrorPop());
- }
- char szPMAddress[MAX_ADDR_NAME] = "";
- char szMailDomain[MAX_HOST_NAME] = "";
- if ((SvrConfigVar("PostMaster", szPMAddress, sizeof(szPMAddress) - 1, hSvrConfig) < 0) ||
- (SvrConfigVar("RootDomain", szMailDomain, sizeof(szMailDomain) - 1, hSvrConfig) < 0))
- {
- SvrReleaseConfigHandle(hSvrConfig);
- SysFree(pszReplyTo);
- ErrSetErrorCode(ERR_INCOMPLETE_CONFIG);
- return (ERR_INCOMPLETE_CONFIG);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Get message handle
- ///////////////////////////////////////////////////////////////////////////////
- int iMsgLinesExtra = SvrGetConfigInt("NotifyMsgLinesExtra", 0, hSvrConfig);
- bool bSenderLog = SvrTestConfigFlag("NotifySendLogToSender", false, hSvrConfig);
- bool bNoSenderBounce = SvrTestConfigFlag("NoSenderBounce", false, hSvrConfig);
- QMSG_HANDLE hMessage = QueCreateMessage(hSpoolQueue);
- if (hMessage == INVALID_QMSG_HANDLE) {
- ErrorPush();
- SvrReleaseConfigHandle(hSvrConfig);
- SysFree(pszReplyTo);
- return (ErrorPop());
- }
- char szQueueFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
- ///////////////////////////////////////////////////////////////////////////////
- // Build error response mail file
- ///////////////////////////////////////////////////////////////////////////////
- if (QueUtBuildErrorRespose(szMailDomain, hFSpool, szPMAddress,
- bNoSenderBounce ? "": szPMAddress, pszReplyTo,
- szQueueFilePath, pszReason, pszText, pszServer,
- iMsgLinesExtra, bSenderLog ? pszLogFile : NULL) < 0) {
- ErrorPush();
- QueCleanupMessage(hSpoolQueue, hMessage);
- QueCloseMessage(hSpoolQueue, hMessage);
- SvrReleaseConfigHandle(hSvrConfig);
- SysFree(pszReplyTo);
- return (ErrorPop());
- }
- SysFree(pszReplyTo);
- ///////////////////////////////////////////////////////////////////////////////
- // Send error response mail file
- ///////////////////////////////////////////////////////////////////////////////
- if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
- ErrorPush();
- QueCleanupMessage(hSpoolQueue, hMessage);
- QueCloseMessage(hSpoolQueue, hMessage);
- SvrReleaseConfigHandle(hSvrConfig);
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Notify "error-handler" admin
- ///////////////////////////////////////////////////////////////////////////////
- char szEHAdmin[MAX_ADDR_NAME] = "";
- if ((SvrConfigVar(pszAdminAddrVar, szEHAdmin, sizeof(szEHAdmin) - 1, hSvrConfig) == 0) &&
- !IsEmptyString(szEHAdmin)) {
- ///////////////////////////////////////////////////////////////////////////////
- // Get message handle
- ///////////////////////////////////////////////////////////////////////////////
- if ((hMessage = QueCreateMessage(hSpoolQueue)) == INVALID_QMSG_HANDLE) {
- ErrorPush();
- SvrReleaseConfigHandle(hSvrConfig);
- return (ErrorPop());
- }
- QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
- ///////////////////////////////////////////////////////////////////////////////
- // Build error response mail file
- ///////////////////////////////////////////////////////////////////////////////
- if (QueUtBuildErrorRespose(szMailDomain, hFSpool, szPMAddress,
- bNoSenderBounce ? "": szPMAddress, szEHAdmin,
- szQueueFilePath, pszReason, pszText,
- pszServer, iMsgLinesExtra, pszLogFile) < 0) {
- ErrorPush();
- QueCleanupMessage(hSpoolQueue, hMessage);
- QueCloseMessage(hSpoolQueue, hMessage);
- SvrReleaseConfigHandle(hSvrConfig);
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Send error response mail file
- ///////////////////////////////////////////////////////////////////////////////
- if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
- ErrorPush();
- QueCleanupMessage(hSpoolQueue, hMessage);
- QueCloseMessage(hSpoolQueue, hMessage);
- SvrReleaseConfigHandle(hSvrConfig);
- return (ErrorPop());
- }
- }
- SvrReleaseConfigHandle(hSvrConfig);
- return (0);
- }
- static int QueUtTXErrorExNotifySender(SPLF_HANDLE hFSpool, char const *pszMessFilePath,
- char const *pszAdminAddrVar, char const *pszReason,
- char const *pszText, char const *pszServer,
- char const *pszLogFile)
- {
- bool bCloseHSpool = false;
- if (hFSpool == INVALID_SPLF_HANDLE) {
- if ((hFSpool = USmlCreateHandle(pszMessFilePath)) == INVALID_SPLF_HANDLE)
- return (ErrGetErrorCode());
- bCloseHSpool = true;
- }
- int iNotifyResult = QueUtTXErrorNotifySender(hFSpool, pszAdminAddrVar, pszReason,
- pszText, pszServer, pszLogFile);
- if (bCloseHSpool)
- USmlCloseHandle(hFSpool);
- return (iNotifyResult);
- }
- static int QueUtTXErrorNotifyRoot(SPLF_HANDLE hFSpool, char const *pszReason,
- char const *pszLogFile)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Load configuration handle
- ///////////////////////////////////////////////////////////////////////////////
- SVRCFG_HANDLE hSvrConfig = SvrGetConfigHandle();
- if (hSvrConfig == INVALID_SVRCFG_HANDLE)
- return (ErrGetErrorCode());
- char szPMAddress[MAX_ADDR_NAME] = "";
- char szMailDomain[MAX_HOST_NAME] = "";
- if ((SvrConfigVar("PostMaster", szPMAddress, sizeof(szPMAddress) - 1, hSvrConfig) < 0) ||
- (SvrConfigVar("RootDomain", szMailDomain, sizeof(szMailDomain) - 1, hSvrConfig) < 0))
- {
- SvrReleaseConfigHandle(hSvrConfig);
- ErrSetErrorCode(ERR_INCOMPLETE_CONFIG);
- return (ERR_INCOMPLETE_CONFIG);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Get message handle
- ///////////////////////////////////////////////////////////////////////////////
- int iMsgLinesExtra = SvrGetConfigInt("NotifyMsgLinesExtra", 0, hSvrConfig);
- QMSG_HANDLE hMessage = QueCreateMessage(hSpoolQueue);
- if (hMessage == INVALID_QMSG_HANDLE) {
- ErrorPush();
- SvrReleaseConfigHandle(hSvrConfig);
- return (ErrorPop());
- }
- char szQueueFilePath[SYS_MAX_PATH] = "";
- QueGetFilePath(hSpoolQueue, hMessage, szQueueFilePath);
- ///////////////////////////////////////////////////////////////////////////////
- // Build error response mail file
- ///////////////////////////////////////////////////////////////////////////////
- if (QueUtBuildErrorRespose(szMailDomain, hFSpool, szPMAddress, szPMAddress,
- szPMAddress, szQueueFilePath, pszReason, NULL, NULL,
- iMsgLinesExtra, pszLogFile) < 0) {
- ErrorPush();
- QueCleanupMessage(hSpoolQueue, hMessage);
- QueCloseMessage(hSpoolQueue, hMessage);
- SvrReleaseConfigHandle(hSvrConfig);
- return (ErrorPop());
- }
- SvrReleaseConfigHandle(hSvrConfig);
- ///////////////////////////////////////////////////////////////////////////////
- // Send error response mail file
- ///////////////////////////////////////////////////////////////////////////////
- if (QueCommitMessage(hSpoolQueue, hMessage) < 0) {
- ErrorPush();
- QueCleanupMessage(hSpoolQueue, hMessage);
- QueCloseMessage(hSpoolQueue, hMessage);
- return (ErrorPop());
- }
- return (0);
- }
- static int QueUtTXErrorExNotifyRoot(SPLF_HANDLE hFSpool, char const *pszMessFilePath,
- char const *pszReason, char const *pszLogFile)
- {
- bool bCloseHSpool = false;
- if (hFSpool == INVALID_SPLF_HANDLE) {
- if ((hFSpool = USmlCreateHandle(pszMessFilePath)) == INVALID_SPLF_HANDLE)
- return (ErrGetErrorCode());
- bCloseHSpool = true;
- }
- int iNotifyResult = QueUtTXErrorNotifyRoot(hFSpool, pszReason, pszLogFile);
- if (bCloseHSpool)
- USmlCloseHandle(hFSpool);
- return (iNotifyResult);
- }
- static int QueUtBuildErrorRespose(char const *pszSMTPDomain, SPLF_HANDLE hFSpool,
- char const *pszFrom, char const *pszSmtpFrom, char const *pszTo,
- char const *pszResponseFile, char const *pszReason,
- char const *pszText, char const *pszServer, int iLinesExtra,
- char const *pszLogFile)
- {
- char const *pszSpoolFileName = USmlGetSpoolFile(hFSpool);
- char const *pszSmtpMsgID = USmlGetSmtpMessageID(hFSpool);
- ///////////////////////////////////////////////////////////////////////////////
- // Retrieve a new message ID
- ///////////////////////////////////////////////////////////////////////////////
- SYS_UINT64 ullMessageID = 0;
- if (SvrGetMessageID(&ullMessageID) < 0)
- return (ErrGetErrorCode());
- FILE *pRespFile = fopen(pszResponseFile, "wb");
- if (pRespFile == NULL) {
- ErrSetErrorCode(ERR_FILE_CREATE);
- return (ERR_FILE_CREATE);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Try to remap target user address
- ///////////////////////////////////////////////////////////////////////////////
- char szDomain[MAX_ADDR_NAME] = "";
- char szName[MAX_ADDR_NAME] = "";
- char szTo[MAX_ADDR_NAME] = "";
- if (USmlMapAddress(pszTo, szDomain, szName) < 0)
- StrSNCpy(szTo, pszTo);
- else
- SysSNPrintf(szTo, sizeof(szTo) - 1, "%s@%s", szName, szDomain);
- ///////////////////////////////////////////////////////////////////////////////
- // Get the current time string
- ///////////////////////////////////////////////////////////////////////////////
- char szTime[128] = "";
- MscGetTimeStr(szTime, sizeof(szTime) - 1);
- ///////////////////////////////////////////////////////////////////////////////
- // Write info line
- ///////////////////////////////////////////////////////////////////////////////
- USmtpWriteInfoLine(pRespFile, LOCAL_ADDRESS_SQB ":0",
- LOCAL_ADDRESS_SQB ":0", szTime);
- ///////////////////////////////////////////////////////////////////////////////
- // Write domain
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "%srn", pszSMTPDomain);
- ///////////////////////////////////////////////////////////////////////////////
- // Write message ID
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "X" SYS_LLX_FMT "rn", ullMessageID);
- ///////////////////////////////////////////////////////////////////////////////
- // Write MAIL FROM
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "MAIL FROM:<%s>rn", pszSmtpFrom);
- ///////////////////////////////////////////////////////////////////////////////
- // Write RCPT TO
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "RCPT TO:<%s>rn", szTo);
- ///////////////////////////////////////////////////////////////////////////////
- // Write SPOOL_FILE_DATA_START
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "%srn", SPOOL_FILE_DATA_START);
- ///////////////////////////////////////////////////////////////////////////////
- // Write Date ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "Date: %srn", szTime);
- ///////////////////////////////////////////////////////////////////////////////
- // Write X-MessageId ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "X-MessageId: <%s>rn", pszSpoolFileName);
- ///////////////////////////////////////////////////////////////////////////////
- // Write X-SmtpMessageId ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "X-SmtpMessageId: <%s>rn", pszSmtpMsgID);
- ///////////////////////////////////////////////////////////////////////////////
- // Write From ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "From: %s PostMaster <%s>rn", pszSMTPDomain, pszFrom);
- ///////////////////////////////////////////////////////////////////////////////
- // Write To ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "To: %srn", pszTo);
- ///////////////////////////////////////////////////////////////////////////////
- // Write Subject ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "Subject: Error sending message [%s] from [%s]rn",
- pszSpoolFileName, pszSMTPDomain);
- ///////////////////////////////////////////////////////////////////////////////
- // Write X-MailerServer ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "%s: %srn", QUE_MAILER_HDR, APP_NAME_VERSION_STR);
- ///////////////////////////////////////////////////////////////////////////////
- // Write X-SMTP-Mailer-Error ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "%s: Message = [%s] Server = [%s]rn",
- QUE_SMTP_MAILER_ERROR_HDR, pszSpoolFileName, pszSMTPDomain);
- ///////////////////////////////////////////////////////////////////////////////
- // Write blank line ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "rn");
- ///////////////////////////////////////////////////////////////////////////////
- // Write XMail bounce identifier
- ///////////////////////////////////////////////////////////////////////////////
- char const *pszMailFrom = USmlMailFrom(hFSpool);
- char const *pszRcptTo = USmlRcptTo(hFSpool);
- fprintf(pRespFile, "[<00>] XMail bounce: Rcpt=[%s];Error=[%s]rnrnrn",
- pszRcptTo, (pszReason != NULL) ? pszReason : "");
- ///////////////////////////////////////////////////////////////////////////////
- // Write error message ( mail data )
- ///////////////////////////////////////////////////////////////////////////////
- fprintf(pRespFile, "[<01>] Error sending message [%s] from [%s].rnrn"
- "ID: <%s>rn"
- "Mail From: <%s>rn"
- "Rcpt To: <%s>rn",
- pszSpoolFileName, pszSMTPDomain, pszSmtpMsgID, pszMailFrom, pszRcptTo);
- if (pszServer != NULL) {
- SYS_INET_ADDR SvrAddr;
- char szIP[128] = "???.???.???.???";
- char szServer[MAX_HOST_NAME] = "";
- if ((MscGetServerAddress(pszServer, SvrAddr) == 0) &&
- (SysGetHostByAddr(SvrAddr, szServer) == 0)) {
- pszServer = szServer;
- SysInetNToA(SvrAddr, szIP);
- } else
- StrSNCpy(szIP, pszServer);
- fprintf(pRespFile, "Server: <%s> [%s]rn", pszServer, szIP);
- }
- fprintf(pRespFile, "rnrn");
- ///////////////////////////////////////////////////////////////////////////////
- // Emit the delivery failure reason
- ///////////////////////////////////////////////////////////////////////////////
- if (pszReason != NULL)
- fprintf(pRespFile, "[<02>] The reason of the delivery failure was:rnrn"
- "%srnrnrn", pszReason);
- ///////////////////////////////////////////////////////////////////////////////
- // Emit extra text
- ///////////////////////////////////////////////////////////////////////////////
- if (pszText != NULL)
- fprintf(pRespFile, "[<03>] Note:rnrn" "%srnrnrn", pszText);
- ///////////////////////////////////////////////////////////////////////////////
- // Dump the log file associated with the message
- ///////////////////////////////////////////////////////////////////////////////
- char szBuffer[1536] = "";
- if (pszLogFile != NULL) {
- FILE *pLogFile = fopen(pszLogFile, "rb");
- if (pLogFile != NULL) {
- fprintf(pRespFile, "[<04>] Here is listed the message log file:rnrn");
- while (MscGetString(pLogFile, szBuffer, sizeof(szBuffer) - 1) != NULL)
- fprintf(pRespFile, "%srn", szBuffer);
- fprintf(pRespFile, "rnrn");
- fclose(pLogFile);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // This function retrieve the spool file message section and sync the content.
- // This is necessary before reading the file
- ///////////////////////////////////////////////////////////////////////////////
- FileSection FS;
- if (USmlGetMsgFileSection(hFSpool, FS) < 0) {
- ErrorPush();
- fclose(pRespFile);
- SysRemove(pszResponseFile);
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Open spool file
- ///////////////////////////////////////////////////////////////////////////////
- FILE *pMsgFile = fopen(FS.szFilePath, "rb");
- if (pMsgFile == NULL) {
- fclose(pRespFile);
- SysRemove(pszResponseFile);
- ErrSetErrorCode(ERR_FILE_OPEN, FS.szFilePath);
- return (ERR_FILE_OPEN);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Seek at the beginning of the message ( headers section )
- ///////////////////////////////////////////////////////////////////////////////
- fseek(pMsgFile, FS.ulStartOffset, SEEK_SET);
- fprintf(pRespFile, "[<05>] Here is listed the initial part of the message:rnrn");
- bool bInHeaders = true;
- while (MscGetString(pMsgFile, szBuffer, sizeof(szBuffer) - 1) != NULL) {
- char *pszXDomain, *pszTmp;
- ///////////////////////////////////////////////////////////////////////////////
- // Mail error loop deteced
- ///////////////////////////////////////////////////////////////////////////////
- if ((StrNComp(szBuffer, QUE_SMTP_MAILER_ERROR_HDR) == 0) &&
- ((pszXDomain = strrchr(szBuffer, '[')) != NULL) &&
- ((pszTmp = strrchr(++pszXDomain, ']')) != NULL) &&
- (strnicmp(pszXDomain, pszSMTPDomain, pszTmp - pszXDomain) == 0)){
- fclose(pMsgFile);
- fclose(pRespFile);
- SysRemove(pszResponseFile);
- ErrSetErrorCode(ERR_MAIL_ERROR_LOOP);
- return (ERR_MAIL_ERROR_LOOP);
- }
- if (bInHeaders && IsEmptyString(szBuffer))
- bInHeaders = false;
- if (!bInHeaders && (iLinesExtra-- < 0))
- break;
- fprintf(pRespFile, "%srn", szBuffer);
- }
- fclose(pMsgFile);
- fclose(pRespFile);
- return (0);
- }
- int QueUtResendMessage(QUEUE_HANDLE hQueue, QMSG_HANDLE hMessage, SPLF_HANDLE hFSpool)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Try to resend the message
- ///////////////////////////////////////////////////////////////////////////////
- int iResendResult = QueResendMessage(hQueue, hMessage);
- ///////////////////////////////////////////////////////////////////////////////
- // If the message is expired ...
- ///////////////////////////////////////////////////////////////////////////////
- if (iResendResult == ERR_SPOOL_FILE_EXPIRED) {
- ///////////////////////////////////////////////////////////////////////////////
- // Handle notifications and cleanup the message
- ///////////////////////////////////////////////////////////////////////////////
- iResendResult = QueUtNotifyPermErrDelivery(hQueue, hMessage, hFSpool,
- "The maximum number of delivery attempts has been reached",
- NULL, true);
- QueCloseMessage(hQueue, hMessage);
- }
- return (iResendResult);
- }