c++ - 使用 C++ WINSOCK(TCP、SSL)发送电子邮件

标签 c++ email ssl smtp winsock2

几天来,我一直在尝试使用 C++ 向自己发送一封简短的纯文本电子邮件。我正在使用 Visual Studio Express 2015。我最终希望通过电子邮件向自己发送自动警报。我正在使用 Gmail 帐户。我似乎无法让它发挥作用。我可以发送数据,但无法接收。服务器正在关闭与错误 10054 的连接。(您可以在 this page 上阅读该错误的含义。)

历史是这样的:我从很多 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] = "my_email@host.com";
    char            msg[512] = "Hello world!";
    char            port[12] = "465";
    char            serverName[64] = "smtp.host.com";
    char            toAddresses[64] = "my_email@host.com";
    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;
    }
}

最佳答案

这个答案的三个部分。

  1. MIME编码用户名和密码。
  2. 实际发送用户名和密码! :)
  3. 有些服务器持怀疑态度,希望您说两次 HELO 或 EHLO。

我会尽快发布完整代码。虽然我觉得我已经完成了大约 40%,但我的成功归功于这个网站:http://www.coastrd.com/smtps .

关于c++ - 使用 C++ WINSOCK(TCP、SSL)发送电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37233514/

相关文章:

c++ - 向非 C++ 程序员解释 C++ SFINAE

c++ - Q_REVISION在Qt类中的含义

iOS9 GoogleAnalytics 和 NSAppTransportSecurity

java - 解决由于 C++ 导致的 Google protobuf 中枚举字段命名限制的解决方案

c++ - 使用 g++ 与 ACE 库链接时遇到一些问题

Python、IMAP 和 GMail。将消息标记为已读

电子邮件到 SMS 网关 : recognizing replies

javascript - ng-repeat 在 ssr 渲染电子邮件中不起作用 - Angular meteor

SSL:如果使用 2048 位 RSA key ,协商的对称 key 也会更大

ssl - cURL vs Postman,对 HTTPS POST 的不同响应