void TCPConnection::AsyncRead(const AnsiString &delimitor) { UpdateAutoLogoutTimer(); std::function<void (const boost::system::error_code&, size_t)> AsyncReadCompletedFunction = std::bind(&TCPConnection::AsyncReadCompleted, shared_from_this(), std::placeholders::_1, std::placeholders::_2); if (is_ssl_) { if (delimitor.GetLength() == 0) boost::asio::async_read(ssl_socket_, receive_buffer_, boost::asio::transfer_at_least(1), AsyncReadCompletedFunction); else boost::asio::async_read_until(ssl_socket_, receive_buffer_, delimitor, AsyncReadCompletedFunction); } else { if (delimitor.GetLength() == 0) { boost::asio::async_read(socket_, receive_buffer_, boost::asio::transfer_at_least(1), AsyncReadCompletedFunction); } else { boost::asio::async_read_until(socket_, receive_buffer_, delimitor, AsyncReadCompletedFunction); } } }
void StringParser::Base64Decode(const String &sInput, String &sOutput) { if (sInput.GetLength() == 0) { sOutput.Empty(); return; } AnsiString sInputStr = sInput; MimeCodeBase64 DeCoder; DeCoder.AddLineBreak(false); DeCoder.SetInput(sInputStr, sInputStr.GetLength(), false); AnsiString output; DeCoder.GetOutput(output); int length = output.GetLength(); // Since we're going to store the result in // a normal StdString, we can't return null // characters. for (int i = 0; i < length; i++) { if (output[i] == 0) output[i] = '\t'; } sOutput = output; }
String MessageUtilities::GetSendersIP(boost::shared_ptr<Message> pMessage) { const String fileName = PersistentMessage::GetFileName(pMessage); AnsiString sHeader = PersistentMessage::LoadHeader(fileName); MimeHeader oHeader; oHeader.Load(sHeader, sHeader.GetLength(), true); // Locate the first Received header MimeField *pReceivedHeader = oHeader.GetField("Received"); if (pReceivedHeader == 0) return "127.0.0.1"; // Now we should try to find the IP in the received header. String sReceivedValue = pReceivedHeader->GetValue(); int iAddressStart = sReceivedValue.Find(_T("[")) +1; int iAddressEnd = sReceivedValue.Find(_T("]"), iAddressStart); int iAddressLen = iAddressEnd - iAddressStart; if (iAddressLen <= 0) return "127.0.0.1"; String sIPAddress = sReceivedValue.Mid(iAddressStart, iAddressLen); if (!StringParser::IsValidIPAddress(sIPAddress)) return "127.0.0.1"; return sIPAddress; }
AnsiString Canonicalization::GetDKIMWithoutSignature_(AnsiString value) { // locate the b= tag int pos = value.Find("b="); if (pos < 0) return ""; // Locate end of b-tag. We need to use the ;-separator // here. The signature may contain spaces and newlines // if it's folded (and canon-mode is set to simple). int end = value.Find(";", pos); int actualEnd = 0; if (end > pos) actualEnd = end; else actualEnd = value.GetLength(); int len = actualEnd - pos; AnsiString before = value.Mid(0, pos+2); AnsiString after = value.Mid(actualEnd); AnsiString result = before + after; return result; }
bool File::Write(const AnsiString &sWrite) { AnsiString sTmp = sWrite; DWORD dwWritten = 0; return Write((const unsigned char*) sTmp.GetBuffer(), sTmp.GetLength(), dwWritten); }
String MimeHeader::GetUnicodeFieldValue(const AnsiString &pszFieldName, const AnsiString &sRawFieldValue) { AnsiString sWideStr; sWideStr = ""; if (sRawFieldValue.IsEmpty()) { if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeHeader::GetUnicodeFieldValue - sRawFieldValue.IsEmpty"); return sWideStr; } // De-code the value to plain text. AnsiString sRetVal; FieldCodeBase* pCoder = MimeEnvironment::CreateFieldCoder(pszFieldName); pCoder->SetInput(sRawFieldValue, sRawFieldValue.GetLength(), false); pCoder->GetOutput(sRetVal); AnsiString sCharset = pCoder->GetCharset(); delete pCoder; sWideStr = Charset::ToWideChar(sRetVal, sCharset); if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeHeader::GetUnicodeFieldValue - sWideStr: " + sWideStr); return sWideStr; }
void SMTPClientConnection::ParseData(const AnsiString &Request) //---------------------------------------------------------------------------() // DESCRIPTION: // Parses a server SMTP cmmand. //---------------------------------------------------------------------------() { multi_line_response_buffer_ += Request; if (multi_line_response_buffer_.GetLength() > 10000) { UpdateAllRecipientsWithError_(500, "Unexpected response from server (too long).", false); return; } if (Request.GetLength() > 3 && (Request.GetAt(3) == '-')) { // Multi-line response. Wait for full buffer. multi_line_response_buffer_ += "\r\n"; EnqueueRead(); return; } bool postReceive = InternalParseData(multi_line_response_buffer_); multi_line_response_buffer_.Empty(); if (postReceive) EnqueueRead(); }
/* Returns one of the following Neutral - Undecided Pass - Signature verified properly. TempFail - Failed to verify signature, potentially a local problem. PermFail - Failed to verify signature. */ DKIM::Result DKIM::Verify(const String &fileName) { if (FileUtilities::FileSize(fileName) > MaxFileSize) return Neutral; AnsiString messageHeader = PersistentMessage::LoadHeader(fileName); MimeHeader mimeHeader; mimeHeader.Load(messageHeader.GetBuffer(), messageHeader.GetLength(), false); vector<pair<AnsiString, AnsiString> > signatureFields = GetSignatureFields(mimeHeader); if (signatureFields.size() == 0) { // No signatures in message. return Neutral; } Result result = Neutral; typedef pair<AnsiString, AnsiString> HeaderField; boost_foreach (HeaderField signatureField, signatureFields) { result = _VerifySignature(fileName, messageHeader, signatureField); if (result == Pass) return Pass; };
// helper. EVP_PKEY* _GetPublicKey(const AnsiString &keyData) { // base64 decode the public key. AnsiString publicKeyData = Base64::Decode(keyData, keyData.GetLength()); const unsigned char * publicKeyDataPointer = (const unsigned char*) publicKeyData.GetBuffer(); EVP_PKEY *publicKey = d2i_PUBKEY(NULL, &publicKeyDataPointer, publicKeyData.GetLength()); return publicKey; }
AnsiString SimpleCanonicalization::CanonicalizeBody(AnsiString value) { // remove all empty lines. while (value.EndsWith("\r\n")) value = value.Mid(0, value.GetLength()-2); value += "\r\n"; return value; }
void Base64Tester::Test() { String s; AnsiString input = "Test"; s = Base64::Encode(input.GetBuffer(), input.GetLength()); if (s.Compare(_T("VGVzdA==")) != 0) throw; input = "Test test test test test test test!!!!"; s = Base64::Encode(input, input.GetLength()); if (s.Compare(_T("VGVzdCB0ZXN0IHRlc3QgdGVzdCB0ZXN0IHRlc3QgdGVzdCEhISE=")) != 0) throw; input = "hMailServer is a free e-mail server for Microsoft Windows. It's used by Internet service providers, companies, governments, schools and enthusiasts in all parts of the world. It supports the common e-mail protocols (IMAP, SMTP and POP3) and can easily be integrated with many existing web mail systems. It has flexible score-based spam protection and can attach to your virus scanner to scan all incoming and outgoing email."; s = Base64::Encode(input, input.GetLength()); if (s.Compare(_T("aE1haWxTZXJ2ZXIgaXMgYSBmcmVlIGUtbWFpbCBzZXJ2ZXIgZm9yIE1pY3Jvc29mdCBXaW5kb3dzLiBJdCdzIHVzZWQgYnkgSW50ZXJuZXQgc2VydmljZSBwcm92aWRlcnMsIGNvbXBhbmllcywgZ292ZXJubWVudHMsIHNjaG9vbHMgYW5kIGVudGh1c2lhc3RzIGluIGFsbCBwYXJ0cyBvZiB0aGUgd29ybGQuIEl0IHN1cHBvcnRzIHRoZSBjb21tb24gZS1tYWlsIHByb3RvY29scyAoSU1BUCwgU01UUCBhbmQgUE9QMykgYW5kIGNhbiBlYXNpbHkgYmUgaW50ZWdyYXRlZCB3aXRoIG1hbnkgZXhpc3Rpbmcgd2ViIG1haWwgc3lzdGVtcy4gSXQgaGFzIGZsZXhpYmxlIHNjb3JlLWJhc2VkIHNwYW0gcHJvdGVjdGlvbiBhbmQgY2FuIGF0dGFjaCB0byB5b3VyIHZpcnVzIHNjYW5uZXIgdG8gc2NhbiBhbGwgaW5jb21pbmcgYW5kIG91dGdvaW5nIGVtYWlsLg==")) != 0) throw; input = "VGVzdA=="; s = Base64::Decode(input, input.GetLength()); if (s.Compare(_T("Test")) != 0) throw; input = "VGVzdCB0ZXN0IHRlc3QgdGVzdCB0ZXN0IHRlc3QgdGVzdCEhISE="; s = Base64::Decode(input, input.GetLength()); if (s.Compare(_T("Test test test test test test test!!!!")) != 0) throw; input = "aE1haWxTZXJ2ZXIgaXMgYSBmcmVlIGUtbWFpbCBzZXJ2ZXIgZm9yIE1pY3Jvc29mdCBXaW5kb3dzLiBJdCdzIHVzZWQgYnkgSW50ZXJuZXQgc2VydmljZSBwcm92aWRlcnMsIGNvbXBhbmllcywgZ292ZXJubWVudHMsIHNjaG9vbHMgYW5kIGVudGh1c2lhc3RzIGluIGFsbCBwYXJ0cyBvZiB0aGUgd29ybGQuIEl0IHN1cHBvcnRzIHRoZSBjb21tb24gZS1tYWlsIHByb3RvY29scyAoSU1BUCwgU01UUCBhbmQgUE9QMykgYW5kIGNhbiBlYXNpbHkgYmUgaW50ZWdyYXRlZCB3aXRoIG1hbnkgZXhpc3Rpbmcgd2ViIG1haWwgc3lzdGVtcy4gSXQgaGFzIGZsZXhpYmxlIHNjb3JlLWJhc2VkIHNwYW0gcHJvdGVjdGlvbiBhbmQgY2FuIGF0dGFjaCB0byB5b3VyIHZpcnVzIHNjYW5uZXIgdG8gc2NhbiBhbGwgaW5jb21pbmcgYW5kIG91dGdvaW5nIGVtYWlsLg=="; s = Base64::Decode(input, input.GetLength()); if (s.Compare(_T("hMailServer is a free e-mail server for Microsoft Windows. It's used by Internet service providers, companies, governments, schools and enthusiasts in all parts of the world. It supports the common e-mail protocols (IMAP, SMTP and POP3) and can easily be integrated with many existing web mail systems. It has flexible score-based spam protection and can attach to your virus scanner to scan all incoming and outgoing email.")) != 0) throw; }
AnsiString HashCreator::GenerateHash(const AnsiString &inputString, const AnsiString &salt) { AnsiString saltString = salt; if (saltString.GetLength() == 0 && _hashType == SHA256) { AnsiString randomString = PasswordGenerator::Generate(); saltString = _GetHash(randomString, hex); saltString = saltString.Mid(0, SALT_LENGTH); } AnsiString value = saltString + _GetHash(saltString + inputString, hex); return value; }
boost::shared_ptr<MimeHeader> MessageUtilities::_GetMessageHeader(boost::shared_ptr<Message> pMessage) { String fileName = PersistentMessage::GetFileName(pMessage); AnsiString sHeader = PersistentMessage::LoadHeader(fileName); boost::shared_ptr<MimeHeader> pHeader = boost::shared_ptr<MimeHeader>(new MimeHeader()); boost::shared_ptr<MimeHeader> pMimeHeader = boost::shared_ptr<MimeHeader>(new MimeHeader); pHeader->Load(sHeader, sHeader.GetLength(), true); return pHeader; }
AnsiString MIMEUnicodeEncoder::EncodeValue(const AnsiString &sCharSet, const String &sUnicodeValue) { AnsiString sMBText = Charset::ToMultiByte(sUnicodeValue, sCharSet); FieldCodeBase pCoder; pCoder.SetCharset(sCharSet); pCoder.SetInput(sMBText, sMBText.GetLength(), true); AnsiString encodedValue; pCoder.GetOutput(encodedValue); return encodedValue; }
AnsiString DKIM::_SignHash(AnsiString &privateKey, AnsiString &canonicalizedHeader, HashCreator::HashType hashType) { // Sign the hash. BIO *private_bio = BIO_new_mem_buf(privateKey.GetBuffer(), -1); if(private_bio == NULL) { ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5309, "DKIM::_SignHash", "Unable to read the private key file into memory."); return ""; } EVP_PKEY *private_key = PEM_read_bio_PrivateKey(private_bio, NULL, NULL, NULL); if(private_key == NULL) { BIO_free(private_bio); ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5310, "DKIM::_SignHash", "Unable to parse the private key file."); return ""; } BIO_free(private_bio); unsigned int siglen = EVP_PKEY_size(private_key); unsigned char *sig = (unsigned char*) OPENSSL_malloc(siglen); EVP_MD_CTX headerSigningContext; EVP_SignInit( &headerSigningContext, hashType == HashCreator::SHA256 ? EVP_sha256() : EVP_sha1()); String result; if (EVP_SignUpdate( &headerSigningContext, canonicalizedHeader.GetBuffer(), canonicalizedHeader.GetLength() ) == 1) { if (EVP_SignFinal( &headerSigningContext, sig, &siglen, private_key) == 1) { result = Base64::Encode((const char*) sig, siglen); } else { ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5311, "DKIM::_SignHash", "Call to EVP_SignFinal failed."); } } else { ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5312, "DKIM::_SignHash", "Call to EVP_SignUpdate failed."); } EVP_PKEY_free(private_key); EVP_MD_CTX_cleanup( &headerSigningContext ); OPENSSL_free(sig); return result; }
void POP3ClientConnection::PrependHeaders_() //---------------------------------------------------------------------------() // DESCRIPTION: // Adds headers to the beginning of the message. //---------------------------------------------------------------------------() { // Add a header with the name of the external account, so that // we can check where we downloaded it from later on. String sHeader; sHeader.Format(_T("X-hMailServer-ExternalAccount: %s\r\n"), account_->GetName().c_str()); AnsiString sAnsiHeader = sHeader; transmission_buffer_->Append((BYTE*) sAnsiHeader.GetBuffer(), sAnsiHeader.GetLength()); }
// store the body part to un-encoded string buffer void MimeBody::Store(AnsiString &output, bool bIncludeHeader) const { // store header fields int nSize = 0; if (bIncludeHeader) MimeHeader::Store(output); // Copy the data to the output buffer. output.append(m_pbText); if (m_listBodies.empty()) return; // store child body parts string strBoundary = GetBoundary(); if (strBoundary.empty()) return; // boundary not be set int nBoundSize = (int)strBoundary.size() + 6; // Bill48105 - These iOutputSize are temp fix for [ ambiguous error int iOutputSizeLess2 = output.size() - 2; int iOutputSizeLess1 = output.size() - 1; for (BodyList::const_iterator it=m_listBodies.begin(); it!=m_listBodies.end(); it++) { // If the initial body ends with \r\n, remove them. We add new ones below. if (m_listBodies.begin() == it && output.size() >= 2 && output[iOutputSizeLess2] == '\r' && output[iOutputSizeLess1] == '\n') { output = output.Mid(0, output.GetLength() - 2); } AnsiString boundaryLine = Formatter::Format(_T("\r\n--{0}\r\n"), String(strBoundary)); output.append(boundaryLine); shared_ptr<MimeBody> pBP = *it; ASSERT(pBP != NULL); pBP->Store(output); } AnsiString endBoundaryLine = Formatter::Format(_T("\r\n--{0}--\r\n"), String(strBoundary)); output.append(endBoundaryLine); }
void TCPConnection::EnqueueWrite(const AnsiString &sData) { AnsiString sTemp = sData; char *pBuf = sTemp.GetBuffer(); std::shared_ptr<ByteBuffer> pBuffer = std::shared_ptr<ByteBuffer>(new ByteBuffer()); pBuffer->Add((BYTE*) pBuf, sData.GetLength()); #ifdef _DEBUG String sDebugOutput; sDebugOutput.Format(_T("SENT: %s"), String(sTemp).c_str()); OutputDebugString(sDebugOutput); #endif EnqueueWrite(pBuffer); }
std::vector<AnsiString> StringParser::SplitString(const AnsiString &sInput, const AnsiString &sSeperators) { std::vector<AnsiString> vecResult; int iBeginning = 0; int iEnd = sInput.Find(sSeperators); if (iEnd == -1) { // The separator was not found in the string. // We should put the entire string in the result. if (!sInput.IsEmpty()) vecResult.push_back(sInput); } int iSeperatorLen = sSeperators.GetLength(); while (iEnd >= 0) { int iSubStrLength = iEnd - iBeginning; String sSubString; sSubString = sInput.Mid(iBeginning, iSubStrLength); vecResult.push_back(sSubString); // Skip to the position where the next substring // can start iBeginning = iEnd + iSeperatorLen; iEnd = sInput.Find(sSeperators, iBeginning); } if (iBeginning > 0) { String sSubString = sInput.Mid(iBeginning); if (!sSubString.IsEmpty()) vecResult.push_back(sSubString); } return vecResult; }
AnsiString MimeHeader::GetUTF8FieldValue(const AnsiString &pszFieldName, const AnsiString &sRawFieldValue) { AnsiString sAnsiStr; if (sRawFieldValue.IsEmpty()) return sAnsiStr; // De-code the value to plain text. AnsiString sRetVal; FieldCodeBase* pCoder = MimeEnvironment::CreateFieldCoder(pszFieldName); pCoder->SetInput(sRawFieldValue, sRawFieldValue.GetLength(), false); pCoder->GetOutput(sRetVal); delete pCoder; sAnsiStr = Charset::ToUTF8(sRetVal); return sAnsiStr; }
AnsiString RelaxedCanonicalization::CanonicalizeHeaderValue(AnsiString value) { /* Unfold all header field continuation lines as described in [RFC2822]; in particular, lines with terminators embedded in continued header field values (that is, CRLF sequences followed by WSP) MUST be interpreted without the CRLF. Implementations MUST NOT remove the CRLF at the end of the header field value. */ value.Replace("\r\n ", " "); value.Replace("\r\n\t", " "); /* Convert all sequences of one or more WSP characters to a single SP character. WSP characters here include those before and after a line folding boundary. */ value.Replace("\t ", " "); value.Replace(" \t", " "); while (value.Find(" ") >= 0) value.Replace(" ", " "); /* Delete all WSP characters at the end of each unfolded header field value. */ while (value.EndsWith(" ") || value.EndsWith("\t")) value = value.Mid(0, value.GetLength() -1); /* Delete any WSP characters remaining before and after the colon separating the header field name from the header field value. The colon separator MUST be retained. */ value.Trim(); return value; }
void StringParser::Base64Encode(const String &sInput, String &sOutput) { if (sInput.GetLength() == 0) { sOutput.Empty(); return; } AnsiString sInputStr = sInput; MimeCodeBase64 Coder; Coder.SetInput(sInputStr, sInputStr.GetLength(), true); Coder.AddLineBreak(false); AnsiString output; Coder.GetOutput(output); sOutput = output; }
// initialize the content with text int MimeBody::SetUnicodeText(const String &sText) { // Retrieve the current charset for this field. std::string strCharset = GetCharset(); if (strCharset.size() == 0) { return SetRawText(sText); } AnsiString sMBText = Charset::ToMultiByte(sText, strCharset); AnsiString sEncodedValue; MimeCodeBase* pCoder = MimeEnvironment::CreateCoder("quoted-printable"); pCoder->SetInput(sMBText, sMBText.GetLength(), true); pCoder->GetOutput(sEncodedValue); delete pCoder; SetTransferEncoding("quoted-printable"); return SetRawText(sEncodedValue); }
void POP3ClientConnection::ParseMessageHeaders_() { assert(current_message_); String fileName = PersistentMessage::GetFileName(current_message_); AnsiString sHeader = PersistentMessage::LoadHeader(fileName); std::shared_ptr<MimeHeader> pHeader = std::shared_ptr<MimeHeader>(new MimeHeader); pHeader->Load(sHeader, sHeader.GetLength()); { // Parse out the sender of the message. String sFrom = pHeader->GetRawFieldValue("From"); if (!sFrom.IsEmpty()) { AddresslistParser oAddressParser; String sFullName, sUser, sDomain; oAddressParser.ExtractParts(sFrom, sFullName, sUser, sDomain); if (!sUser.IsEmpty() && !sDomain.IsEmpty()) { sFrom = sUser + "@" + sDomain; if (StringParser::IsValidEmailAddress(sFrom)) current_message_->SetFromAddress(sFrom); } } } // bool bPreprocessRecipientList = true; CreateRecipentList_(pHeader); // Remove non-existent accounts. RemoveInvalidRecipients_(); RetrieveReceivedDate_(pHeader); }
void MimeHeader::SetUnicodeFieldValue(const AnsiString &sFieldName, const String & sFieldValue, const AnsiString & sCharset) { // Retrieve the current charset for this field. MimeField* pfd = GetField(sFieldName); if (sFieldValue.GetLength() == 0) { SetRawFieldValue(sFieldName, "", ""); return; } AnsiString sCharsetToUse = sCharset; // If client hasn't specified character set, assume it's the existing one. if (pfd && pfd->GetCharset() && sCharsetToUse.IsEmpty()) sCharsetToUse = pfd->GetCharset(); // If there's no existing charset, assume it's the same as for the email. if (sCharsetToUse.IsEmpty()) sCharsetToUse = GetCharset(); if (sCharsetToUse.IsEmpty()) sCharsetToUse = "utf-8"; AnsiString sMBText = Charset::ToMultiByte(sFieldValue, sCharsetToUse); // Encode the value FieldCodeBase* pCoder = MimeEnvironment::CreateFieldCoder(sFieldName); pCoder->SetInput(sMBText, sMBText.GetLength(), true); pCoder->SetCharset(sCharsetToUse.c_str()); AnsiString sEncodedValue; pCoder->GetOutput(sEncodedValue); delete pCoder; SetRawFieldValue(sFieldName, sEncodedValue, sCharsetToUse); }
String MimeBody::GetUnicodeText() { String sWideStr; AnsiString sRawText = GetRawText(); if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sRawText: " + sRawText) else if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sRawText"); if (sRawText.IsEmpty()) { if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sRawText.IsEmpty!"); return sRawText; } std::string strCharset = GetCharset(); if (strCharset.size() == 0) { if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText strCharset.size=0!"); return sRawText; } // De-code the value to plain text. AnsiString sRetVal; MimeCodeBase* pCoder = MimeEnvironment::CreateCoder(GetTransferEncoding()); pCoder->SetInput(sRawText, sRawText.GetLength(), false); pCoder->GetOutput(sRetVal); delete pCoder; sWideStr = Charset::ToWideChar(sRetVal, strCharset); if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sWideStr: " + sWideStr) else if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sWideStr"); return sWideStr; }
String IMAPCommandSEARCH::GetHeaderValue_(const String &fileName, std::shared_ptr<Message> pMessage, const String &sHeaderField) { if (message_data_) { message_data_ = std::shared_ptr<MessageData>(new MessageData()); message_data_->LoadFromMessage(fileName, pMessage); return message_data_->GetFieldValue(sHeaderField); } if (!mime_header_) { // Load header AnsiString sHeader = PersistentMessage::LoadHeader(fileName); mime_header_ = std::shared_ptr<MimeHeader>(new MimeHeader); mime_header_->Load(sHeader, sHeader.GetLength(), true); } AnsiString sHeaderFieldStr = sHeaderField; return mime_header_->GetUnicodeFieldValue(sHeaderFieldStr); }
void SMTPClientConnection::InternalParseData(const AnsiString &Request) { LOG_DEBUG("SMTPClientConnection::_ParseASCII()"); String sData = "RECEIVED: " + Request; LOG_SMTP_CLIENT(GetSessionID(), GetIPAddress().ToString(), sData); // Below 3 lines is fix of the problem that occurs when the remote server answers // with 2 line in his welcome message. String sMinus = "-"; if ((Request.GetLength() > 3) && (Request.GetAt(3) == sMinus.GetAt(0))) { LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 1"); return; } int lFirstSpace = Request.Find(" "); AnsiString sFirstWordTemp; if (lFirstSpace < 0) sFirstWordTemp = Request; else sFirstWordTemp = Request.Mid(0, lFirstSpace); sFirstWordTemp.MakeUpper(); int iCode = atoi(sFirstWordTemp); // We should not update all recipient's if we've just sent a // RCPT TO. We should only update the specific one we've just // sent to. // // Also, we should not update state if we've just sent QUIT to // the server. At the time we send QUIT, the message has already // been either accepted for delivery and rejected. Any error after // this isn't relvat. if (m_CurrentState != RCPTTOSENT && m_CurrentState != QUITSENT) { if (IsPermanentNegative(iCode)) { _UpdateAllRecipientsWithError(iCode, Request, false); _SendQUIT(); return; } else if (IsTransientNegative(iCode)) { _UpdateAllRecipientsWithError(iCode, Request, false); _SendQUIT(); return; } } switch (m_CurrentState) { case SENDUSERNAME: _ProtocolSendUsername(); break; case SENDPASSWORD: _ProtocolSendPassword(); break; case PASSWORDCHECK: if (!_ProtocolPassswordCheck(iCode, Request)) { // Authentication failed. We have just sent // a quit command. return; } break; } if (m_CurrentState == HELO) { if (iCode == 220) { String sComputerName = Utilities::ComputerName(); if (m_bUseSMTPAuth) { _SendData("EHLO " + sComputerName); _SetState(EHLOSENT); } else { _SendData("HELO " + sComputerName); _SetState(HELOSENT); } LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 2"); return ; } else { LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 3"); _UpdateAllRecipientsWithError(iCode, Request, false); _SendQUIT(); return; } } if (m_CurrentState == EHLOSENT) { // Ask the server to initiate login process. _SendData("AUTH LOGIN"); _SetState(SENDUSERNAME); return ; } if (m_CurrentState == HELOSENT) { if (IsPositiveCompletion(iCode)) { // --- Server accepted HELO. Go to HEADER/MAILFROM state. _SetState(MAILFROM); } else { _UpdateAllRecipientsWithError(iCode, Request, false); } } if (m_CurrentState == MAILFROM) { String sFrom = m_pDeliveryMessage->GetFromAddress(); String sData = "MAIL FROM:<" + sFrom + ">"; _SendData(sData); m_CurrentState = MAILFROMSENT; LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 4"); return; } if (m_CurrentState == MAILFROMSENT) { if (IsPositiveCompletion(iCode)) { // --- Server accepted mail from. Go to header/rcpt to state. m_CurrentState = RCPTTO; } else { LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 5"); _UpdateAllRecipientsWithError(iCode, Request, false); } } if (m_CurrentState == RCPTTO) { LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 6"); shared_ptr<MessageRecipient> pRecipient = _GetNextRecipient(); if (!pRecipient) { _SendQUIT(); return; } String sRecipient = pRecipient->GetAddress(); String sData = "RCPT TO:<" + sRecipient + ">"; _SendData(sData); m_CurrentState = RCPTTOSENT; return; } if (m_CurrentState == RCPTTOSENT) { if (m_iCurRecipient < m_vecRecipients.size()) { if (IsPositiveCompletion(iCode)) { _actualRecipients.insert(m_vecRecipients[m_iCurRecipient]); } else { _UpdateRecipientWithError(iCode, Request, m_vecRecipients[m_iCurRecipient], false); } } shared_ptr<MessageRecipient> pRecipient = _GetNextRecipient(); if (pRecipient) { // Send next recipient. _SendData("RCPT TO:<" + pRecipient->GetAddress() + ">"); m_CurrentState = RCPTTOSENT; } else { if (_actualRecipients.size() == 0) { _SendQUIT(); return; } m_CurrentState = DATAQUESTION; } } if (m_CurrentState == DATAQUESTION) { _SendData("DATA"); m_CurrentState = DATA; LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 7"); return; } if (m_CurrentState == DATA) { if (IsPositiveIntermediate(iCode)) { // Send the data! const String fileName = PersistentMessage::GetFileName(m_pDeliveryMessage); LOG_DEBUG("SMTPClientConnection::~_BEFORE SendFile"); _StartSendFile(fileName); LOG_DEBUG("SMTPClientConnection::~_AFTER SendFile"); return; } } if (m_CurrentState == DATASENT) { LOG_DEBUG("SMTPClientConnection::~_BEFORE SendQUIT"); _SendQUIT(); LOG_DEBUG("SMTPClientConnection::~_AFTER SendQUIT"); if (IsPositiveCompletion(iCode)) { _UpdateSuccessfulRecipients(); LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 9"); return; } else { _UpdateAllRecipientsWithError(iCode, Request, false); LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 10"); } return; } if (m_CurrentState == QUITSENT) { // We just received a reply on our QUIT. Time to disconnect. m_bPendingDisconnect = true; PostDisconnect(); } }
void IMAPSort::CacheHeaderFields_(std::shared_ptr<IMAPConnection> pConnection, const std::vector<std::pair<int, std::shared_ptr<Message> > > &vecMessages, const std::map<__int64, String > &databaseMetaData, SortField &sortField, std::map<__int64, String> &mapHeaderFields) { mapHeaderFields.clear(); String sHeaderField; switch (sortField) { case From: sHeaderField = "From"; break; case Subject: sHeaderField = "Subject"; break; case To: sHeaderField = "To"; break; case CC: sHeaderField = "CC"; break; case Date: sHeaderField = "Date"; break; } // Cache the header field for all messages. bool bTrimLeadingSpecialCharacters = (sortField == From || sortField == To || sortField == CC); std::vector<std::pair<int, std::shared_ptr<Message> > >::const_iterator iter = vecMessages.begin(); std::vector<std::pair<int, std::shared_ptr<Message> > >::const_iterator iterEnd = vecMessages.end(); for (; iter != iterEnd; iter++) { // Fetch message. const std::shared_ptr<Message> p1 = (*iter).second; String sFieldValue = ""; // Read message and parse out the value from the header. std::map<__int64, String >::const_iterator dbMetaIter = databaseMetaData.find(p1->GetID()); if (dbMetaIter == databaseMetaData.end()) { String fileName = PersistentMessage::GetFileName(pConnection->GetAccount(), p1); AnsiString sHeader = PersistentMessage::LoadHeader(fileName); MimeHeader oHeader;oHeader.Load(sHeader, sHeader.GetLength()); sFieldValue = oHeader.GetUnicodeFieldValue(sHeaderField); if (sortField == Date) { DateTime dt = Time::GetDateTimeFromMimeHeader(sFieldValue); sFieldValue = Time::GetTimeStampFromDateTime(dt); } } else { sFieldValue = (*dbMetaIter).second; } if (sortField == Date && sFieldValue.IsEmpty()) { /* * RFC 5256 "2.2. Sent Date" chapter. If the sent date cannot be determined (a Date: header is missing or cannot be parsed), * the INTERNALDATE for that message is used as the sent date. */ sFieldValue = p1->GetCreateTime(); } // Convert the string to upper case. The sorting should be // case insensitive. Otherwise b will come before A. sFieldValue.ToUpper(); // Remove leading ". If we sort on From, "Test" should come in // same position as Test. (quotes / no quotes) if (bTrimLeadingSpecialCharacters) { sFieldValue.TrimLeft(_T("\"")); sFieldValue.TrimLeft(_T("<")); } // Cache the header mapHeaderFields[p1->GetID()] = sFieldValue; } }
void SMTPVacationMessageCreator::CreateVacationMessage(shared_ptr<const Account> recipientAccount, const String &sToAddress, const String &sVacationSubject, const String &sVacationMessage, const shared_ptr<Message> pOriginalMessage) { if (!_CanSendVacationMessage(recipientAccount->GetAddress(), sToAddress)) return; // We have already notified this user. LOG_DEBUG("Creating out-of-office message."); String sModifiedSubject = sVacationSubject; String sModifiedBody = sVacationMessage; const String originalFileName = PersistentMessage::GetFileName(recipientAccount, pOriginalMessage); if (sModifiedSubject.Find(_T("%")) >= 0 || sModifiedBody.Find(_T("%")) >= 0) { // Replace macros in the string. MimeHeader header; AnsiString sHeader = PersistentMessage::LoadHeader(originalFileName); header.Load(sHeader, sHeader.GetLength(), true); String sOldSubject; if (header.GetField("Subject")) sOldSubject = header.GetField("Subject")->GetValue(); sModifiedSubject.ReplaceNoCase(_T("%SUBJECT%"), sOldSubject); sModifiedBody.ReplaceNoCase(_T("%SUBJECT%"), sOldSubject); } if (sModifiedSubject.GetLength() == 0) { // Parse out the subject in the original // message, so that we can Re: that.. MimeHeader header; AnsiString sHeader = PersistentMessage::LoadHeader(originalFileName); header.Load(sHeader, sHeader.GetLength(), true); String sOldSubject; if (header.GetField("Subject")) sOldSubject = header.GetField("Subject")->GetValue(); sModifiedSubject = "Re: " + sOldSubject; } // Send a copy of this email. shared_ptr<Message> pMsg = shared_ptr<Message>(new Message()); pMsg->SetState(Message::Delivering); pMsg->SetFromAddress(recipientAccount->GetAddress()); const String newFileName = PersistentMessage::GetFileName(pMsg); shared_ptr<MessageData> pNewMsgData = shared_ptr<MessageData>(new MessageData()); pNewMsgData->LoadFromMessage(newFileName, pMsg); // Required headers pNewMsgData->SetReturnPath(recipientAccount->GetAddress()); pNewMsgData->GenerateMessageID(); pNewMsgData->SetSentTime(Time::GetCurrentMimeDate()); pNewMsgData->SetFieldValue("Content-Type", "text/plain; charset=\"utf-8\""); // Optional headers pNewMsgData->SetFrom(recipientAccount->GetAddress()); pNewMsgData->SetTo(sToAddress); pNewMsgData->SetSubject(sModifiedSubject); pNewMsgData->SetBody(sModifiedBody); pNewMsgData->SetAutoReplied(); pNewMsgData->IncreaseRuleLoopCount(); // Write message data pNewMsgData->Write(newFileName); // Add recipients. bool recipientOK = false; RecipientParser recipientParser; recipientParser.CreateMessageRecipientList(sToAddress, pMsg->GetRecipients(), recipientOK); // Save message if (pMsg->GetRecipients()->GetCount() > 0) PersistentMessage::SaveObject(pMsg); // Tell app to submit mail Application::Instance()->SubmitPendingEmail(); }