如何使用套接字C++发送邮件

How to send mail using socket C++

本文关键字:C++ 何使用 套接字      更新时间:2023-10-16

我正在使用套接字将邮件从我的 Gmail acc 发送到我的 Gmail acc 以避免 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, "EHLOn"); 
sent=send(sockfd, line, strlen(line),0);
Sleep(500);
strcpy_s(line, "STARTTLSn");
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, "DATAn");
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, "rn.rn");
sent = send(sockfd, line, strlen(line), 0);
Sleep(500);
strcpy_s(line, "quitn");
sent = send(sockfd, line, strlen(line), 0);
Sleep(500);
}
}
closesocket(sockfd);
WSACleanup();
cout << "mail was sent" << endl;
}

SMTP的完整规范是一个公开可用的文档。如果您查看 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 上的任何其他答案中。有关详细信息,请参阅 MSDN 或其他位置的 Microsoft 文档。

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

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