【问题标题】:How to send mail using socket C++如何使用套接字 C++ 发送邮件
【发布时间】:2019-10-06 13:03:34
【问题描述】:

我正在使用套接字将邮件从我的 Gmail 帐户发送到我的 Gmail 帐户,以避免 SSL 和身份验证,但我不知道 Gmail 是否会因为 TLS(垃圾邮件原因)以某种方式阻止这些端口,因为我没有收到任何内容垃圾邮件文件夹也是空的。

如果有人对此主题有经验,我将不胜感激。

int main() {

    cout << "send mail" << endl;

    char arr[] = "gmail-smtp-in.l.google.com";
    char* ptrServer = arr;
    char arr0[] = "someaddress@gmail.com";
    char* ptrReceiver= arr0;
    char arr1[] = "someaddress@gmail.com";
    char* ptrSender = arr1;
    char arr2[] = "- Some Data -";
    char* ptrSubject = arr2; 
    char arr3[] = "Hello from the PC";
    char* ptrMessage = arr3;

    sendEmail(ptrServer, ptrReceiver, ptrSender, ptrSubject, ptrMessage);

    cin >> arr;
    return 0;
}

这里是我用来发送邮件的函数(我不知道你需要为 TLS 发送什么,我只是发送这个序列 EHLO 和 STARTTLS)

void sendEmail(char * server, char * to, char * from, char * subject, char * message) {


    SOCKET sockfd;
    WSADATA wsaData;
    hostent* host;
    sockaddr_in dest;



    char szSmtpServerName[64] = "";
    int sent;
    char line[256];

    if (WSAStartup(0x202, &wsaData) != SOCKET_ERROR) {
        if ((host = gethostbyname(server)) != NULL) {
            memset(&dest, 0, sizeof(dest));
            memcpy(&(dest.sin_addr), host->h_addr, host->h_length);

            dest.sin_family = host->h_addrtype;
            dest.sin_port = htons(25);

            sockfd = socket(AF_INET, SOCK_STREAM, 0);


            connect(sockfd, (struct sockaddr*) & dest, sizeof(dest));


            strcpy_s(line, "EHLO\n"); 
            sent=send(sockfd, line, strlen(line),0);
            Sleep(500);

            strcpy_s(line, "STARTTLS\n");
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

            strcpy_s(line, "MAIL FROM:<");
            strncat_s(line, from, strlen(from));
            strncat_s(line, ">\n", 3);
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);


            strcpy_s(line, "RCPT TO:<");
            strncat_s(line, to, strlen(to));
            strncat_s(line, ">\n", 3);
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

            strcpy_s(line, "DATA\n");
            sent = (send(sockfd, line, strlen(line), 0));
            Sleep(500);


            strcpy_s(line, "To: ");
            strcat_s(line, to);
            strcat_s(line, "\n");
            strcat_s(line, "From: ");
            strcat_s(line, from);
            strcat_s(line, "\n");
            strcat_s(line, "Subject: ");
            strcat_s(line, subject);
            strcat_s(line, "\n");
            strcat_s(line, message);
            strcat_s(line, "\r\n.\r\n");
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

            strcpy_s(line, "quit\n");
            sent = send(sockfd, line, strlen(line), 0);
            Sleep(500);

        }

    }
    closesocket(sockfd);
    WSACleanup();
    cout << "mail was sent" << endl;
}

【问题讨论】:

    标签: c++ visual-studio sockets websocket smtp


    【解决方案1】:

    SMTPis a publicly available document 的完整规范。如果您查看 SMTP 的这些正式规范,您将很容易发现所显示代码的一些基本问题。

    1) 建立连接后,发送者必须等待服务器的初始问候消息。所示代码立即发送EHLO 命令,无需等待。

    2)发送EHLO命令后,发送方必须等待服务器的响应,而不是等待500毫秒,然后处理响应。

    3) EHLO 命令可能会失败,因为它是一个扩展;如果是这样,发件人必须回退到 HELO。不太可能,使用现代 SMTP 服务器,但必须准备好强大的程序来处理。

    4) 在所有情况下,服务器的响应都可能指示错误和/或拒绝接受邮件。显示的代码无法进行任何错误检查。

    5) 发送者发送STARTTLS命令后,必须等待服务器的响应,如果命令成功,发送者必须发起TLS协商。显示的代码无法做到这一点。

    6) 发生 TLS 协商并建立加密连接后,SMTP 会话从初始状态重新启动,从 EHLO/HELO 状态开始,而不是 MAIL FROM

    您不能采取任何简单的捷径,例如在规定的一段时间内睡觉,而不是正确处理服务器回复。随着时间的推移,这将无法可靠地工作。它可能看起来有效,一次或两次,但最终会崩溃。那是保证。您必须正确、完整地实施 SMTP 的每个部分,并正确实施。

    由于您使用的是 Microsoft Windows,因此您应该在 Microsoft 的文档中找到有关在 MS-Windows 上使用 TLS 的完整文档。显然,这是一个非常大的主题,根本不会逐字复制到此答案或 Stackoverflow 上的任何其他答案中。有关详细信息,请参阅 Microsoft 在 MSDN 或其他地方的文档。

    这些都是相当复杂的大型技术编程主题。您不会在 Stackoverflow 或任何其他公共论坛上找到对它们的完整描述简化为完整的一或两段答案。任何人都可以告诉您的唯一一件事是参考技术文档以获取有关特定协议如何工作的完整规范。知道在哪里可以找到以及如何阅读技术文档是每个 C++ 开发人员都需要知道的事情。

    您也很可能会发现 MS-Windows 可能会提供一个 SMTP 客户端库,该库可以正确且正确地处理 SMTP 的所有方面,包括 TLS,而无需担心您的代码。而这种 SMTP 客户端库是否可用,只有在查阅 Microsoft 的技术文档后才能确定。

    【讨论】:

    • 感谢您的回答!它对每个试图理解这个主题的人都非常有帮助。
    • 我的意思是有另一个命令来开始协商还是用一些winsock函数来处理?
    • @Itsmycode Winsock 根本不处理 SSL/TLS。为此,您需要一个单独的库。您可以使用 Microsoft 的 SChannel、开源 OpenSSL 或任何数量的其他可用库。
    • @SamVarshavchik "您也很可能会发现 MS-Windows 可能会提供一个 SMTP 客户端库,可以正确且正确地处理 SMTP 的所有方面" - Windows 不提供这样的内置库。另一方面,Microsoft 的 .NET 框架确实有一个 SmtpClient 类,但它已被弃用,取而代之的是第三方库。
    猜你喜欢
    • 2011-09-04
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 2017-03-15
    • 2011-01-22
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    相关资源
    最近更新 更多