// This method sends the report over HTTP request BOOL CErrorReportSender::SendOverHTTP() { strconv_t strconv; if(g_CrashInfo.m_uPriorities[CR_HTTP]<0) { m_Assync.SetProgress(_T("Sending error report over HTTP is disabled (negative priority); skipping."), 0); return FALSE; } if(g_CrashInfo.m_sUrl.IsEmpty()) { m_Assync.SetProgress(_T("No URL specified for sending error report over HTTP; skipping."), 0); return FALSE; } CHttpRequest request; request.m_sUrl = g_CrashInfo.m_sUrl; request.m_aTextFields[_T("appname")] = strconv.t2a(g_CrashInfo.m_sAppName); request.m_aTextFields[_T("appversion")] = strconv.t2a(g_CrashInfo.m_sAppVersion); request.m_aTextFields[_T("crashguid")] = strconv.t2a(g_CrashInfo.m_sCrashGUID); request.m_aTextFields[_T("emailfrom")] = strconv.t2a(g_CrashInfo.m_sEmailFrom); request.m_aTextFields[_T("emailsubject")] = strconv.t2a(g_CrashInfo.m_sEmailSubject); request.m_aTextFields[_T("description")] = strconv.t2a(g_CrashInfo.m_sDescription); CString sMD5Hash; CalcFileMD5Hash(m_sZipName, sMD5Hash); request.m_aTextFields[_T("md5")] = strconv.t2a(sMD5Hash); if(g_CrashInfo.m_bHttpBinaryEncoding) { CHttpRequestFile f; f.m_sSrcFileName = m_sZipName; f.m_sContentType = _T("application/zip"); request.m_aIncludedFiles[_T("crashrpt")] = f; } else { std::string sEncodedData; int nRet = Base64EncodeAttachment(m_sZipName, sEncodedData); if(nRet!=0) { return FALSE; } request.m_aTextFields[_T("crashrpt")] = sEncodedData; } BOOL bSend = m_HttpSender.SendAssync(request, &m_Assync); return bSend; }
int CSmtpClient::SendEmailToRecipient(CString sSmtpServer, CEmailMessage* msg, AssyncNotification* scn) { int status = 1; strconv_t strconv; struct addrinfo *result = NULL; struct addrinfo *ptr = NULL; struct addrinfo hints; int iResult = -1; CString sPostServer; CString sServiceName = "25"; SOCKET sock = INVALID_SOCKET; CString sMsg, str; std::set<CString>::iterator it; CString sStatusMsg; // Prepare message text CString sMessageText = msg->m_sText; sMessageText.Replace(_T("\n"),_T("\r\n")); sMessageText.Replace(_T("\r\n.\r\n"), _T("\r\n*\r\n")); LPCWSTR lpwszMessageText = strconv.t2w(sMessageText.GetBuffer(0)); std::string sUTF8Text = UTF16toUTF8(lpwszMessageText); // Check that all attachments exist for(it=msg->m_aAttachments.begin(); it!=msg->m_aAttachments.end(); it++) { if(CheckAttachmentOK(*it)!=0) { sStatusMsg.Format(_T("Attachment not found: %s"), *it); scn->SetProgress(sStatusMsg, 1); return 2; // critical error } } sStatusMsg.Format(_T("Getting address info of %s port %s"), sSmtpServer, CString(sServiceName)); scn->SetProgress(sStatusMsg, 1); int res = SOCKET_ERROR; char buf[1024]=""; std::string sEncodedFileData; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; LPCSTR lpszSmtpServer = strconv.t2a(sSmtpServer); LPCSTR lpszServiceName = strconv.t2a(sServiceName); iResult = getaddrinfo(lpszSmtpServer, lpszServiceName, &hints, &result); if(iResult!=0) goto exit; for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { if(scn->IsCancelled()) {status = 2; goto exit;} sStatusMsg.Format(_T("Creating socket")); scn->SetProgress(sStatusMsg, 1); sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if(sock==INVALID_SOCKET) { scn->SetProgress(_T("Socket creation failed."), 1); goto exit; } sStatusMsg.Format(_T("Connecting to SMTP server %s port %s"), sSmtpServer, CString(sServiceName)); scn->SetProgress(sStatusMsg, 1); res = connect(sock, ptr->ai_addr, (int)ptr->ai_addrlen); if(res!=SOCKET_ERROR) break; closesocket(sock); } if(res==SOCKET_ERROR) goto exit; sStatusMsg.Format(_T("Connected OK.")); scn->SetProgress(sStatusMsg, 5); if(scn->IsCancelled()) {status = 2; goto exit;} res = recv(sock, buf, 1024, 0); if(res==SOCKET_ERROR) { sStatusMsg.Format(_T("Failed to receive greeting message from SMTP server (recv code %d)."), res); scn->SetProgress(sStatusMsg, 1); goto exit; } if(220!=GetMessageCode(buf)) { goto exit; } char responce[1024]; sStatusMsg.Format(_T("Sending HELO")); scn->SetProgress(sStatusMsg, 1); // send HELO res=SendMsg(scn, sock, _T("HELO CrashSender\r\n"), responce, 1024); if(res!=250) { sStatusMsg = CString(responce, 1024); scn->SetProgress(sStatusMsg, 0); goto exit; } sStatusMsg.Format(_T("Sending sender and recipient information")); scn->SetProgress(sStatusMsg, 1); sMsg.Format(_T("MAIL FROM:<%s>\r\n"), msg->m_sFrom); res=SendMsg(scn, sock, sMsg, responce, 1024); if(res!=250) { sStatusMsg = CString(responce, 1024); scn->SetProgress(sStatusMsg, 0); goto exit; } sMsg.Format(_T("RCPT TO:<%s>\r\n"), msg->m_sTo); res=SendMsg(scn, sock, sMsg, responce, 1024); if(res!=250) { sStatusMsg = CString(responce, 1024); scn->SetProgress(sStatusMsg, 0); goto exit; } sStatusMsg.Format(_T("Start sending email data")); scn->SetProgress(sStatusMsg, 1); // Send DATA res=SendMsg(scn, sock, _T("DATA\r\n"), responce, 1024); if(res!=354) { sStatusMsg = CString(responce, 1024); scn->SetProgress(sStatusMsg, 0); goto exit; } str.Format(_T("From: <%s>\r\n"), msg->m_sFrom); sMsg = str; str.Format(_T("To: <%s>\r\n"), msg->m_sTo); sMsg += str; str.Format(_T("Subject: %s\r\n"), msg->m_sSubject); sMsg += str; sMsg += "MIME-Version: 1.0\r\n"; sMsg += "Content-Type: multipart/mixed; boundary=KkK170891tpbkKk__FV_KKKkkkjjwq\r\n"; sMsg += "\r\n\r\n"; res = SendMsg(scn, sock, sMsg); if(res!=sMsg.GetLength()) goto exit; /* Message text */ sStatusMsg.Format(_T("Sending message text")); scn->SetProgress(sStatusMsg, 15); sMsg = "--KkK170891tpbkKk__FV_KKKkkkjjwq\r\n"; sMsg += "Content-Type: text/plain; charset=UTF-8\r\n"; sMsg += "\r\n"; sMsg += sUTF8Text.c_str(); sMsg += "\r\n"; res = SendMsg(scn, sock, sMsg); if(res!=sMsg.GetLength()) goto exit; sStatusMsg.Format(_T("Sending attachments")); scn->SetProgress(sStatusMsg, 1); /* Attachments. */ for(it=msg->m_aAttachments.begin(); it!=msg->m_aAttachments.end(); it++) { CString sFileName = *it; sFileName.Replace('/', '\\'); CString sDisplayName = sFileName.Mid(sFileName.ReverseFind('\\')+1); // Header sMsg = "\r\n--KkK170891tpbkKk__FV_KKKkkkjjwq\r\n"; sMsg += "Content-Type: application/octet-stream\r\n"; sMsg += "Content-Transfer-Encoding: base64\r\n"; sMsg += "Content-Disposition: attachment; filename=\""; sMsg += sDisplayName; sMsg += "\"\r\n"; sMsg += "\r\n"; res = SendMsg(scn, sock, sMsg); if(res!=sMsg.GetLength()) goto exit; // Encode data LPBYTE buf = NULL; //int buf_len = 0; int nEncode=Base64EncodeAttachment(sFileName, sEncodedFileData); if(nEncode!=0) { sStatusMsg.Format(_T("Error BASE64-encoding attachment %s"), sFileName); scn->SetProgress(sStatusMsg, 1); goto exit; } // Send encoded data sMsg = sEncodedFileData.c_str(); res = SendMsg(scn, sock, sMsg); if(res!=sMsg.GetLength()) goto exit; delete [] buf; } sMsg = "\r\n--KkK170891tpbkKk__FV_KKKkkkjjwq--"; res = SendMsg(scn, sock, sMsg); if(res!=sMsg.GetLength()) goto exit; // End of message marker if(250!=SendMsg(scn, sock, _T("\r\n.\r\n"), responce, 1024)) { sStatusMsg = CString(responce, 1024); scn->SetProgress(sStatusMsg, 0); goto exit; } // quit if(221!=SendMsg(scn, sock, _T("QUIT \r\n"), responce, 1024)) { sStatusMsg = CString(responce, 1024); scn->SetProgress(sStatusMsg, 0); goto exit; } // OK. status = 0; exit: if(scn->IsCancelled()) status = 2; sStatusMsg.Format(_T("Finished with error code %d"), status); scn->SetProgress(sStatusMsg, 100, false); // Clean up closesocket(sock); freeaddrinfo(result); return status; }
int CSmtpClient::SendEmailToRecipient(CString sSmtpServer, CEmailMessage* msg) { // This method connects to the given SMTP server and tries to send // the E-mail message. int status = 1; // Resulting status. strconv_t strconv; // String convertor struct addrinfo *result = NULL; struct addrinfo *ptr = NULL; struct addrinfo hints; std::string sEncodedLogin; std::string sEncodedPassword; CString sBodyTo; //Vojtech: Lines of the "To:" and "Cc:" lines, that will become part of the e-mail header. int iResult = -1; CString sPostServer; CString sServiceName; SOCKET sock = INVALID_SOCKET; CString sMsg, str; std::set<CString>::iterator it; CString sStatusMsg; const int RESPONSE_BUFF_SIZE = 4096; char response[RESPONSE_BUFF_SIZE]; int res = SOCKET_ERROR; std::string sEncodedFileData; bool bESMTP = false; // Convert port number to string sServiceName.Format(_T("%d"), m_sServer.IsEmpty()?25:m_nPort); // Prepare message text (we need to replace "\n" by "\r\n" and remove . from message). CString sMessageText = msg->GetText(); sMessageText.Replace(_T("\n"),_T("\r\n")); sMessageText.Replace(_T("\r\n.\r\n"), _T("\r\n*\r\n")); LPCWSTR lpwszMessageText = strconv.t2w(sMessageText.GetBuffer(0)); // Convert the text to UTF-8 encoding std::string sUTF8Text = UTF16toUTF8(lpwszMessageText); // Check that all attachments exist int i; for(i=0; i<msg->GetAttachmentCount(); i++) { CString sFileName = msg->GetAttachment(i); if(CheckAttachmentOK(sFileName)!=0) { // Some attachment file does not present sStatusMsg.Format(_T("Attachment not found: %s"), sFileName); m_scn->SetProgress(sStatusMsg, 1); return 2; // critical error } } // Add a message to log sStatusMsg.Format(_T("Getting address info of %s port %s"), sSmtpServer, CString(sServiceName)); m_scn->SetProgress(sStatusMsg, 1); // Prepare to open socket memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; LPCSTR lpszSmtpServer = strconv.t2a(sSmtpServer); LPCSTR lpszServiceName = strconv.t2a(sServiceName); iResult = getaddrinfo(lpszSmtpServer, lpszServiceName, &hints, &result); if(iResult!=0) goto exit; // For each interface do for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { // Check if cancelled if(m_scn->IsCancelled()) {status = 2; goto exit;} // Add a message to log sStatusMsg.Format(_T("Creating socket")); m_scn->SetProgress(sStatusMsg, 1); // Open socket sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if(sock==INVALID_SOCKET) { m_scn->SetProgress(_T("Socket creation failed."), 1); goto exit; } // Add a message to log sStatusMsg.Format(_T("Connecting to SMTP server %s port %s"), sSmtpServer, CString(sServiceName)); m_scn->SetProgress(sStatusMsg, 1); // Connect socket res = connect(sock, ptr->ai_addr, (int)ptr->ai_addrlen); if(res!=SOCKET_ERROR) break; // If successfull, break the loop // Close socket closesocket(sock); } // Check if socket open if(res==SOCKET_ERROR) { sStatusMsg.Format(_T("Socket connection error.")); m_scn->SetProgress(sStatusMsg, 5); goto exit; } // Add a message to log sStatusMsg.Format(_T("Connected OK.")); m_scn->SetProgress(sStatusMsg, 5); // Check cancel status if(m_scn->IsCancelled()) {status = 2; goto exit;} m_scn->SetProgress(_T("Waiting for greeting message from SMTP server..."), 1); // Wait until server send us greeting message, for example: // 220 mail.company.tld ESMTP CommuniGate Pro 5.1.4i is glad to see you! res=SendMsg(sock, NULL, response, RESPONSE_BUFF_SIZE); if(res==SOCKET_ERROR) { // Error - server did not send us greeting message sStatusMsg.Format(_T("Failed to receive greeting message from SMTP server (recv code %d)."), res); m_scn->SetProgress(sStatusMsg, 1); goto exit; } // Check the code server returned (expect code 220). if(220!=GetMessageCode(response)) { // Invalid greeting m_scn->SetProgress(_T("Invalid greeting message."), 1); goto exit; } // Add a message to log sStatusMsg.Format(_T("Sending EHLO")); m_scn->SetProgress(sStatusMsg, 1); res=SendMsg(sock, _T("EHLO CrashSender\r\n"), response, RESPONSE_BUFF_SIZE); // Check return code (expect code 250) if(res==250) { sStatusMsg = CString(_T("EHLO command not supported")); bESMTP = true; } if(!bESMTP) { // Server may not understand EHLO, try HELO sStatusMsg.Format(_T("Sending HELO")); m_scn->SetProgress(sStatusMsg, 1); res=SendMsg(sock, _T("HELO CrashSender\r\n"), response, RESPONSE_BUFF_SIZE); // Expect code 250 if(res!=250) { // Add a message to log sStatusMsg = CString(_T("HELO command not supported")); m_scn->SetProgress(sStatusMsg, 0); goto exit; } } // Check whether to perform authorization procedure if(!m_sLogin.IsEmpty()) { if(!bESMTP) { sStatusMsg.Format(_T("SMTP server does not support authorization.")); m_scn->SetProgress(sStatusMsg, 1); } sStatusMsg.Format(_T("Sending AUTH LOGIN.")); m_scn->SetProgress(sStatusMsg, 1); // SMTP authorization // AUTH <SP> LOGIN <CRLF> res=SendMsg(sock, _T("AUTH LOGIN\r\n"), response, RESPONSE_BUFF_SIZE); if(res!=334) { m_scn->SetProgress(_T("Unexpected server response"), 0); goto exit; } // Send login sStatusMsg.Format(_T("Sending login")); m_scn->SetProgress(sStatusMsg, 1); // Convert login to ASCII LPCSTR lpszLogin = strconv.t2a(m_sLogin); // And encode it in BASE-64 sEncodedLogin = base64_encode(reinterpret_cast<const unsigned char*>(lpszLogin),(int)strlen(lpszLogin)); sEncodedLogin+="\r\n"; LPCTSTR lpwszLogin = strconv.a2t((LPCSTR)(sEncodedLogin.c_str())); memset(response,0,1024); // Send it res=SendMsg(sock, lpwszLogin, response, 1024); // Check return code - expect 334 if (res!=334) { sStatusMsg = _T("Login not accepted"); m_scn->SetProgress(sStatusMsg, 0); goto exit; } // Send password sStatusMsg.Format(_T("Sending password")); m_scn->SetProgress(sStatusMsg, 1); // Convert to ASCII LPCSTR lpszPassword = strconv.t2a(m_sPassword); // BASE-64 encode sEncodedPassword = base64_encode(reinterpret_cast<const unsigned char*>(lpszPassword),(int)strlen(lpszPassword)); sEncodedPassword+="\r\n"; LPCTSTR lpwszPassword = strconv.a2t((LPCSTR)(sEncodedPassword.c_str())); memset(response,0,1024); // Send it res=SendMsg(sock, lpwszPassword, response, 1024); if(res!=235) { sStatusMsg = _T("Authorization failed"); m_scn->SetProgress(sStatusMsg, 0); } } // Next send sender and recipient info sStatusMsg.Format(_T("Sending sender and recipient information")); m_scn->SetProgress(sStatusMsg, 1); // Send MAIL FROM sMsg.Format(_T("MAIL FROM:<%s>\r\n"), msg->GetSenderAddress()); res=SendMsg(sock, sMsg, response, RESPONSE_BUFF_SIZE); if (res!=250) { sStatusMsg = _T("Unexpected status code"); m_scn->SetProgress(sStatusMsg, 0); goto exit; } // Process multiple e-mail recipients. for(i=0; i<msg->GetRecipientCount(); i++) { sMsg.Format(i==0 ? _T("To: <%s>\r\n") : _T("Cc: <%s>\r\n"), msg->GetRecipientAddress(i)); sBodyTo += sMsg; sMsg.Format(_T("RCPT TO:<%s>\r\n"), msg->GetRecipientAddress(i)); res=SendMsg(sock, sMsg, response, RESPONSE_BUFF_SIZE); if(res!=250) { sStatusMsg = _T("Unexpected status code"); m_scn->SetProgress(sStatusMsg, 0); goto exit; } } sStatusMsg.Format(_T("Start sending email data")); m_scn->SetProgress(sStatusMsg, 1); // Send DATA res=SendMsg(sock, _T("DATA\r\n"), response, RESPONSE_BUFF_SIZE); if (res!=354) { sStatusMsg = _T("Unexpected status code"); m_scn->SetProgress(sStatusMsg, 0); goto exit; } // Get current time time_t cur_time; time(&cur_time); char szDateTime[64] = ""; #if _MSC_VER >= 1400 struct tm ltimeinfo; localtime_s(<imeinfo, &cur_time ); strftime(szDateTime, 64, "%a, %d %b %Y %H:%M:%S", <imeinfo); #else struct tm* ltimeinfo = localtime(&cur_time ); strftime(szDateTime, 64, "%a, %d %b %Y %H:%M:%S", ltimeinfo); #endif TIME_ZONE_INFORMATION tzi; GetTimeZoneInformation(&tzi); int diff_hours = -tzi.Bias/60; int diff_mins = abs(tzi.Bias%60); // Send date header str.Format(_T("Date: %s %c%02d%02d\r\n"), strconv.a2t(szDateTime), diff_hours>=0?'+':'-', diff_hours, diff_mins); sMsg = str; // Send From header str.Format(_T("From: <%s>\r\n"), msg->GetSenderAddress()); sMsg += str; sMsg += sBodyTo; // Send subject str.Format(_T("Subject: %s\r\n"), msg->GetSubject()); sMsg += str; // Send MIME-Version header sMsg += "MIME-Version: 1.0\r\n"; // Send Content-Type sMsg += "Content-Type: multipart/mixed; boundary=KkK170891tpbkKk__FV_KKKkkkjjwq\r\n"; sMsg += "\r\n\r\n"; res = SendMsg(sock, sMsg); if(res!=sMsg.GetLength()) goto exit; /* Message text */ sStatusMsg.Format(_T("Sending message text")); m_scn->SetProgress(sStatusMsg, 15); sMsg = "--KkK170891tpbkKk__FV_KKKkkkjjwq\r\n"; sMsg += "Content-Type: text/plain; charset=UTF-8\r\n"; sMsg += "\r\n"; sMsg += sUTF8Text.c_str(); sMsg += "\r\n"; res = SendMsg(sock, sMsg); if(res!=sMsg.GetLength()) goto exit; sStatusMsg.Format(_T("Sending attachments")); m_scn->SetProgress(sStatusMsg, 1); /* Attachments. */ for(i=0; i<msg->GetAttachmentCount(); i++) { CString sFileName = msg->GetAttachment(i); sFileName.Replace('/', '\\'); CString sDisplayName = sFileName.Mid(sFileName.ReverseFind('\\')+1); // Header sMsg = "\r\n--KkK170891tpbkKk__FV_KKKkkkjjwq\r\n"; sMsg += "Content-Type: application/octet-stream\r\n"; sMsg += "Content-Transfer-Encoding: base64\r\n"; sMsg += "Content-Disposition: attachment; filename=\""; sMsg += sDisplayName; sMsg += "\"\r\n"; sMsg += "\r\n"; res = SendMsg(sock, sMsg); if(res!=sMsg.GetLength()) goto exit; // Encode data LPBYTE buf = NULL; //int buf_len = 0; int nEncode=Base64EncodeAttachment(sFileName, sEncodedFileData); if(nEncode!=0) { sStatusMsg.Format(_T("Error BASE64-encoding attachment %s"), sFileName); m_scn->SetProgress(sStatusMsg, 1); goto exit; } // Send encoded data sMsg = sEncodedFileData.c_str(); res = SendMsg(sock, sMsg); if(res!=sMsg.GetLength()) goto exit; delete [] buf; } sMsg = "\r\n--KkK170891tpbkKk__FV_KKKkkkjjwq--"; res = SendMsg(sock, sMsg); if(res!=sMsg.GetLength()) goto exit; // End of message marker res = SendMsg(sock, _T("\r\n.\r\n"), response, RESPONSE_BUFF_SIZE); if (res!=250) { goto exit; } // Quit res = SendMsg(sock, _T("QUIT\r\n"), response, RESPONSE_BUFF_SIZE); // Expect code 221 if(res!=221) { goto exit; } // OK. status = 0; exit: if(m_scn->IsCancelled()) status = 2; sStatusMsg.Format(_T("Finished with error code %d"), status); m_scn->SetProgress(sStatusMsg, 100, false); // Clean up closesocket(sock); freeaddrinfo(result); return status; }