On Thu, 4 Sep 2003, [iso-8859-1] S=F6nke Ruempler wrote: > > > Don't you have it ? > > i meant the new binary with the new function ;-)
Here you go. You need to set DEFAULT_DOMAIN in the environment (or registry for Windows). You can export DEFAULT_DOMAIN in the sendmail script if you want. - Davide /* * SendMail by Davide Libenzi ( sendmail replacement for XMail ) * Copyright (C) 1999 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 U= SA * * Davide Libenzi <[EMAIL PROTECTED]> * */ #if defined(WIN32) #include <windows.h> #include <stdio.h> #include <io.h> #include <direct.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "AppDefines.h" #define SYS_SLASH_CHAR '\\' #define SYS_SLASH_STR "\\" #define SYS_MAX_PATH 256 #define SysSNPrintf _snprintf #define Sign(v) (((v) < 0) ? -1: +1) #define Min(a, b) (((a) < (b)) ? (a): (b)) #define Max(a, b) (((a) > (b)) ? (a): (b)) #define Abs(v) (((v) > 0) ? (v): -(v)) int SysFileSync(FILE *pFile) { if (fflush(pFile) || _commit(_fileno(pFile))) return (-1); return (0); } int SysPathExist(char const *pszPathName) { return ((_access(pszPathName, 0) =3D=3D 0) ? 1 : 0); } int SysMakeDir(char const *pszPathName) { return ((_mkdir(pszPathName) =3D=3D 0) ? 1 : 0); } int SysErrNo(void) { return (errno); } char const *SysErrStr(void) { return (strerror(errno)); } unsigned long SysGetProcessId(void) { return ((unsigned long) GetCurrentThreadId()); } int SysMoveFile(char const *pszOldName, char const *pszNewName) { if (!MoveFileEx(pszOldName, pszNewName, MOVEFILE_REPLACE_EXISTING | MOV= EFILE_COPY_ALLOWED)) return (-1); return (0); } int SysGetHostName(char *pszHostName, int iNameSize) { DWORD dwSize =3D (DWORD) iNameSize; GetComputerName(pszHostName, &dwSize); return (0); } void SysMsSleep(int iMsTimeout) { Sleep(iMsTimeout); } char *SysGetEnv(const char *pszVarName) { char szRKeyPath[256] =3D ""; sprintf(szRKeyPath, "SOFTWARE\\%s\\%s", APP_PRODUCER, APP_NAME_STR); HKEY hKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRKeyPath, 0, KEY_QUERY_VALUE, &hKey) =3D=3D ERROR_SUCCESS) { char szKeyValue[2048] =3D ""; DWORD dwSize =3D sizeof(szKeyValue), dwKeyType; if (RegQueryValueEx(hKey, pszVarName, NULL, &dwKeyType, (u_char *) = szKeyValue, &dwSize) =3D=3D ERROR_SUCCESS) { RegCloseKey(hKey); return (strdup(szKeyValue)); } RegCloseKey(hKey); } const char *pszValue =3D getenv(pszVarName); return ((pszValue !=3D NULL) ? strdup(pszValue) : NULL); } #else // #if defined(WIN32) #if defined(__LINUX__) || defined(__SOLARIS__) || defined(__BSD__) #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <dirent.h> #define SYS_SLASH_CHAR '/' #define SYS_SLASH_STR "/" #define SYS_MAX_PATH 256 #define SysSNPrintf snprintf #define stricmp strcasecmp #define strnicmp strncasecmp #define Sign(v) (((v) < 0) ? -1: +1) #define Min(a, b) (((a) < (b)) ? (a): (b)) #define Max(a, b) (((a) > (b)) ? (a): (b)) #define Abs(v) (((v) > 0) ? (v): -(v)) int SysFileSync(FILE *pFile) { if (fflush(pFile) || fsync(fileno(pFile))) return (-1); return (0); } int SysPathExist(char const *pszPathName) { return ((access(pszPathName, 0) =3D=3D 0) ? 1 : 0); } int SysMakeDir(char const *pszPathName) { return ((mkdir(pszPathName, 0700) =3D=3D 0) ? 1 : 0); } int SysErrNo(void) { return (errno); } char const *SysErrStr(void) { return (strerror(errno)); } unsigned long SysGetProcessId(void) { return ((unsigned long) getpid()); } int SysMoveFile(char const *pszOldName, char const *pszNewName) { if (rename(pszOldName, pszNewName) !=3D 0) return (-1); return (0); } int SysGetHostName(char *pszHostName, int iNameSize) { gethostname(pszHostName, iNameSize); return (0); } void SysMsSleep(int iMsTimeout) { usleep(iMsTimeout * 1000); } char *SysGetEnv(const char *pszVarName) { const char *pszValue =3D getenv(pszVarName); return ((pszValue !=3D NULL) ? strdup(pszValue) : NULL); } #else // #if defined(__LINUX__) || defined(__SOLARIS__) #error system type not defined ! #endif // #if defined(__LINUX__) || defined(__SOLARIS__) #endif // #if defined(WIN32) #define ENV_MAIL_ROOT "MAIL_ROOT" #define LOCAL_TEMP_SUBPATH "spool" SYS_SLASH_STR "temp" SYS_SLASH_STR #define LOCAL_SUBPATH "spool" SYS_SLASH_STR "local" SYS_SLASH_STR #define MAIL_DATA_TAG "<<MAIL-DATA>>" #define MAX_ADDR_NAME 256 #define SAPE_OPEN_TENTATIVES 5 #define SAPE_OPEN_DELAY 500 #define ENV_DEFAULT_DOMAIN "DEFAULT_DOMAIN" #define SetEmptyString(s) (s)[0] =3D '\0' #define IsEmptyString(s) (*(s) =3D=3D '\0') #define StrNCpy(t, s, n) do { strncpy(t, s, n); (t)[(n) - 1] =3D '\0= '; } while (0) #define StrSNCpy(t, s) StrNCpy(t, s, sizeof(t)) static FILE *SafeOpenFile(char const *pszFilePath, char const *pszMode) { FILE *pFile; for (int ii =3D 0; ii < SAPE_OPEN_TENTATIVES; ii++) { if ((pFile =3D fopen(pszFilePath, pszMode)) !=3D NULL) return (pFile); SysMsSleep(SAPE_OPEN_DELAY); } return (NULL); } static char const *AddressFromAtPtr(char const *pszAt, char const *pszBase, char *pszAddress) { char const *pszStart =3D pszAt; for (; (pszStart >=3D pszBase) && (strchr("<> \t,\":;'\r\n", *pszStart)= =3D=3D NULL); pszStart--); ++pszStart; char const *pszEnd =3D pszAt + 1; for (; (*pszEnd !=3D '\0') && (strchr("<> \t,\":;'\r\n", *pszEnd) =3D= =3D NULL); pszEnd++); int iAddrLength =3D (int) (pszEnd - pszStart); strncpy(pszAddress, pszStart, iAddrLength); pszAddress[iAddrLength] =3D '\0'; return (pszEnd); } static int EmitRecipients(FILE *pMailFile, char const *pszAddrList) { int iRcptCount =3D 0; char const *pszCurr =3D pszAddrList; for (; (pszCurr !=3D NULL) && (*pszCurr !=3D '\0');) { char const *pszAt =3D strchr(pszCurr, '@'); if (pszAt =3D=3D NULL) break; char szAddress[256] =3D ""; if ((pszCurr =3D AddressFromAtPtr(pszAt, pszAddrList, szAddress)) != =3D NULL) { fprintf(pMailFile, "rcpt to:<%s>\r\n", szAddress); ++iRcptCount; } } return (iRcptCount); } static int GetTime(struct tm & tmLocal, int &iDiffHours, int &iDiffMin= s, time_t tCurr) { if (tCurr =3D=3D 0) time(&tCurr); tmLocal =3D *localtime(&tCurr); struct tm tmTimeLOC =3D tmLocal; struct tm tmTimeGM; tmTimeGM =3D *gmtime(&tCurr); tmTimeLOC.tm_isdst =3D 0; tmTimeGM.tm_isdst =3D 0; time_t tLocal =3D mktime(&tmTimeLOC); time_t tGM =3D mktime(&tmTimeGM); int iSecsDiff =3D (int) difftime(tLocal, tGM); int iSignDiff =3D Sign(iSecsDiff); int iMinutes =3D Abs(iSecsDiff) / 60; iDiffMins =3D iMinutes % 60; iDiffHours =3D iSignDiff * (iMinutes / 60); return (0); } static int GetTimeStr(char *pszTimeStr, int iStringSize, time_t tCurr) { int iDiffHours =3D 0; int iDiffMins =3D 0; struct tm tmTime; GetTime(tmTime, iDiffHours, iDiffMins, tCurr); char szDiffTime[128] =3D ""; if (iDiffHours > 0) sprintf(szDiffTime, " +%02d%02d", iDiffHours, iDiffMins); else sprintf(szDiffTime, " -%02d%02d", -iDiffHours, iDiffMins); strftime(pszTimeStr, iStringSize - strlen(szDiffTime) - 1, "%a, %d %b %= Y %H:%M:%S", &tmTime); strcat(pszTimeStr, szDiffTime); return (0); } static char *CopyAddress(char *pszDest, char const *pszAddr, int iSize) { char *pszDomain; if (strchr(pszAddr, '@') || ((pszDomain =3D SysGetEnv(ENV_DEFAULT_DOMAI= N)) =3D=3D NULL)) StrNCpy(pszDest, pszAddr, iSize); else SysSNPrintf(pszDest, iSize, "[EMAIL PROTECTED]", pszAddr, pszDomain); return (pszDest); } int main(int iArgCount, char *pszArgs[]) { ///////////////////////////////////////////////////////////////////////////= //// // Initialize time ///////////////////////////////////////////////////////////////////////////= //// tzset(); ///////////////////////////////////////////////////////////////////////////= //// // Get the mail root path ///////////////////////////////////////////////////////////////////////////= //// int iVarLength =3D 0; FILE *pInFile =3D stdin; char *pszMailRoot =3D SysGetEnv(ENV_MAIL_ROOT); char szMailRoot[SYS_MAX_PATH] =3D ""; if ((pszMailRoot =3D=3D NULL) || ((iVarLength =3D strlen(pszMailRoot)) = =3D=3D 0)) { if (pszMailRoot !=3D NULL) free(pszMailRoot); fprintf(stderr, "cannot find environment variable: %s\n", ENV_MAIL_= ROOT); return (1); } StrSNCpy(szMailRoot, pszMailRoot); if (szMailRoot[iVarLength - 1] !=3D SYS_SLASH_CHAR) strcat(szMailRoot, SYS_SLASH_STR); free(pszMailRoot); ///////////////////////////////////////////////////////////////////////////= //// // Parse command line ///////////////////////////////////////////////////////////////////////////= //// int ii; bool bExtractRcpts =3D false; bool bXMailFormat =3D false; bool bDotMode =3D true; char szMailFrom[256] =3D ""; char szExtMailFrom[256] =3D ""; char szInputFile[SYS_MAX_PATH] =3D ""; char szRcptFile[SYS_MAX_PATH] =3D ""; for (ii =3D 1; ii < iArgCount; ii++) { if (pszArgs[ii][0] !=3D '-') break; if (strcmp(pszArgs[ii], "--") =3D=3D 0) { ++ii; break; } if (pszArgs[ii][1] !=3D '-') { int iSkipParam =3D 0; bool bEatAll =3D false; for (int jj =3D 1; !bEatAll && (pszArgs[ii][jj] !=3D '\0'); jj+= +) { switch (pszArgs[ii][jj]) { case ('N'): case ('O'): case ('o'): case ('R'): case ('V'): case ('X'): iSkipParam =3D 1; break; case ('i'): bDotMode =3D false; break; case ('t'): bExtractRcpts =3D true; break; case ('f'): { if (pszArgs[ii][jj + 1] !=3D '\0') CopyAddress(szMailFrom, pszArgs[ii] + jj + 1, sizeo= f(szMailFrom) - 1); else if ((ii + 1) < iArgCount) { CopyAddress(szMailFrom, pszArgs[ii + 1], sizeof(szM= ailFrom) - 1); iSkipParam =3D 1; } bEatAll =3D true; } break; case ('F'): { if (pszArgs[ii][jj + 1] !=3D '\0') StrSNCpy(szExtMailFrom, pszArgs[ii] + jj + 1); else if ((ii + 1) < iArgCount) { StrSNCpy(szExtMailFrom, pszArgs[ii + 1]); iSkipParam =3D 1; } char const *pszOpen =3D strchr(szExtMailFrom, '<'); if (pszOpen =3D=3D NULL) CopyAddress(szMailFrom, szExtMailFrom, sizeof(szMai= lFrom) - 1); else { char szTmpMailFrom[256] =3D ""; StrSNCpy(szTmpMailFrom, pszOpen + 1); char *pszClose =3D (char *) strchr(szTmpM= ailFrom, '>'); if (pszClose !=3D NULL) *pszClose =3D '\0'; CopyAddress(szMailFrom, szTmpMailFrom, sizeof(szMai= lFrom) - 1); } bEatAll =3D true; } break; } } if (iSkipParam) ++ii; } else { if (strcmp(pszArgs[ii], "--rcpt-file") =3D=3D 0) { if (++ii < iArgCount) StrSNCpy(szRcptFile, pszArgs[ii]); } else if (strcmp(pszArgs[ii], "--xinput-file") =3D=3D 0) { if (++ii < iArgCount) { StrSNCpy(szInputFile, pszArgs[ii]); bXMailFormat =3D true; } } else if (strcmp(pszArgs[ii], "--input-file") =3D=3D 0) { if (++ii < iArgCount) StrSNCpy(szInputFile, pszArgs[ii]); } } } ///////////////////////////////////////////////////////////////////////////= //// // Check if recipients are supplied ///////////////////////////////////////////////////////////////////////////= //// if (!bExtractRcpts && (ii >=3D iArgCount) && IsEmptyString(szRcptFile)) { fprintf(stderr, "empty recipient list\n"); return (2); } if (!IsEmptyString(szInputFile)) { if ((pInFile =3D fopen(szInputFile, "rb")) =3D=3D NULL) { perror(szInputFile); return (3); } } ///////////////////////////////////////////////////////////////////////////= //// // Save recipients index ///////////////////////////////////////////////////////////////////////////= //// int iRcptIndex =3D ii; int iRcptCount =3D iArgCount - iRcptIndex; ///////////////////////////////////////////////////////////////////////////= //// // Create file name ///////////////////////////////////////////////////////////////////////////= //// char szHostName[256] =3D ""; char szDataFile[SYS_MAX_PATH] =3D ""; char szMailFile[SYS_MAX_PATH] =3D ""; SysGetHostName(szHostName, sizeof(szHostName) - 1); sprintf(szDataFile, "%s%s%lu000.%lu.%s", szMailRoot, LOCAL_TEMP_SUBPATH, (unsigned long) time(NULL), SysGetProcessId(), szHostName); sprintf(szMailFile, "%s.mail", szDataFile); ///////////////////////////////////////////////////////////////////////////= //// // Open raw data file ///////////////////////////////////////////////////////////////////////////= //// FILE *pDataFile =3D fopen(szDataFile, "w+b"); if (pDataFile =3D=3D NULL) { perror(szDataFile); if (pInFile !=3D stdin) fclose(pInFile); return (4); } ///////////////////////////////////////////////////////////////////////////= //// // Open maildrop file ///////////////////////////////////////////////////////////////////////////= //// FILE *pMailFile =3D fopen(szMailFile, "wb"); if (pMailFile =3D=3D NULL) { perror(szMailFile); fclose(pDataFile), remove(szDataFile); if (pInFile !=3D stdin) fclose(pInFile); return (5); } ///////////////////////////////////////////////////////////////////////////= //// // Emit sender ///////////////////////////////////////////////////////////////////////////= //// fprintf(pMailFile, "mail from:<%s>\r\n", szMailFrom); ///////////////////////////////////////////////////////////////////////////= //// // Emit recipients ///////////////////////////////////////////////////////////////////////////= //// for (ii =3D iRcptIndex; ii < iArgCount; ii++) { char szAddr[256] =3D ""; CopyAddress(szAddr, pszArgs[ii], sizeof(szAddr) - 1); fprintf(pMailFile, "rcpt to:<%s>\r\n", szAddr); } ///////////////////////////////////////////////////////////////////////////= //// // Emit message by reading from stdin ///////////////////////////////////////////////////////////////////////////= //// bool bInHeaders =3D true; bool bHasFrom =3D false; bool bHasDate =3D false; bool bRcptSource =3D false; char szBuffer[1536] =3D ""; while (fgets(szBuffer, sizeof(szBuffer) - 1, pInFile) !=3D NULL) { int iLineLength =3D strlen(szBuffer); for (;(iLineLength > 0) && ((szBuffer[iLineLength - 1] =3D=3D '\r') || (szBuffer[iLin= eLength - 1] =3D=3D '\n')); iLineLength--); szBuffer[iLineLength] =3D '\0'; ///////////////////////////////////////////////////////////////////////////= //// // Is it time to stop reading ? ///////////////////////////////////////////////////////////////////////////= //// if (bDotMode && (strcmp(szBuffer, ".") =3D=3D 0)) break; ///////////////////////////////////////////////////////////////////////////= //// // Decode XMail spool file format ///////////////////////////////////////////////////////////////////////////= //// if (bXMailFormat) { if (strcmp(szBuffer, MAIL_DATA_TAG) =3D=3D 0) bXMailFormat =3D false; continue; } ///////////////////////////////////////////////////////////////////////////= //// // Extract mail from ///////////////////////////////////////////////////////////////////////////= //// if (bInHeaders) { if (iLineLength =3D=3D 0) { bInHeaders =3D false; ///////////////////////////////////////////////////////////////////////////= //// // Add mail from ( if not present ) ///////////////////////////////////////////////////////////////////////////= //// if (!bHasFrom) { if (strlen(szExtMailFrom) !=3D 0) fprintf(pDataFile, "From: %s\r\n", szExtMailFrom); else fprintf(pDataFile, "From: <%s>\r\n", szMailFrom); } ///////////////////////////////////////////////////////////////////////////= //// // Add date ( if not present ) ///////////////////////////////////////////////////////////////////////////= //// if (!bHasDate) { char szDate[128] =3D ""; GetTimeStr(szDate, sizeof(szDate) - 1, time(NULL)); fprintf(pDataFile, "Date: %s\r\n", szDate); } } if ((szBuffer[0] =3D=3D ' ') || (szBuffer[0] =3D=3D '\t')) { if (bExtractRcpts && bRcptSource) { int iRcptCurr =3D EmitRecipients(pMailFile,= szBuffer); if (iRcptCurr > 0) iRcptCount +=3D iRcptCurr; } } else { bRcptSource =3D (strnicmp(szBuffer, "To:", 3) =3D=3D 0) || (strnicmp(szBuffer, "Cc:", 3) =3D=3D 0) || (strnicmp(szBuffer, "Bcc:", 4) =3D=3D 0); if (bExtractRcpts && bRcptSource) { int iRcptCurr =3D EmitRecipients(pMailFile,= szBuffer); if (iRcptCurr > 0) iRcptCount +=3D iRcptCurr; } if (!bHasFrom && (strnicmp(szBuffer, "From:", 5) =3D=3D 0)) bHasFrom =3D true; if (!bHasDate && (strnicmp(szBuffer, "Date:", 5) =3D=3D 0)) bHasDate =3D true; } } ///////////////////////////////////////////////////////////////////////////= //// // Emit mail line ///////////////////////////////////////////////////////////////////////////= //// fprintf(pDataFile, "%s\r\n", szBuffer); } ///////////////////////////////////////////////////////////////////////////= //// // Close input file if different from stdin ///////////////////////////////////////////////////////////////////////////= //// if (pInFile !=3D stdin) fclose(pInFile); ///////////////////////////////////////////////////////////////////////////= //// // Dump recipient file ///////////////////////////////////////////////////////////////////////////= //// if (!IsEmptyString(szRcptFile)) { FILE *pRcptFile =3D SafeOpenFile(szRcptFile, "rb"); if (pRcptFile =3D=3D NULL) { perror(szRcptFile); fclose(pDataFile), remove(szDataFile); fclose(pMailFile), remove(szMailFile); return (6); } while (fgets(szBuffer, sizeof(szBuffer) - 1, pRcptFile) !=3D NULL) { int iLineLength =3D strlen(szBuffer); for (;(iLineLength > 0) && ((szBuffer[iLineLength - 1] =3D=3D '\r') || (szBuffer[= iLineLength - 1] =3D=3D '\n')); iLineLength--); szBuffer[iLineLength] =3D '\0'; if (iLineLength >=3D MAX_ADDR_NAME) continue; char *pszAt =3D strchr(szBuffer, '@'); if (pszAt =3D=3D NULL) continue; char szRecipient[MAX_ADDR_NAME] =3D ""; if (AddressFromAtPtr(pszAt, szBuffer, szRecipient) !=3D NULL) { fprintf(pMailFile, "rcpt to:<%s>\r\n", szRecipient); ++iRcptCount; } } fclose(pRcptFile); } ///////////////////////////////////////////////////////////////////////////= //// // Check the number of recipients ///////////////////////////////////////////////////////////////////////////= //// if (iRcptCount =3D=3D 0) { fprintf(stderr, "empty recipient list\n"); fclose(pDataFile), remove(szDataFile); fclose(pMailFile), remove(szMailFile); return (7); } ///////////////////////////////////////////////////////////////////////////= //// // Empty line separator between maildrop header and data ///////////////////////////////////////////////////////////////////////////= //// fprintf(pMailFile, "\r\n"); ///////////////////////////////////////////////////////////////////////////= //// // Append data file ///////////////////////////////////////////////////////////////////////////= //// rewind(pDataFile); unsigned int uReaded; do { if (((uReaded =3D fread(szBuffer, 1, sizeof(szBuffer), pDataFile)) = !=3D 0) && (fwrite(szBuffer, 1, uReaded, pMailFile) !=3D uReaded)) { perror(szMailFile); fclose(pDataFile), remove(szDataFile); fclose(pMailFile), remove(szMailFile); return (8); } } while (uReaded =3D=3D sizeof(szBuffer)); fclose(pDataFile), remove(szDataFile); ///////////////////////////////////////////////////////////////////////////= //// // Sync and close the mail file ///////////////////////////////////////////////////////////////////////////= //// if ((SysFileSync(pMailFile) < 0) || fclose(pMailFile)) { remove(szMailFile); fprintf(stderr, "cannot write file: %s\n", szMailFile); return (9); } ///////////////////////////////////////////////////////////////////////////= //// // Move the mail file ///////////////////////////////////////////////////////////////////////////= //// char szDropFile[SYS_MAX_PATH] =3D ""; sprintf(szDropFile, "%s%s%lu000.%lu.%s", szMailRoot, LOCAL_SUBPATH, (unsigned long) time(NULL), SysGetProcessId(), szHostName); if (SysMoveFile(szMailFile, szDropFile) < 0) { remove(szMailFile); fprintf(stderr, "cannot move file: %s\n", szMailFile); return (10); } return (0); } - To unsubscribe from this list: send the line "unsubscribe xmail" in the body of a message to [EMAIL PROTECTED] For general help: send the line "help" in the body of a message to [EMAIL PROTECTED]