2016-05-15 7 views
-1

Я пытался в течение нескольких дней отправить короткое текстовое письмо мне самому с C++. Я использую Visual Studio Express 2015. В конечном итоге я надеюсь, что я отправлю автоответчики. Я использую учетную запись Gmail. Кажется, я не могу заставить это работать. Я могу отправлять данные, но не могу их получить. Сервер закрывает мое соединение с ошибкой 10054. (Вы можете прочитать о том, что эта ошибка означает на this page.)Отправить письмо с помощью C++ WINSOCK (TCP, SSL)

Вот история: Я собрал все это из большого количества S.O. сообщений и статей MSDN. Раньше у меня был функциональный раздел WSASetSocketSecurity, но по какой-то причине мои попытки подключения были отключены, поэтому я опустил его. На этом этапе я соглашусь на то, что сервер не отменит мое соединение, когда я отправлю EHLO или HELO.

Я действительно затрудняюсь с тем, как действовать. Дни исследования, десятки прочитанных статей, сотни тупиков. Я надеюсь, что вы простите несколько бит мусорного кода и что S.O. удалили мои руки. Пожалуйста, взгляните, дайте мне знать, что я делаю неправильно, дайте мне знать о каком-либо неправильном стиле или о чем-либо еще, что оскорбляет ваши чувства хорошего кодера. Большое спасибо.

#include "stdafx.h" 

#include <exception> 
#include <string> 
#include <iostream> // In-out stream objects for development 
#include <stdio.h> // Standard in-out for development 

#include <winsock2.h> // For making socket connection to email server 
#include <Mstcpip.h> 
#include <Ws2tcpip.h> // Enhanced protocols to assist winsock2.h 

#pragma comment(lib, "Ws2_32.lib") // Library for winsock2.h 
#pragma comment(lib, "Fwpuclnt.lib") // Library for winsock2.h 

#define BUFFER_SIZE 512 

using namespace std; 
void cleanup(SOCKET ConnectSocket, struct addrinfo *result) { 
    if (ConnectSocket != INVALID_SOCKET) { 
     closesocket(ConnectSocket); 
    } 
    freeaddrinfo(result); 
    WSACleanup(); 
    cout << "socket closed" << endl; 
    cin.get(); // Development only 
} 

int _tmain(int argc, char* argv[]) { 
    // Initialize email parameters 
    char   bccAddresses[64] = ""; 
    char   fromAddress[64] = "[email protected]"; 
    char   msg[512] = "Hello world!"; 
    char   port[12] = "465"; 
    char   serverName[64] = "smtp.host.com"; 
    char   toAddresses[64] = "[email protected]"; 
    SOCKET   ConnectSocket = INVALID_SOCKET; 
    struct addrinfo *result = NULL; 
    struct addrinfo *ptr = NULL; 
    struct addrinfo hints; 
    WSADATA   wsaData; 

    try { 
     // Initialize Winsock 
     int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << iResult << endl; 
      throw std::exception("WSAStartup failed\n"); 
     } 
     cout << "WSAStartup successful: " << iResult << endl; 

     // Set up the hints socket address structure 
     ZeroMemory(&hints, sizeof(hints)); 
     hints.ai_flags = AI_SECURE; 
     hints.ai_family = AF_INET; 
     hints.ai_socktype = SOCK_STREAM; 
     hints.ai_protocol = IPPROTO_TCP; 

     // Resolve the server address and port 
     iResult = getaddrinfo(serverName, port, &hints, &result); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("getaddrinfo failed\n"); 
     } 
     cout << "getaddrinfo successful: " << iResult << endl; 

     // Connect to the socket 
     ptr = result; 
     ConnectSocket = WSASocket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol, NULL, 0, 0); 
     if (ConnectSocket == INVALID_SOCKET) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("Error at socket\n"); 
     } 
     cout << "WSASocket successful: " << iResult << endl; 

     // Connect via the socket 
     iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << WSAGetLastError() << endl; 
      closesocket(ConnectSocket); 
      ConnectSocket = INVALID_SOCKET; 
      throw std::exception("Unable to connect to server!\n"); 
     } 
     cout << "connect successful: " << iResult << endl; 

     // Send message 
     char sendBuffer[BUFFER_SIZE] = "What is your malfunction"; 
     char recvBuffer[BUFFER_SIZE]; 

     sprintf_s(sendBuffer, BUFFER_SIZE, "EHLO %s%s", serverName, "\r\n"); 
     iResult = send(ConnectSocket, sendBuffer, BUFFER_SIZE, 0); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("WINSOCK send failed\n"); 
     } 
     cout << "Sent:\n" << sendBuffer << "Byte count: " << iResult << endl; 

     iResult = recv(ConnectSocket, recvBuffer, BUFFER_SIZE, 0); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("WINSOCK recv failed\n"); 
     } 
     cout << "EHLO response: " << iResult << endl; 
     sprintf_s(sendBuffer, BUFFER_SIZE, "QUIT%s", "\r\n"); 
     iResult = send(ConnectSocket, sendBuffer, BUFFER_SIZE, 0); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("WINSOCK send failed\n"); 
     } 
     cout << "Sent:\n" << sendBuffer << "Byte count: " << iResult << endl; 
     iResult = recv(ConnectSocket, recvBuffer, BUFFER_SIZE, 0); 
     if (iResult < 0) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("WINSOCK recv failed\n"); 
     } 
     cout << "Quit response: " << iResult << endl; 

     // Shutdown the connection 
     iResult = shutdown(ConnectSocket, SD_SEND); 
     if (iResult == SOCKET_ERROR) { 
      cout << "Error " << WSAGetLastError() << endl; 
      throw std::exception("shutdown failed\n"); 
     } 
     // Clean up 
     cleanup(ConnectSocket, result); 
     return 0; 
    } 
    catch (std::exception err) { 
     printf(err.what()); 
     cleanup(ConnectSocket, result); 
     return 1; 
    } 
    catch (...) { 
     printf("Unknown error\n"); 
     cleanup(ConnectSocket, result); 
     return 2; 
    } 
} 
+0

PS: После этого я буду отделять свою регистрационную информацию от жесткого кода. Сейчас он доступен для простоты, пока я развиваюсь. – GarrettML

+0

О, я тупой ... Я надеюсь, что скоро опубликую свое решение. – GarrettML

ответ

0

Три части этого ответа.

  1. MIME Кодирует имя пользователя и пароль.
  2. НАСТОЛЬКО отправьте имя пользователя и пароль! :)
  3. Некоторые серверы скептически настроены и хотят, чтобы вы дважды сказали HELO или EHLO.

Я отправлю полный код в ближайшее время. Хотя я чувствую, что был около 40% пути, я обязан своим успехом на этом сайте: http://www.coastrd.com/smtps.