// Lotus Notes Command Line Mail Client NOTES_MAIL by Gottfried Rudorfer // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright 2002 Gottfried Rudorfer. All Rights Reserved. // // MODULE: Notes_mail.cpp // // PURPOSE: Implements main functions required by notes_mail // for windows. // // COMMENTS: // // AUTHOR: Gottfried Rudorfer // http://godefroy.sdf-eu.org/notes_mail/ // //=========================================================================== // // Module: Notes_Mail.CPP // // Syntax: Notes_Mail -help // // Description: // Notes C++ API program that reads AHD environment variables // stores them in environment variables and sends it as notes // mail to the recipients. // Note: // This program is coded to read the mail message from environment variables // defined in the settings file. // //=========================================================================== #ifndef NOTES_MAIL_H #include "Notes_Mail.h" #endif // String Character for the Copyright char COPYRIGHT[] = "\\StringFileInfo\\040904B0\\LegalCopyright"; //--------------------------------------------------------------------------- // // Notes_Mail::CleanDir // Description: Clean Up Mailbox Directory // Input: String with name of Mailbox // Output: Result Status of Function (0=OK) // //--------------------------------------------------------------------------- int Notes_Mail::CleanDir(const string &mailbox) { HANDLE dirH = NULL; WIN32_FIND_DATA fd; DWORD findRet; char strBuf[256]; unsigned int countB = 0; VectorOfStrings Files; int openErr, ProgramStatus = 0, mailtime, result, len; time_t nowt; struct _stat buffer; char inchar; string errorText, inStr; BOOL timeP, toP, subjectP, attachmentsP, bodyP; time( &nowt ); CleanVars(); string BaseDir = MailBox + "\\" + mailbox; string searchD = BaseDir + "\\*"; dirH = FindFirstFile( searchD.c_str(), // pointer to name of file to search for &fd // pointer to returned information ); if (dirH != INVALID_HANDLE_VALUE) { if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) { if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { string Name = fd.cFileName; int len = Name.length(); if ((len > PrefixLength) && (PrefixDelim == Name[-1+PrefixLength])) { Files.push_back(fd.cFileName); countB++; } } } } else { string err="Notes_Mail: Service: Error processing directory "; err += MailBox.c_str(); err += " the error was: "; GetLastErrorText(strBuf, 255); err += strBuf; NotifyError("Cleanup", err, "Error", 0); ProgramStatus+=1; } while( FindNextFile(dirH, &fd) ) { if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) { if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { string Name = fd.cFileName; int len = Name.length(); if ((len > PrefixLength) && (PrefixDelim == Name[-1+PrefixLength])) { Files.push_back(fd.cFileName); countB++; } } } } findRet = GetLastError(); if (ERROR_NO_MORE_FILES != findRet) { string err="Notes_Mail: Service: Error processing directory "; err += MailBox.c_str(); err += " the error was: "; GetLastErrorText(strBuf, 255); err += strBuf; NotifyError("Cleanup", err, "Error", 0); ProgramStatus+=2; } sort(Files.begin(), Files.end(), greater()); for(unsigned int i=0; i < Files.size(); ++i) { int mailFDdel = -1; FILE *mailSTdel = NULL; string Name = Files[i]; string file = BaseDir + "\\" + Name; openErr = 0; result = _stat( file.c_str(), &buffer ); if( result != 0 ) { string error = "Can not get details of \"" + file + "\" ."; NotifyError("Cleanup", error, "Error", 0); ProgramStatus+=4; continue; } else { if (!(buffer.st_mode & _S_IFREG)) { string error = "Error: \"" + file + "\" is not a file."; NotifyError("Cleanup", error, "Error", 2); ProgramStatus+=8; continue; } } if( (mailFDdel = _sopen( file.c_str(), _O_RDONLY, _SH_DENYNO )) == -1 ) openErr = 1; else if( (mailSTdel = _fdopen( mailFDdel, "r" )) == NULL ) openErr = 2; if (openErr) { string err = "The file '"; err += file + "' was not opened. Error: " + strerror( errno ); NotifyError("Cleanup", err, "Error", 0); ProgramStatus+=16; continue; } mailtime = -1; CleanVars(); inStr = "\n"; errorText = ""; timeP = 1; toP = 0; subjectP = 0; attachmentsP = 0; bodyP = 0; while ((EOF != (inchar = getc(mailSTdel))) && (errorText == "")) { inStr+=inchar; if (inchar == '\n') { len = inStr.length(); if (len >= 3) { // search for '\n', '\001', '\n' if ((inStr[len-1] == '\n') && (inStr[len-2] == ESC) && (inStr[len-3] == '\n')) { int numF = -4 + inStr.length(); string field=""; if (numF > 0) field = inStr.substr(1, numF); inStr="\n"; if (timeP) { // process mail creation time int temp = ToNumber(field.c_str()); if (-1 == temp) { string errorText = "The first field in file '"; errorText += file + "' must be a number."; break; } else { mailtime = temp; } timeP = 0; toP = 1; } else if (toP) { MailAddr = field; toP = 0; subjectP = 1; } else if (subjectP) { MailSubject = field; subjectP = 0; attachmentsP = 1; } else if (attachmentsP) { string::size_type end, beg=field.find_first_not_of("\n"); while(beg != string::npos) { end=field.find_first_of("\n",beg); Attachments[field.substr(beg,end-beg)]="ok"; beg=field.find_first_not_of("\n",end); } attachmentsP = 0; bodyP = 1; } else if (bodyP) { MailBody = field; break; } else { errorText += "unknown extra field in file."; } } } } } if (errorText != "") { NotifyError("Cleanup", errorText, "Error", 0); ProgramStatus+=32; } fclose(mailSTdel); _close(mailFDdel); if ((-1 != mailtime) && ((mailtime+max_mail_days*24*60*60)< nowt)) { // delete old file for ( StringStringMap::iterator da = Attachments.begin(); da != Attachments.end(); ++da ) { string Aname = AttachmentBox + '\\' + da->first; if( _unlink( Aname.c_str() ) == -1 ) { string err = "The file '"; err += Aname + "' was not deleted. Error: " + strerror( errno ); NotifyError("CleanUp", err, "Error", 0); ProgramStatus+=64; } else { string err = "The file '"; err += Aname + "' was deleted."; NotifyError("CleanUp", err, "Information", 0); ProgramStatus+=128; } } if( _unlink( file.c_str() ) == -1 ) { string err = "The file '"; err += file + "' was not deleted. Error: " + strerror( errno ); NotifyError("CleanUp", err, "Error", 0); ProgramStatus+=256; } else { string err = "The file '"; err += file + "' was deleted."; NotifyError("CleanUp", err, "Information", 0); } } } return ProgramStatus; } //--------------------------------------------------------------------------- // // Notes_Mail::MyGetenv // Description: Load environment variable into own memory space // Input: Character pointer to name of environment variable // Output: Result string with environment value // //--------------------------------------------------------------------------- string Notes_Mail::MyGetenv(char *envname) { char *strptr; string env_string; if ((strptr=getenv(envname))) { env_string = strptr; } return env_string; } //--------------------------------------------------------------------------- // // Notes_Mail::logevt // Description: Log messeage into the application log of windows // Inputs: Character pointer to name of the message, type of message // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::logevt(const char *str, WORD type) { HANDLE evtHdl; BOOL ret; LPCTSTR arrE[2] ={str, NULL}; evtHdl = RegisterEventSource(NULL, "Notes_Mail"); ret = ReportEvent(evtHdl, type, NOTES_MAIL_CATEGORY, NOTES_MAIL_MESSAGE, NULL, 1, 0, arrE, NULL); if (evtHdl) DeregisterEventSource(evtHdl); ret = CloseEventLog(evtHdl); } //--------------------------------------------------------------------------------- // // Notes_Mail::MkMailDir // Description: Create directory for mailbox of notes_mail if it doesn't exist // Input: String containing the directory name // Output: None // //--------------------------------------------------------------------------------- void Notes_Mail::MkMailDir(string &dir) { struct _stat buffer; int result = 0; result = _stat( dir.c_str(), &buffer ); if( result != 0 ) { if( _mkdir( dir.c_str() ) != 0 ) { string error = "Error: Can't create directory \"" + dir + "\"."; NotifyError("Init", error, "Error", 1); } else { string error = "Directory \"" + dir + "\" was created successfully."; NotifyError("Init", error, "Information", 0); } } else { if (!(buffer.st_mode & _S_IFDIR)) { string error = "Error: \"" + dir + "\" is not a directory."; NotifyError("Init", error, "Error", 2); } } } //--------------------------------------------------------------------------- // // Notes_Mail::CheckMailDirs // Description: Check and create mail directories if they do not exist // Input: None // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::CheckMailDirs() { MkMailDir(MailBox); MkMailDir(ReceivedBox); MkMailDir(InBox); MkMailDir(SentBox); MkMailDir(OutBox); MkMailDir(ErrBox); MkMailDir(AttachmentBox); } //--------------------------------------------------------------------------- // // Notes_Mail::PrintWithoutEsc // Description: Delete internally used escape characters from string and // write the result to a file // Inputs: String containing the text, pointer to the file descriptor // Output: Result Status of Function (0=OK) // //--------------------------------------------------------------------------- int Notes_Mail::PrintWithoutEsc(string Text, FILE *fileS) { // security fix see ftp.cert.org int len = Text.length(); char seq[3] = {'\n', ESC, '\0'}; char *convBuf = new char[1+len]; if (!convBuf) { string err = "Could not allocate "; err += 1+len + " Bytes."; NotifyError("general", err, "Error", 4); } strcpy(convBuf, Text.c_str()); for (char *cp = convBuf; *cp; *cp++) { if (!strncmp(cp, seq, 2)) cp[1] = '_'; len--; } fprintf(fileS, "%s\n\001\n", convBuf); delete convBuf; return 0; } //--------------------------------------------------------------------------- // // Notes_Mail::Queue // Description: Queue a message in the internal mailbox // Input: String containing the directory where to store the message // Output: Result Status of Function (0=OK) // //--------------------------------------------------------------------------- int Notes_Mail::Queue(string &dir) { string FileName = dir + "\\.outlock"; int lockRet, openErr = 0; struct tm *locTime; char strBuf[128]; int noFile = 0, count=0, result = 0; struct _stat buffer; if (-1 == lockFDout) { if( (lockFDout = _sopen( FileName.c_str(), _O_RDWR | _O_APPEND | _O_CREAT, \ _SH_DENYNO, _S_IREAD | _S_IWRITE )) == -1 ) openErr = 1; if (openErr) { string err = "The file '"; err += FileName + "' was not opened. Error: " + strerror( errno ); NotifyError("queuing", err, "Error", 8); } } lockRet = _locking( lockFDout, _LK_UNLCK, 1L ); for (int i=0; i < 60; i++) { lockRet = _locking( lockFDout, _LK_NBLCK, 1L ); if (!lockRet) break; Sleep(1000); } if (0 != lockRet) { string err = "The file '"; err += FileName + "' could not be locked. " + strerror( errno ) ; NotifyError("queuing", err, "Error", 16); } _ftime( &timeStrIn ); locTime = localtime(&timeStrIn.time); while (!noFile) { sprintf(strBuf, "%04d-%02d-%02d--%02d-%02d-%02d-%03d--OUT-%02d-mail.txt", 1900+locTime->tm_year, \ 1+locTime->tm_mon, locTime->tm_mday, locTime->tm_hour, \ locTime->tm_min, locTime->tm_sec, timeStrIn.millitm, ++count); MailFileName = dir + "\\"; MailFileName += strBuf; noFile = _stat( MailFileName.c_str(), &buffer ); } sprintf(strBuf, "%04d-%02d-%02d--%02d-%02d-%02d-%03d--OUT-%02d-", 1900+locTime->tm_year, \ 1+locTime->tm_mon, locTime->tm_mday, locTime->tm_hour, \ locTime->tm_min, locTime->tm_sec, timeStrIn.millitm, count); FilePrefix = strBuf; //GlobalAlloc() openErr=0; if( (mailFDout = _sopen( MailFileName.c_str(), _O_RDWR | _O_APPEND | _O_CREAT, \ _SH_DENYNO, _S_IREAD | _S_IWRITE )) == -1 ) { openErr = 1; } else { if( (mailSTout = _fdopen( mailFDout, "a+" )) == NULL ) openErr = 1; } if (openErr) { string err = "The file '"; err += MailFileName + "' was not opened. Error: " + strerror( errno ); NotifyError("queuing", err, "Error", 32); } lockRet = _locking( mailFDout, _LK_UNLCK, 1L ); for (int j=0; j < 60; j++) { lockRet = _locking( mailFDout, _LK_NBLCK, 1L ); if (!lockRet) break; Sleep(1000); } if (0 != lockRet) { string err = "The file '"; err += MailFileName + "' could not be locked." + strerror( errno ); NotifyError("queuing", err, "Error", 64); } lockRet = _locking( lockFDout, _LK_UNLCK, 1L ); _close(lockFDout); lockFDout = -1; sprintf(strBuf, "%ld", timeStrIn.time); string time = strBuf; PrintWithoutEsc(time, mailSTout); PrintWithoutEsc(MailAddr, mailSTout); PrintWithoutEsc(MailSubject, mailSTout); AttachmentsOut(mailSTout); PrintWithoutEsc(MailBody, mailSTout); AttributesOut(mailSTout); fclose(mailSTout); mailSTout = NULL; lockRet = _locking( mailFDout, _LK_UNLCK, 1L ); _close(mailFDout); mailFDout = -1; return 0; } //--------------------------------------------------------------------------- // // // Notes_Mail::AttachmentsOut // Description: Copy attechments into the attachment mailbox. // Input: Pointer to the opened mail file // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::AttachmentsOut(FILE *MailStream) { BOOL result = 0; string AttachErrs=""; for ( StringStringMap::iterator i = Attachments.begin(); i != Attachments.end(); ++i ) { string PathSource="", NameSource=""; string Source = i->first; SplitPathName(Source, PathSource, NameSource); string NewFile = AttachmentBox + "\\" + FilePrefix + NameSource; result = CopyFile( Source.c_str(), // pointer to name of an existing file NewFile.c_str(), // pointer to filename to copy to FALSE // flag for operation if file exists ); if (!result) { Attachments[i->first] = "error"; string err = "The attachment file '"; err += Source + "' could not be copied to '" + NewFile + "'."; AttachErrs += err + "\n"; NotifyError("sending", err, "Warning", 0); } else { fprintf(MailStream, "%s\n", NewFile.c_str()); } } fprintf(MailStream, "\001\n"); if (AttachErrs != "") { MailBody += "\n\nNotes_Mail: Notes about attachments: " + AttachErrs \ + "\nNotes_Mail: These attachments could not be included in this mail because of errors.\n" \ + "\nPlease forward this message to your administrator."; } } //--------------------------------------------------------------------------- // // Notes_Mail::AttributesOut // Description: Write attributes to mailfile // Input: Pointer to the opened mail file // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::AttributesOut(FILE *MailStream) { BOOL result = 0; string AttachErrs=""; for ( StringStringMap::iterator i = Attributes.begin(); i != Attributes.end(); ++i ) { fprintf(MailStream, "%s=%s\n", (i->first).c_str(), (i->second).c_str()); } fprintf(MailStream, "\001\n"); } //--------------------------------------------------------------------------- // // Notes_Mail::SplitPathName // Description: Split full qualified name into path and name // Input: String with full qualified name // Output: String with path and string with name // //--------------------------------------------------------------------------- void Notes_Mail::SplitPathName(string &FullName, string &Path, string &Name) { int last_bs = 0; for (string::size_type cpos=0; cpos != string::npos;) { cpos = FullName.find_first_of("\\", cpos); if (cpos != string::npos) { last_bs = cpos++; } } if (!last_bs) { Path = ""; Name = FullName; } else { Path = FullName.substr(0, last_bs); Name = FullName.substr(last_bs+1, FullName.length()); } } //--------------------------------------------------------------------------------- // // main // Description: Entrypoint of notes_mail // Input: Integer with number of arguments, array of pointers to the arguments // Output: Return-code of program (0=OK) // //--------------------------------------------------------------------------------- int main( int argc, char *argv[] ) { SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main }, { NULL, NULL } }; int srvRetInt, retCode; Notes_Mail aMail; string missingArg=""; char strBuf[128]; if (("" != aMail.MyGetenv("CONTENT_LENGTH")) || ("" != aMail.MyGetenv("QUERY_STRING") )) NotesWeb(aMail); aMail.ProcessArguments(argc, argv); aMail.CheckMailDirs(); if (aMail.InstallService) { srvRetInt = CmdInstallService(); exit(srvRetInt); } if (aMail.RemoveService) { srvRetInt = CmdRemoveService(); exit(srvRetInt); } if (aMail.RunAsService) { if (!StartServiceCtrlDispatcher(dispatchTable)) { string err = "StartServiceCtrlDispatcher failed."; aMail.NotifyError("main", err, "Error", 0); aMail.ProgramStatus+=8; if (aMail.ProgramStatus) exit(aMail.ProgramStatus); } else { exit(0); // end of service } } if ( (!aMail.Ahd) && (aMail.MailBody == "") && (aMail.MailSubject == "") && (!aMail.useStdin) && (aMail.MailAddr == "") ) { aMail.PrintArguments("No -to,-subject,-body arguments given."); aMail.logevt("No command line arguments given.", EVENTLOG_ERROR_TYPE); aMail.ProgramStatus+=8; exit(aMail.ProgramStatus); } if (!aMail.Ahd) { if ((aMail.MailBody == "") && (!aMail.useStdin)) { missingArg += " -body oder -bodystdin fehlt"; aMail.ProgramStatus+=1; } if (aMail.MailSubject == "") { missingArg += " -subject fehlt"; aMail.ProgramStatus+=2; } if (aMail.MailAddr == "") { missingArg += " -to fehlt"; aMail.ProgramStatus+=4; } if ("" != missingArg) aMail.PrintArguments(missingArg.c_str()); if (aMail.useStdin) { string line; unsigned long cBytes = 0; while(getline(cin,line)) { cBytes += line.length(); if (cBytes > aMail.MaxBodyBytes) { string error = "Error: Max. size of body "; error += aMail.MaxBodyBytes + "reached.\nBody of message will be truncated."; aMail.NotifyError("queuing", error, "Warning", 0); break; } aMail.MailBody += "\n" + line; } } } else { aMail.GetAHD(); } if (aMail.ProgramStatus) exit(aMail.ProgramStatus); retCode = aMail.Queue(aMail.OutBox); if (aMail.DirectMail) { retCode = aMail.SendMail(aMail.MailFileName); aMail.CloseMailDB(); } sprintf(strBuf, "End of Program with RC=%d", aMail.ProgramStatus); aMail.NotifyError("queuing", (string)strBuf, "Information", 0); return (aMail.ProgramStatus); } // END MAIN //--------------------------------------------------------------------------- // // Notes_Mail::ToNumber // Description: Convert string to number // Input: Pointer to the string, length of string // Output: converted number // //--------------------------------------------------------------------------- long Notes_Mail::ToNumber(const char* string, unsigned int length) { long number = -1; BOOL digits = 1; const char *cp = string; unsigned int count = 0; while (*cp) { if (length && count > length) break; if (!isdigit(*cp)) { digits = 0; break; } cp++; count++; } if (digits) number = atol(string); return number; } //--------------------------------------------------------------------------- // // Notes_Mail::ReduceName // Description: Cut off one character from prefix-string if it contains the prefix at the end. // Input: String with full name // Output: String with reduced name // //--------------------------------------------------------------------------- void Notes_Mail::ReduceName(string &fullName, string &reducedName) { int len = fullName.length(); if ((len > PrefixLength) && (PrefixDelim == fullName[-1+PrefixLength])) reducedName = fullName.substr(PrefixLength, len); else reducedName = fullName; } //--------------------------------------------------------------------------- // // Notes_Mail::NotifyError // Description: Send error message to the evntlog of windows // Input: string with name of subcomponent, string with errortext, string with severity, // integer to terminate the program or not // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::NotifyError(string Part, string ErrorText, string Severity, int Exit) { string Intro, RProgName, Path; transform (Part.begin(),Part.end(), Part.begin(), toupper); SplitPathName(ProgName, Path, RProgName); Intro = Part; Intro += " "; Intro += "MailFileName: "; if (MailSubject == "") Intro += "(none)"; else { string PathSource="", NameSource=""; SplitPathName(MailFileName, PathSource, NameSource); Intro += NameSource; } Intro += " Address: "; if (MailAddr == "") Intro += "(none)"; else Intro += MailAddr; Intro += " Subject: "; if (MailSubject == "") Intro += "(none)"; else Intro += MailSubject; Intro += " Attachments: "; string aString=""; for ( StringStringMap::iterator at = Attachments.begin(); at != Attachments.end(); ++at ) { if ("" == aString) aString += at->first; else aString += " " + at->first; } if (aString == "") Intro += "(none)"; else Intro += aString; Intro += " " + Severity +":"; Intro += " " + ErrorText; cerr << Intro << endl; if (Severity == "Information") logevt(Intro.c_str(),EVENTLOG_INFORMATION_TYPE); else if (Severity == "Warning") logevt(Intro.c_str(),EVENTLOG_WARNING_TYPE); else logevt(Intro.c_str(),EVENTLOG_ERROR_TYPE); if (Exit) exit(Exit); } //--------------------------------------------------------------------------- // // Notes_Mail::CloseMailDB // Description: Shut down the mail API to lotus notes // Input: None // Output: None // //--------------------------------------------------------------------------- int Notes_Mail::CloseMailDB() { if (MailDBOpened) { MailDB->Close(); // Terminate the API Session->Term(); delete Session; delete MailDB; Session = NULL; MailDB = NULL; MailDBOpened=SessionInitialized=GetMailDatabase=0; timeStrOpen.time = 0; } return 0; } //--------------------------------------------------------------------------- // // Notes_Mail::OpenMailDB // Description: Open the mail API to lotus notes // Input: None // Output: Status of the initialization (0=OK) // //--------------------------------------------------------------------------- int Notes_Mail::OpenMailDB() { int Status = 0; progressStr = ""; if (!MailDBOpened) { // Begin TRY block. // Throw all errors encountered during command execution. try { LNSTATUS lnstat = LNNOERROR; // Initialize the API. if (!Session) Session = new LNNotesSession; if (!MailDB) MailDB = new LNDatabase; if (!SessionInitialized) { lnstat = Session->Init(); // Use notes.ini progressStr += "Init"; if (lnstat) throw lnstat; SessionInitialized = 1; } if (!GetMailDatabase) { progressStr += " GetMailDatabase"; lnstat = Session->GetMailDatabase( MailDB ); if (lnstat) throw lnstat; GetMailDatabase = 1; } if (!MailDBOpened) { progressStr += " MailDB->Open"; lnstat = MailDB->Open(); if (lnstat) throw lnstat; MailDBOpened = 1; } _ftime( &timeStrOpen ); } // END try block. catch (LNSTATUS lnerror) { char ErrorBuf[LNERROR_MESSAGE_LENGTH]; string ErrorMsg = "Lotus Notes API Error: Progress was: " + progressStr + ": "; LNGetErrorMessage(lnerror, ErrorBuf); ErrorMsg += ErrorBuf; cerr << ErrorMsg << endl; logevt(ErrorMsg.c_str(),EVENTLOG_ERROR_TYPE); Status += 8; } } return Status; } //--------------------------------------------------------------------------- // // Notes_Mail::CleanVars // Description: Clean class global variables // Input: None // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::CleanVars() { MailAddr = ""; MailSubject = ""; MailBody = ""; // delete old attachment entries Attachments.clear(); // delte old Attribute entries Attributes.clear(); } //--------------------------------------------------------------------------- // // Notes_Mail::ReceiveMail // Description: Receive a Lotus Notes Mail and store it into a file // Input: None // Output: Status of the received mail (0=OK) // //--------------------------------------------------------------------------- int Notes_Mail::ReceiveMail() { string FileName = InBox + "\\.inlock"; int lockRet, openErr = 0; struct tm *locTime; char strBuf[128]; int noFile = 0, count=0; struct _stat buffer; int ProgramStatus = 0; string Part = "receiving"; int i; CleanVars(); if (-1 == lockFDin) { if( (lockFDin = _sopen( FileName.c_str(), _O_RDWR | _O_APPEND | _O_CREAT, \ _SH_DENYNO, _S_IREAD | _S_IWRITE )) == -1 ) openErr = 1; if (openErr) { string err = "The file '"; err += FileName + "' was not opened. Error: " + strerror( errno ); NotifyError(Part, err, "Error", 0); ProgramStatus +=8; goto leave; } } lockRet = _locking( lockFDin, _LK_UNLCK, 1L ); // unlock first for (i=0; i < 60; i++) { lockRet = _locking( lockFDin, _LK_NBLCK, 1L ); if (!lockRet) break; Sleep(1000); } if (0 != lockRet) { string err = "The file '"; err += FileName + "' could not be locked. " + strerror( errno ); NotifyError(Part, err, "Error", 0); ProgramStatus += 6; } _ftime( &timeStrIn ); locTime = localtime(&timeStrIn.time); if (!MailDBOpened) ProgramStatus += OpenMailDB(); if (ProgramStatus) { goto leave; } try { LNViewFolder View; MailDB->GetViewFolder("($POP3)", &View); //InBox View.Open(); //Find the entry count in the view. LNINT Entries = View.GetEntryCount(); //sprintf(strBuf, "Reading Inbox, found %d entries\n", Entries); //logevt(strBuf,EVENTLOG_INFORMATION_TYPE); //Let's loop through all the documents in this view. for (unsigned int i = 0; i < Entries; i++) { LNDocument Doc; LNINT IndentLevels = 0; ProgramStatus = 0; CleanVars(); //Navigate through view using subscript operator in LNViewFolder. LNVFEntry Entry = View[i]; NOTEID Docid = Entry.GetNoteID(); //Get the LNDocument associated with the view entry. Entry.GetDocument(&Doc); //Open the document. Doc.Open(); LNMailMessage LMail( Doc ); LNDatetime Sent; if (( LMail.GetDateSent (&Sent) == LNWARN_NOT_FOUND ) || !GetSumRes()) { // no date when sent. Doc.Close(); continue; } int mon, day, year, hour, min, sec; struct tm when, *nowPtr; time_t mailt, nowt, oldt; mon = Sent.GetMonth(); day = Sent.GetDay(); year = Sent.GetYear(); hour = Sent.GetHour(); min = Sent.GetMinute(); sec = Sent.GetSecond(); when.tm_sec = sec; /* seconds after the minute - [0,59] */ when.tm_min = min; /* minutes after the hour - [0,59] */ when.tm_hour = hour; /* hours since midnight - [0,23] */ when.tm_mday = day; /* day of the month - [1,31] */ when.tm_mon = mon - 1; /* months since January - [0,11] */ when.tm_year = year - 1900; /* years since 1900 */ when.tm_wday = 0; /* days since Sunday - [0,6] */ when.tm_yday = 0; /* days since January 1 - [0,365] */ time( &nowt ); /* Get time as long integer. */ nowPtr = localtime( &nowt ); /* Convert to local time. */ when.tm_isdst = nowPtr->tm_isdst; /* daylight savings time flag */ oldt = mktime(&when); // (mailtime+max_mail_days*24*60*60)< nowt) in Cleanup if (((oldt+max_mail_days*24*60*60)< nowt) || !GetSumRes()) { // skip mails in inbox older than one month Doc.Close(); continue; } mailt = mktime(&when); sprintf(strBuf, "%04d-%02d-%02d--%02d-%02d-%02d-%07d--IN-mail.txt", year, \ mon, day, hour, min, sec, Docid); MailFileName = ReceivedBox + "\\"; MailFileName += strBuf; noFile = _stat( MailFileName.c_str(), &buffer ); if ((!noFile) || !GetSumRes()) { Doc.Close(); continue; // mail is already received. } string TmpFileName = InBox; TmpFileName += "\\"; TmpFileName += strBuf; string ErrFileName = ErrBox; ErrFileName += "\\"; ErrFileName += strBuf; sprintf(strBuf, "%04d-%02d-%02d--%02d-%02d-%02d-%07d--IN-", year, \ mon, day, hour, min, sec, Docid); FilePrefix = strBuf; // openErr=0; if ((-1 == mailFDin) || (NULL == mailSTin)) { if( (mailFDin = _sopen( TmpFileName.c_str(), _O_RDWR | _O_APPEND | _O_CREAT, \ _SH_DENYNO, _S_IREAD | _S_IWRITE )) == -1 ) { openErr = 1; } else { if( (mailSTin = _fdopen( mailFDin, "a+" )) == NULL ) openErr = 1; } } if (openErr) { string err = "The file '"; err += TmpFileName + "' was not opened. Error: " + strerror( errno ); NotifyError(Part, err, "Error", 0); ProgramStatus += 2; } lockRet = _locking( mailFDin, _LK_UNLCK, 1L ); for (int j=0; j < 60; j++) { lockRet = _locking( mailFDin, _LK_NBLCK, 1L ); if (!lockRet) break; Sleep(1000); } if (0 != lockRet) { string err = "The file '"; err += TmpFileName + "' could not be locked. " + strerror( errno ); NotifyError(Part, err, "Error", 0); ProgramStatus += 4; } if (Doc.HasAttachments()) { LNAttachmentArray attachments; Doc.GetAttachments( &attachments ); LNINT Entries = attachments.GetCount(); //Let's loop through all the attachments in this document. for (unsigned int i = 0; i < Entries; i++) { LNAttachment Att = attachments[i]; string Attname = Att.GetAttachmentName(); for (string::size_type cpos=0; cpos != string::npos;) { cpos = Attname.find_first_of(NotOkChars, cpos); if (cpos != string::npos) { Attname[cpos] = '_'; } } string NewPath = AttachmentBox; NewPath += '\\' + FilePrefix + Attname; if (!Att.Detach( NewPath.c_str() )) Attachments[FilePrefix + Attname] = "ok"; else { string err = "IN: Mail: "; err += FilePrefix + " Attachment '"; err += Attname + "' was not detached."; NotifyError(Part, err, "Error", 0); ProgramStatus += 8; } } } lockRet = _locking( lockFDin, _LK_UNLCK, 1L ); _close(lockFDin); lockFDin = -1; LNText Item; LNString Subject="", From="", Body=""; if (Doc.HasItem("Subject")) { Doc.GetItem("Subject", &Item); Subject = Item[0]; } else { string err = "IN: Mail: "; err += FilePrefix + " No Subject item!"; NotifyError(Part, err, "Warning", 0); } if (Doc.HasItem("From")) { Doc.GetItem("From", &Item); From = Item[0]; } else { string err = "IN: Mail: "; err += FilePrefix + " No From item!"; NotifyError(Part, err, "Error", 0); ProgramStatus += 32; } if (Doc.HasItem("Body")) { LNRichText RTBody; LMail.GetBody(&RTBody); RTBody.GetText( &Body ); } else { string err = "IN: Mail: "; err += FilePrefix + " No Body item!"; NotifyError(Part, err, "Warning", 0); } MailAddr = From; MailSubject = Subject; sprintf(strBuf, "%ld", mailt); string time = strBuf; PrintWithoutEsc(time, mailSTin); PrintWithoutEsc((string)From, mailSTin); PrintWithoutEsc((string)Subject, mailSTin); for ( StringStringMap::iterator ai = Attachments.begin(); ai != Attachments.end(); ++ai ) { string Name = ai->first; fprintf(mailSTin, "%s\n", Name.c_str()); } fprintf(mailSTin, "\001\n"); PrintWithoutEsc((string)Body, mailSTin); fclose(mailSTin); mailSTin = NULL; lockRet = _locking( mailFDin, _LK_UNLCK, 1L ); _close(mailFDin); mailFDin = -1; Doc.Close(); if (!ProgramStatus) { int result = rename(TmpFileName.c_str(), MailFileName.c_str()); if( result != 0 ) { string err = "Could not rename "; err += TmpFileName + " to " + MailFileName; NotifyError(Part, err, "Error", 0); } else { sprintf(strBuf, "Lotus Notes API: Received mail."); NotifyError(Part, (string)strBuf, "Information", 0); } } else { int result = rename(TmpFileName.c_str(), MailFileName.c_str()); // int result = rename(TmpFileName.c_str(), ErrFileName.c_str()); if( result != 0 ) { string err = "Could not rename "; // err += TmpFileName + " to " + ErrFileName; err += TmpFileName + " to " + MailFileName; NotifyError(Part, err, "Error", 0); } } } //Close the view. View.Close(); } //Error handler. If an error occurred, get the text of the error //message and display it. catch (LNSTATUS lnerror) { char ErrorBuf[LNERROR_MESSAGE_LENGTH]; string ErrorMsg = "Lotus Notes API Error: "; LNGetErrorMessage(lnerror, ErrorBuf); ErrorMsg += ErrorBuf; NotifyError(Part, ErrorMsg, "Error", 0); ProgramStatus += 8; goto leave; } leave: if (-1 != lockFDin) { lockRet = _locking( lockFDin, _LK_UNLCK, 1L ); _close(lockFDin); lockFDin = -1; } if (mailSTin) { fclose(mailSTin); mailSTin = NULL; } if (-1 != mailFDin) { lockRet = _locking( mailFDin, _LK_UNLCK, 1L ); _close(mailFDin); mailFDin = -1; } return ProgramStatus; } //--------------------------------------------------------------------------- // // Notes_Mail::SendMail // Description: Send a Lotus Notes Mail from a file // Input: String with mail file to send // Output: Status of the sent mail (0=OK) // //--------------------------------------------------------------------------- int Notes_Mail::SendMail(string MyMailFileName) { string FileName = OutBox + "\\.outlock"; int lockRet, openErr = 0; struct tm *locTime; char strBuf[128]; int noFile = 0, count=0, result = 0; char inchar; ProgramStatus=0; string PathSource="", NameSource="", Dest=""; time_t mailtime = 0; string errorText=""; BOOL timeP = 0, toP = 0, subjectP = 0, attachmentsP = 0, bodyP = 0, attributeP = 0; string timeS="", toS="", subjectS="", attachmentS="", bodyS="", inStr="\n"; int len, i, j; CleanVars(); if (!GetSumRes()) goto leave; if (MyMailFileName == "") { ProgramStatus+=1; goto leave; } MailFileName = MyMailFileName; if (-1 == lockFDout) { if( (lockFDout = _sopen( FileName.c_str(), _O_RDWR | _O_APPEND | _O_CREAT, \ _SH_DENYNO, _S_IREAD | _S_IWRITE )) == -1 ) openErr = 1; if (openErr) { string err = "The file '"; err += FileName + "' was not opened. Error: " + strerror( errno ); NotifyError("sending", err, "Error", 0); goto leave; } } lockRet = _locking( lockFDout, _LK_UNLCK, 1L ); for (i=0; i < 60; i++) { lockRet = _locking( lockFDout, _LK_NBLCK, 1L ); if (!lockRet) break; Sleep(1000); } if (0 != lockRet) { string err = "The file '"; err += FileName + "' could not be locked. " + strerror( errno ); NotifyError("sending", err, "Error", 0); ProgramStatus+=4; goto leave; } openErr=0; if ((-1 == mailFDout) || (!mailSTout)) { if( (mailFDout = _sopen( MyMailFileName.c_str(), _O_RDONLY, _SH_DENYNO )) == -1 ) { openErr = 1; } else { if( (mailSTout = _fdopen( mailFDout, "r" )) == NULL ) openErr = 2; } if (openErr) { string err = "The file '"; err += MyMailFileName + "' was not opened. Error: " + strerror( errno ); NotifyError("sending", err, "Error", 0); ProgramStatus+=8; goto leave; } } lockRet = _locking( mailFDout, _LK_UNLCK, 1L ); for (j=0; j < 60; j++) { lockRet = _locking( mailFDout, _LK_NBLCK, 1L ); if (!lockRet) break; Sleep(1000); } if (0 != lockRet) { string err = "The file '"; err += MyMailFileName + "' could not be locked. " + strerror( errno ); NotifyError("sending", err, "Error", 0); ProgramStatus+=16; goto leave; } _ftime( &timeStrIn ); locTime = localtime(&timeStrIn.time); mailtime = timeStrIn.time; timeP = 1; // first field is time while ((EOF != (inchar = getc(mailSTout))) && (errorText == "")) { inStr+=inchar; switch( inchar ) { case '\n': len = inStr.length(); if (len >= 3) { // search for '\n', '\001', '\n' if ((inStr[len-1] == '\n') && (inStr[len-2] == ESC) && (inStr[len-3] == '\n')) { int numF = -4 + inStr.length(); string field=""; if (numF > 0) field = inStr.substr(1, numF); inStr="\n"; if (timeP) { // process mail creation time int temp = ToNumber(field.c_str()); if (-1 == temp) { errorText += "first field must be time in digits"; } else { mailtime = temp; } timeP = 0; toP = 1; } else if (toP) { MailAddr = field; toP = 0; subjectP = 1; } else if (subjectP) { MailSubject = field; subjectP = 0; attachmentsP = 1; } else if (attachmentsP) { string::size_type end, beg=field.find_first_not_of("\n"); while(beg != string::npos) { end=field.find_first_of("\n",beg); Attachments[field.substr(beg,end-beg)]="ok"; beg=field.find_first_not_of("\n",end); } attachmentsP = 0; bodyP = 1; } else if (bodyP) { MailBody = field; bodyP = 0; attributeP = 1; } else if (attributeP) { string::size_type end, beg=field.find_first_not_of("\n"); while(beg != string::npos) { end=field.find_first_of("\n",beg); string this_attribute = field.substr(beg,end-beg); beg=field.find_first_not_of("\n",end); string Name, Value; string::size_type eq_end, eq_beg=this_attribute.find_first_not_of("="); eq_end=this_attribute.find_first_of("=",eq_beg); if (eq_end != string::npos) { Name =this_attribute.substr(eq_beg, eq_end-eq_beg); Value=this_attribute.substr(eq_end+1, this_attribute.length()-eq_end-1); } else { errorText += "Attribute requires a = sign"; } if ((Value.length() == 0) || (Value == "")) { errorText += "Parse-Error: -attribute name=value , value must be defined"; } else { Attributes[Name]=Value; } } attributeP = 0; } else { errorText += "unknown extra field in file."; } } } break; default: break; } } fclose(mailSTout); mailSTout = NULL; lockRet = _locking( mailFDout, _LK_UNLCK, 1L ); _close(mailFDout); mailFDout = -1; if ((mailtime + 60 * 10) < timeStrIn.time) { int diff = (timeStrIn.time - mailtime)/60; sprintf(strBuf, "\n\nNotes_Mail: Warning: This mail is %d min (%d hours, %d days) old!\n", diff, diff/60, diff/60/24); MailBody += strBuf; } if (MailAddr == "") errorText+=" Missing Mail-To address."; if (errorText != "") { int result; string PathSource="", NameSource=""; SplitPathName(MyMailFileName, PathSource, NameSource); string Dest=ErrBox + "\\" + NameSource; result = rename(MyMailFileName.c_str(), Dest.c_str()); if( result != 0 ) { string err = "Could not rename "; err += MyMailFileName + " to " + Dest; NotifyError("sending", err, "Error", 0); } NotifyError("sending", errorText, "Error", 0); ProgramStatus+=1; goto leave; } if (!MailDBOpened) ProgramStatus += OpenMailDB(); if (ProgramStatus) { goto leave; } try { LNDocument Document; LNSTATUS lnstat = LNNOERROR; LNRichText RT; progressStr = ""; progressStr += " CreateDocument"; lnstat = MailDB->CreateDocument(&Document); if (lnstat) throw lnstat; else { LNText Txt; LNAttachment aLNAttachment; progressStr += " Document.Open"; Document.Open(); lnstat = Document.CreateItem("Body", &RT); if (lnstat) throw lnstat; progressStr += " RichtText.Append"; lnstat = RT.Append(MailBody.c_str()); if (lnstat) throw lnstat; progressStr += " Txt.SetValue.Subject"; lnstat = Txt.SetValue(MailSubject.c_str()); if (lnstat) throw lnstat; progressStr += " Document.CreateItem"; lnstat = Document.CreateItem("Subject", Txt); if (lnstat) throw lnstat; for ( StringStringMap::iterator at = Attachments.begin(); at != Attachments.end(); ++at ) { string reducedName; string fullName = at->first; string PathSource="", NameSource=""; SplitPathName(fullName, PathSource, NameSource); ReduceName(NameSource, reducedName); lnstat = Document.CreateAttachment(fullName.c_str(), reducedName.c_str(), TRUE, &aLNAttachment); if (lnstat) throw lnstat; } for ( StringStringMap::iterator attr = Attributes.begin(); attr != Attributes.end(); ++attr ) { progressStr += " Document.AddAttributes"; string Name = attr->first; string Value= attr->second; LNDatetime Dt; LNDatetimes TimeFld; LNText TextFld; bool timedone = 0, timeproc = 0; time_t nowtime = 0, dateval = mailtime; if (Value.substr(0, 5) == "date:") { timeproc = 1; if (Value.substr(0, 8) == "date:now") { char buf[128], sign, *num; char *dateStr = buf; int digits; strcpy(dateStr, (Value.substr(8,Value.length()-8)).c_str()); if (Value.length() > 128) goto TEXTPROC; sign = *dateStr; dateStr++; num = dateStr; digits = 1; while (*dateStr) { if (!isdigit(*dateStr)) { digits = 0; cout << "Found non-digit: \"" << dateStr << "\"" << endl; break; } dateStr++; } if (digits) { nowtime = atol(num); } else { goto TEXTPROC; } if (sign == '-') { dateval -= nowtime * 60; } else if (sign == '+') { dateval += nowtime * 60; } else { cout << "no sign found " << sign << endl; goto TEXTPROC; } struct tm *nowPtr; nowPtr = localtime(&dateval); Dt.SetDate(1+nowPtr->tm_mon, nowPtr->tm_mday, 1900+nowPtr->tm_year); if (lnstat) throw lnstat; Dt.SetTime(nowPtr->tm_hour, nowPtr->tm_min, nowPtr->tm_sec); if (lnstat) throw lnstat; timedone = 1; } else { // expecting normal time format // Date/Time in the format: DD.MM.YYYY HH:MM:SS char buf[128]; char *dateStr = buf; char delim = '.'; string temp = ""; int count = 0; BOOL dayP = 1, monP = 0, yearP = 0, hourP = 0, minuteP = 0, secondP = 0; int day, mon, year, hour=0, minute=0, second=0, num; if (Value.length() > 128) goto TEXTPROC; strcpy(dateStr, (Value.substr(5,Value.length()-5)).c_str()); while(*dateStr) { if (isdigit(*dateStr)) { temp += *dateStr; count++; } else if (*dateStr == delim) { if (count) { num = atol(temp.c_str()); if (dayP) { day = num; monP = 1; dayP = 0; } else if (monP) { mon = num; yearP = 1; monP = 0; delim = ' '; } else if (yearP) { year = num; hourP = 1; yearP = 0; delim = ':'; } else if (hourP) { hour = num; minuteP = 1; hourP = 0; } else if (minuteP) { minute = num; secondP = 1; minuteP = 0; } } count = 0; temp = ""; } else { goto TEXTPROC; } dateStr++; } if (secondP && count) { num = atol(temp.c_str()); second = num; secondP = 0; } lnstat = Dt.SetDate(mon, day, year); if (lnstat) throw lnstat; lnstat = Dt.SetTime(hour, minute, second); if (lnstat) throw lnstat; } // Set the current datetime into the TimeField LNItem. lnstat = TimeFld.SetValue(Dt); if (lnstat) throw lnstat; Document.CreateItem(Name.c_str(), TimeFld, LNITEMFLAGS_AUTO_SUMMARY); if (lnstat) throw lnstat; timedone = 1; } TEXTPROC: if (!timedone) { TextFld.SetValue(Value.c_str()); lnstat = Document.CreateItem(Name.c_str(), TextFld, LNITEMFLAGS_AUTO_SUMMARY); if (lnstat) throw lnstat; } } } LNMailMessage LMail( Document ); LNDatetime Sent; progressStr += " SetDeliveryPriority"; lnstat = LMail.SetDeliveryPriority ( LNDELIVERYPRIORITY_HIGH ); if (lnstat) throw lnstat; progressStr += " SendTo"; lnstat = Document.SendTo(MailAddr.c_str()); if (lnstat) throw lnstat; progressStr += " Save"; lnstat = Document.Save(); if (lnstat) throw lnstat; if ( LMail.GetDateSent (&Sent) == LNWARN_NOT_FOUND ) sprintf(strBuf, "Message not sent yet. (i.e. a draft)."); else { sprintf(strBuf, "Lotus Notes API: Sent at %04d-%02d-%02d %02d:%02d:%02d Domino server time.", \ Sent.GetYear(), Sent.GetMonth(), Sent.GetDay(), Sent.GetHour(), \ Sent.GetMinute(), Sent.GetSecond() ); NotifyError("sending", (string)strBuf, "Information", 0); } Document.Close(); } // END try block. catch (LNSTATUS lnerror) { char ErrorBuf[LNERROR_MESSAGE_LENGTH]; string ErrorMsg = "Lotus Notes API Error: Progress was: " + progressStr + ": "; LNGetErrorMessage(lnerror, ErrorBuf); ErrorMsg += ErrorBuf; NotifyError("sending", ErrorMsg, "Error", 0); ProgramStatus += 8; goto leave; } catch (const char *pErrorMessage) { string ErrorMsg = "Lotus Notes API Error: Progress was: " + progressStr + ": "; ErrorMsg += pErrorMessage; NotifyError("sending", ErrorMsg, "Error", 0); ProgramStatus += 16; goto leave; } SplitPathName(MyMailFileName, PathSource, NameSource); Dest=SentBox + "\\" + NameSource; if (!ProgramStatus) { result = rename(MyMailFileName.c_str(), Dest.c_str()); if( result != 0 ) { string err = "Could not rename "; err += MyMailFileName + " to " + Dest; NotifyError("sending", err, "Error", 0); } } progressStr = ""; leave: if (-1 != lockFDout) { lockRet = _locking( lockFDout, _LK_UNLCK, 1L ); _close(lockFDout); lockFDout = -1; } if (mailSTout) { fclose(mailSTout); mailSTout = NULL; } if (-1 != mailFDout) { lockRet = _locking( mailFDout, _LK_UNLCK, 1L ); _close(mailFDout); mailFDout = -1; } return ProgramStatus; } //--------------------------------------------------------------------------- // // Notes_Mail::Notes_Mail // Description: Void Constructor // Input: None // Output: None // //--------------------------------------------------------------------------- Notes_Mail::Notes_Mail() { Session = NULL; MailDB = NULL; Ahd = 0; ProgramStatus = 0; MailAddr=""; MailSubject=""; MailBody=""; ProgName=""; useStdin = 0; InstallService = 0; RemoveService = 0; DirectMail = 0; MaxBodyBytes = 4194304; MailFileName=""; RunAsService=0; LNSetThrowAllErrors (TRUE); progressStr=""; MailDBOpened=SessionInitialized=GetMailDatabase=0; _ftime( &timeStrIn ); timeStrOpen.time = 0; GetInstPath(); ChkSum(); MailBox = InstPath + "\\..\\MailBox"; ReceivedBox = MailBox + "\\Received"; InBox = MailBox + "\\In"; SentBox = MailBox + "\\Sent"; OutBox = MailBox + "\\Out"; ErrBox = MailBox + "\\Error"; AttachmentBox = MailBox + "\\Attachment"; lockFDin = mailFDin = -1; mailSTin = NULL; lockFDout = mailFDout = -1; mailSTout = NULL; LGL(); } //--------------------------------------------------------------------------- // // Notes_Mail::ChkSum // Description: Calculate the check sum for Notes_Mail // Input: None // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::ChkSum() { unsigned long sum = 0; for (int i=0; i < sizeof(Notes320_gif); i++) sum += Notes320_gif[i] * (i + 1); if (sum != chksum) checkSumOk = 0; else checkSumOk = 1; } //--------------------------------------------------------------------------- // // Notes_Mail::GetSumRes // Description: Return the result of the check sum check. // Input: None // Output: Integer with result (1 = OK) // //--------------------------------------------------------------------------- int Notes_Mail::GetSumRes() { return checkSumOk; } //--------------------------------------------------------------------------- // // Notes_Mail::GetAHD // Description: Get AHD Variables and store them in internal Variables // Input: None // Output: Integer with result (1 = OK) // //--------------------------------------------------------------------------- void Notes_Mail::GetAHD() { MailAddr=MyGetenv("NX_NTF_EMAIL_ADDRESS"); MailSubject=MyGetenv("NX_NTF_SUMMARY"); MailBody=MyGetenv("NX_NTF_MESSAGE"); if (MailAddr=="") { NotifyError("sending", "Variable NX_NTF_EMAIL_ADDRESS not defined or empty", "Error", 0); ProgramStatus+=1; } if (MailSubject=="") { NotifyError("sending", "Variable NX_NTF_SUMMARY not defined or empty", "Error", 0); ProgramStatus+=2; } if (MailBody=="") { NotifyError("sending", "Variable NX_NTF_MESSAGE not defined or empty", "Error", 0); ProgramStatus+=4; } } // StringModuleVersion // Description: // This routine will extract the version string from the // string version resource in the RC file for the current module. // Note that you must add version.lib to your project to // link to the Win32 versioning API calls. The actual call // VerQueryValue() uses a value of 040904B0 for the language // and character set. This value is equivalent to English // language text encoded using Unicode. // // Input: None // Output: String containing the version string StringModuleVersion() { char file_name[ MAX_PATH ]; GetModuleFileName( ::GetModuleHandle( NULL ), file_name, MAX_PATH ); DWORD dwDummyHandle; DWORD len = GetFileVersionInfoSize( file_name, &dwDummyHandle ); vector buf( len ); ::GetFileVersionInfo( file_name, 0, len, buf.begin() ); char *version; unsigned int ver_length; ::VerQueryValue( buf.begin(), "\\StringFileInfo\\040904B0\\FileVersion", (void **) &version, &ver_length ); return string( version, ver_length ); } // Notes_Mail::LGL // Description: // This routine will extract the LegalCopyright string from the // string version resource in the RC file for the current module. // Note that you must add version.lib to your project to // link to the Win32 versioning API calls. The actual call // VerQueryValue() uses a value of 040904B0 for the language // and character set. This value is equivalent to English // language text encoded using Unicode. // Input: None // Output: None // void Notes_Mail::LGL() { char file_name[ MAX_PATH ]; char author[] = "Ksxxjvmih$Vyhsvjiv"; char *ap=author; GetModuleFileName( ::GetModuleHandle( NULL ), file_name, MAX_PATH ); DWORD dwDummyHandle; DWORD len = GetFileVersionInfoSize( file_name, &dwDummyHandle ); vector buf( len ); ::GetFileVersionInfo( file_name, 0, len, buf.begin() ); char *version; unsigned int ver_length; ::VerQueryValue( buf.begin(), COPYRIGHT, (void **) &version, &ver_length ); if ((ver_length < strlen(author)) || (strlen(author) < 10)) checkSumOk = 0; else { while(*ap) { (*ap) = (*ap) - 4; ap++; } version+=ver_length-strlen(author)-1; if (strcmp(version, author)) checkSumOk = 0; } } //--------------------------------------------------------------------------- // // Notes_Mail::PrintArguments // Description: Print usage text for notes_mail // Input: Pointer to an optional error message // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::PrintArguments(const char *error) { string RProgName, Path; SplitPathName(ProgName, Path, RProgName); cerr << "\n" << error << "\n" << "Use-Case 1: " << RProgName << " -help" << "\n" << "Use-Case 2: " << RProgName << " -ahd | -to \"recipient\" -subject \"subject\" " << "\n\t\t-body \"body\" | -bodystdin | [-attachments \"file1\" \"file2\" ... ] " << "\n\t\t-attribute \"name=some value\" | -direct" << "\n" << "Use-Case 3: " << RProgName << " -installservice | -removeservice" << "\n" << "Use-Case 4: " << RProgName << " -service" << "\n" << "Use-Case 5: " << RProgName << " (no arguments) CGI program together with a web server" << "\n" << "\n(c) 2002 by Gottfried Rudorfer" << "\n" << "version " << StringModuleVersion()<< endl; } // END PrintArguments() //--------------------------------------------------------------------------- // // Notes_Mail::Help // Description: Print help text for Notes_Mail // Input: None // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::Help() { PrintArguments("Help:"); cerr << "\n" << "-help : display additional information (this output)" << "\n" << "-to \"recipient\" : send mail to one or more recipients use comma (,) as delimiter" << "\n" << "-subject \"subject\" : specify subject for mail message" << "\n" << "-body \"body\" : use specified text as body text" << "\n" << "-bodystdin : read body text from stdin i.e. type message.txt | notes_mail -bodystdin " << "\n" << "-attachments \"file1\" ... : specify one or more attachments to add to mail" << "\n" << "-attribute \"name=a text value\" : set text attribute in mail message" << "\n" << "-attribute \"name=date:dd:mm:yyyy hh:mm:ss\" : set date attribute" << "\n" << "-attribute \"name=date:now+number\" : current date + offset in minutes" << "\n" << "-attribute \"name=date:now-number\" : current date - offset in minutes" << "\n" << "-ahd : read mail message from AHD" << "\n" << "-direct : send mail directly to the domino server without queuing" << "\n" << "-installservice : install the lotus notes command Windows service" << "\n" << "-removeservice : remove the lotus notes command Windows service" << "\n" << "-service : internally used by notes_mail when started from Windows" << "\n" << "(no argument): CGI add the path to notes_mail as virtual path of your web server" << endl; exit(1); } //--------------------------------------------------------------------------- // // Notes_Mail::GetInstPath // Description: Get absolute installation path name // Input: None // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::GetInstPath() { TCHAR szPath[512]; string::size_type last_bs = 0; if ( GetModuleFileName( NULL, szPath, 512 ) != 0 ) { ProgName=szPath; } for (string::size_type cpos=0; cpos != string::npos;) { cpos = ProgName.find_first_of("\\", cpos); if (cpos != string::npos) { last_bs = cpos++; } } if (!last_bs) { cerr << "Path missing on progam name.\n" << "You have to specify the full path to this program" << endl; exit(128); } if (ProgName.length() > MAX_PATH - 100) { // exit if path gets too long cerr << "Maximum path length be exeeded.\nInstall somewhere in the root i.e.: C:\\Program Files ." << endl; exit(99); } InstPath = ProgName.substr(0, last_bs); } //--------------------------------------------------------------------------- // // Notes_Mail::ProcessArguments // Description: Process arguments given on invocation // Input: integer holding the number of arguments, array of pointers to the arguments // Output: None // //--------------------------------------------------------------------------- void Notes_Mail::ProcessArguments ( int argc, char *argv[]) { ProgName = *argv++; for (*argv; ((*argv)||(!GetSumRes())); *argv++) { string Argument = *argv; if (Argument == "-to") { if (*++argv) MailAddr = *argv; else { PrintArguments("Parse-Error: -to requires a value"); exit(1024); } } else if (Argument == "-subject") { if (*++argv) MailSubject = *argv; else { PrintArguments("Parse-Error: -subject requires a value"); exit(1024); } } else if (Argument == "-body") { if (*++argv) MailBody = *argv; else { PrintArguments("Parse-Error: -body requires a value"); exit(1024); } } else if (Argument == "-bodystdin") { useStdin = 1; } else if (Argument == "-installservice") { InstallService = 1; } else if (Argument == "-removeservice") { RemoveService = 1; } else if (Argument == "-ahd") { Ahd = 1; } else if (Argument == "-service") { RunAsService = 1; } else if (Argument == "-direct") { DirectMail = 1; } else if (Argument == "-help") { Help(); } else if (Argument == "-attribute") { if (*++argv) { string attrib = *argv; string name, value; string::size_type end, beg=attrib.find_first_not_of("="); end=attrib.find_first_of("=",beg); if (end != string::npos) { name =attrib.substr(beg, end-beg); value=attrib.substr(end+1, attrib.length()-end-1); } else { PrintArguments("Parse-Error: -attribute requires a = sign"); exit(1024); } if ((value.length() == 0) || (value == "")) { PrintArguments("Parse-Error: -attribute name=value , value must be defined"); exit(1024); } Attributes[name] = value; } else { PrintArguments("Parse-Error: -attributes requires a value"); exit(1024); } } else if (Argument == "-attachments") { if (!*argv) break; while(*argv++) { if (!*argv) break; string File=*argv; if (File.length() > 0) { if (File[0] == '-') { *argv--; break; } Attachments[File]="ok"; } else { // } } } else { string Msg = "Parse-Error: Invalid argument \"" + Argument + "\""; PrintArguments(Msg.c_str()); exit(99); } if ((!*argv) && GetSumRes()) break; } }