void TestWriteEmail(int numAttachments) { Email email; InitEmail(email); MojRefCountedPtr<AsyncEmailWriter> writer( new AsyncEmailWriter(email) ); // Create a body part EmailPartList partList; partList.push_back( CreateBodyPart("test1") ); // Create some attachments for(int i = 0; i < numAttachments; i++) { std::stringstream name; name << "attach" << i; EmailPartPtr attachmentPart( new EmailPart(EmailPart::ATTACHMENT) ); attachmentPart->SetLocalFilePath(name.str()); partList.push_back(attachmentPart); } writer->SetPartList(partList); // Set up a fake file "test1" in our mock factory boost::shared_ptr<MockAsyncIOChannelFactory> ioFactory( new MockAsyncIOChannelFactory() ); writer->SetAsyncIOChannelFactory(ioFactory); ioFactory->SetFileData("test1", "Email body"); // Make some fake attachments for(int i = 0; i < numAttachments; i++) { std::stringstream name, data; name << "attach" << i; data << "Attachment data " << i; ioFactory->SetFileData(name.str().c_str(), data.str()); } std::string output; WriteEmail(writer, output); //fprintf(stderr, "Email:\n%s\n", output.c_str()); }
MojErr SmtpSendMailCommand::FinishCalculateEmailSize(const std::exception* exc) { if(exc) { HandleException(*exc, __func__, __FILE__, __LINE__); return MojErrNone; } try { m_bytesLeft = m_counter->GetBytesWritten(); MojLogInfo(m_log, "done calculating email size"); MojLogDebug(m_log, "email size: %d bytes", m_bytesLeft); m_write_state = State_SendMailFrom; // If SIZE extension is present, and server specified a fixed maximum size, // check calculated mail size against server limit. if (m_session.GetSizeMax() && m_session.GetSizeMaxValue() > 0) { if (m_bytesLeft > m_session.GetSizeMaxValue()) { MojLogInfo(m_log, "Outgoing mail is larger than server stated SIZE, so rejecting immediately"); m_error.internalError = "Message larger than server stated limit, not trying to send"; m_error.errorCode = MailError::EMAIL_SIZE_EXCEEDED; m_error.errorText = ""; // No server text, cannot present message m_error.errorOnEmail = true; m_write_state = State_SendErrorRset; } } WriteEmail(); } catch(const std::exception& e) { HandleException(e, __func__, __FILE__, __LINE__); } catch(...) { HandleUnknownException(); } return MojErrNone; }
MojErr SmtpSendMailCommand::HandleResponse(const std::string& line) { try { switch (m_write_state) { case State_SendMailFrom: { MojLogInfo(m_log, "MAIL FROM command response"); if (m_status == Status_Ok) { MojLogInfo(m_log, "MAIL FROM command +OK"); m_toIdx = 0; if(m_toIdx < m_toAddress.size()) { m_write_state = State_SendRcptTo; } else { m_error.errorCode = MailError::BAD_RECIPIENTS; // Error out if for some reason there is no recipient. m_error.errorOnEmail = true; m_error.errorOnAccount = false; m_error.internalError = "Error setting forward address"; m_write_state = State_SendErrorRset; } WriteEmail(); } else { MojLogInfo(m_log, "MAIL FROM command -ERR"); m_error = GetStandardError(); m_error.internalError = "Error setting reverse address"; m_write_state = State_SendErrorRset; WriteEmail(); } break; } case State_SendRcptTo: { MojLogInfo(m_log, "RCPT TO command response"); if (m_status == Status_Ok) { m_toIdx++; if (m_toIdx < m_toAddress.size()) { MojLogInfo(m_log, "RCPT TO command +OK, more to come"); m_write_state = State_SendRcptTo; } else { MojLogInfo(m_log, "RCPT TO command +OK, done"); m_write_state = State_SendData; } WriteEmail(); } else { MojLogInfo(m_log, "RCPT TO command -ERR"); m_error = GetStandardError(); if (m_status == 550) { // general failure means bad recipient m_error.errorCode = MailError::BAD_RECIPIENTS; m_error.errorOnEmail = true; m_error.errorOnAccount = false; } // 452 is technically a non-fatal error that says no more recipients can be // added, on the expectation we'll go and send our mail, and then send a // copy to the next batch of recipients. Instead, we'll treat this as a // permanent error, and not send it to anyone (by sending RSET, and not DATA). // 552 is (as the spec says) an old and occasionally seen typo of 452. if (m_status == 452 || m_status == 552) { m_error.errorCode = MailError::BAD_RECIPIENTS; // too many, actually m_error.errorOnEmail = true; m_error.errorOnAccount = false; } m_error.internalError = "Error setting forward address"; m_write_state = State_SendErrorRset; WriteEmail(); } break; } case State_SendData: { MojLogInfo(m_log, "DATA command response"); if (m_status == Status_Ok) { MojLogInfo(m_log, "DATA command +OK"); m_write_state = State_SendBody; WriteEmail(); } else { MojLogInfo(m_log, "DATA command -ERR"); m_error = GetStandardError(); m_error.internalError = "Error starting mail body"; m_write_state = State_SendErrorRset; WriteEmail(); } break; } case State_SendBody: { MojLogInfo(m_log, "BODY command response"); if (m_status == Status_Ok) { MojLogInfo(m_log, "BODY command +OK"); m_write_state = State_SendRset; WriteEmail(); } else { MojLogInfo(m_log, "BODY command -ERR"); m_error = GetStandardError(); m_error.internalError = "Error completing send"; m_write_state = State_SendErrorRset; WriteEmail(); } break; } case State_SendRset: { MojLogInfo(m_log, "RSET command response"); if (m_status == Status_Ok) { MojLogInfo(m_log, "RSET command +OK"); SendDone(); } else { MojLogInfo(m_log, "RSET command -ERR"); m_error = GetStandardError(); m_error.internalError = "Error resetting"; HandleSmtpError(m_error); } break; } case State_SendErrorRset: { // Handle an error response after clearing an error: if we had one bad e-mail, we want to // be sure we are in a good state before going to the next e-mail. HandleSmtpError(m_error); break; } default: { MojLogInfo(m_log, "Unknown write mail state %d in SmtpSendMailCommand::HandleResponse", m_write_state); HandleFailure("bad HandleResponse state"); break; } } } catch(const std::exception& e) { HandleException(e, __func__, __FILE__, __LINE__); } catch(...) { HandleUnknownException(); } return MojErrNone; }
int main ( int argc, char *argv[] ) { gettextinfo ( &StartupTextInfo ); atexit ( exitcode ); extern bool sound_flag; sound_flag = true; printf ( "\n" "MailChess v %s by Don Cross <*****@*****.**>, 1 March 1996.\n" "http://www.intersrv.com/~dcross\n" "\n", MailChess_Version ); const char * const help = "Use: MAILCHES mailfile\n" "\n" "This program helps two people play chess by e-mail. MailChess reads\n" "and writes a text file which can be sent back and forth by email.\n" "MailChess ignores e-mail headers and other extraneous text.\n" "\n" "If 'mailfile' exists, it is scanned for chess data and MailChess tries\n" "to restore a game in progress so that the next move can be made.\n" "\n" "If 'mailfile' does not exist, MailChess assumes that you want to\n" "start a new game, and that you will play White.\n" "In this case, you will make your first move and MailChess will\n" "create the file 'mailfile'.\n"; // "If the optional parameter 'listfile' is specified, MailChess will\n" // "read the game encoded in 'mailfile' and create a human-readable\n" // "listing of the game in 'listfile', then immediately exit.\n"; if ( argc != 2 && argc != 3 ) { printf ( "%s", help ); return 1; } ChessBoard theBoard; if ( argc == 3 ) { if ( !ReadEmail ( 0, theBoard, argv[1] ) ) { fprintf ( stderr, "No valid chess data in file '%s'\n", argv[1] ); return 1; } FILE *out = fopen ( argv[2], "wt" ); if ( !out ) { fprintf ( stderr, "Cannot open file '%s' for write!\n", argv[2] ); return 1; } ListChessGame ( theBoard, out ); fclose ( out ); printf ( "Game listing written to file '%s'\n", argv[2] ); return 0; } ChessUI_dos_cga theUserInterface; ChessPlayer *player = new HumanChessPlayer ( theUserInterface ); if ( !player ) { fprintf ( stderr, "Error: Not enough memory to run this program!\n" ); return 1; } if ( !ReadEmail ( &theUserInterface, theBoard, argv[1] ) ) { fprintf ( stderr, "The file '%s' does not exist.\n", argv[1] ); fprintf ( stderr, "Do you want to start a new game and create '%s'?\n", argv[1] ); fprintf ( stderr, "(y/n): " ); fflush ( stderr ); char answer [20]; answer[0] = '\0'; fgets ( answer, sizeof(answer), stdin ); if ( answer[0]!='y' && answer[0]!='Y' ) { delete player; return 1; } } MoveList legalMoveList; ChessSide winner = SIDE_NEITHER; if ( theBoard.WhiteToMove() ) { theBoard.GenWhiteMoves ( legalMoveList ); if ( legalMoveList.num == 0 ) { winner = theBoard.WhiteInCheck() ? SIDE_BLACK : SIDE_NEITHER; } } else { theBoard.GenBlackMoves ( legalMoveList ); if ( legalMoveList.num == 0 ) { winner = theBoard.BlackInCheck() ? SIDE_WHITE : SIDE_NEITHER; } } bool gameIsOver = (legalMoveList.num == 0); if ( !gameIsOver ) { // Look for definite draws... if ( theBoard.IsDefiniteDraw(3) ) { winner = SIDE_NEITHER; gameIsOver = true; } } // Now, 'gameIsOver' definitely has the correct value. if ( gameIsOver ) { // Display the ending state of the game and let the // user gloat/sulk/sigh. HelpUser_EndOfGame ( winner ); while ( (bioskey(0) & 0xff) != 0x1b ); sprintf ( ExitMessage, "This game is over. MailChess has not changed '%s'.\n", argv[1] ); } else { // Read a single move from the user. // Ask the user if he/she is sure afterward. // If not, cancel the move and let them do another. // Otherwise, commit to the move, write the updated game // state to the text file, and exit. HelpUser_MakeMove(); for(;;) { Move move; INT32 timeSpent = 0; bool moveWasRead = player->GetMove ( theBoard, move, timeSpent ); if ( moveWasRead ) { theUserInterface.RecordMove ( theBoard, move, timeSpent ); UnmoveInfo unmove; theBoard.MakeMove ( move, unmove ); theUserInterface.DrawBoard ( theBoard ); int promptY = theBoard.WhiteToMove() ? 25 : 24; gotoxy ( 20, promptY ); printf ( "Are you sure this is the move you want to make? (Y/N) " ); unsigned key = 0; while ( toupper(key) != 'Y' && toupper(key) != 'N' ) { key = bioskey(0) & 0xff; } if ( key == 'Y' || key == 'y' ) { WriteEmail ( theBoard, argv[1] ); sprintf ( ExitMessage, "Your move has been added to the file '%s'.\n", argv[1] ); break; } else { gotoxy ( 1, promptY ); printf ( " " ); theBoard.UnmakeMove ( move, unmove ); theUserInterface.DrawBoard ( theBoard ); } } else { sprintf ( ExitMessage, "The file '%s' has not been changed.\n", argv[1] ); break; } } } delete player; return 0; }