|
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <filesystem>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define MAKE_INT32(str) \
(static_cast<uint32_t>(str[0]) << 24 | \
static_cast<uint32_t>(str[1]) << 16 | \
static_cast<uint32_t>(str[2]) << 8 | \
static_cast<uint32_t>(str[3]))
namespace fs = std::filesystem;
const int BUFFER_SIZE = 4096;
bool receiveCommand(SOCKET clientSocket, std::string& command) {
char buffer[BUFFER_SIZE];
int bytesRead = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0);
if (bytesRead <= 0) {
return false;
}
buffer[bytesRead] = '\0';
command = buffer;
return true;
}
std::string parseSender(const std::string& command) {
std::size_t start = command.find('<');
std::size_t end = command.find('>', start);
if (start != std::string::npos && end != std::string::npos) {
return command.substr(start + 1, end - start - 1);
}
return "";
}
std::string parseRecipient(const std::string& command) {
std::size_t start = command.find('<');
std::size_t end = command.find('>', start);
if (start != std::string::npos && end != std::string::npos) {
return command.substr(start + 1, end - start - 1);
}
return "";
}
bool createFolder(const std::string& folderPath) {
try {
fs::create_directory(folderPath);
return true;
}
catch (const std::exception& e) {
std::cerr << "Failed to create folder: " << e.what() << std::endl;
return false;
}
}
void saveEmailToFile(const std::string& emailContent, const std::string& sender, const std::string& recipient) {
std::string folderPath = "email"; // 文件夹路径
// 检查文件夹是否存在
if (createFolder(folderPath)) {
std::cout << "Folder created successfully." << std::endl;
}
std::string fileName = "email/" + sender + "_" + recipient + ".txt";
std:fstream file(fileName);
if (file.is_open()) {
file << emailContent;
file.close();
std::cout << "Email saved to file: " << fileName << std::endl;
}
else {
std::cerr << "Failed to save email to file." << std::endl;
}
}
int main() {
// 初始化 Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Failed to initialize Winsock." << std::endl;
return 1;
}
// 创建套接字
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET) {
std::cerr << "Failed to create socket." << std::endl;
WSACleanup();
return 1;
}
// 绑定地址和端口
sockaddr_in serverAddress{};
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(25); // SMTP默认端口
serverAddress.sin_addr.s_addr = INADDR_ANY;
if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
std::cerr << "Failed to bind." << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
// 监听连接请求
if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) {
std::cerr << "Failed to listen." << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
std::cout << "Server started. Listening for incoming connections..." << std::endl;
while (true) {
// 接受客户端连接
SOCKET clientSocket = accept(serverSocket, nullptr, nullptr);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Failed to accept client connection." << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
std::cout << "Client connected." << std::endl;
const std::string welcomeMessage = "220 Welcome to My Mail Server\r\n";
send(clientSocket, welcomeMessage.c_str(), welcomeMessage.size(), 0);
// 接收客户端的命令
std::string command;
if (!receiveCommand(clientSocket, command)) {
std::cerr << "Error receiving command." << std::endl;
closesocket(clientSocket);
continue;
}
// 判断命令是否为 EHLO
if (command.substr(0, 4) == "EHLO") {
// 发送 EHLO 响应
std::string response = "250-Hello gru.win\r\n"
"250-SIZE 52428800\r\n"
"250-8BITMIME\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-PIPELINING\r\n"
"250-CHUNKING\r\n"
"250 OK\r\n";
send(clientSocket, response.c_str(), static_cast<int>(response.size()), 0);
if (!receiveCommand(clientSocket, command)) {
std::cerr << "Error receiving command." << std::endl;
closesocket(clientSocket);
continue;
}
}
std::string sender;
std::string recipient;
while (command.length() >= 4)
{
switch (MAKE_INT32(command))
{
case MAKE_INT32("MAIL"):
// 收到 MAIL FROM 命令,获取发件人信息
sender = parseSender(command);
break;
// 判断下一个命令是否为 RCPT TO
case MAKE_INT32("RCPT"):
// 获取收件人信息
recipient = parseRecipient(command);
break;
//const std::string welcomeMessage = "250 OK\r\n";
//send(clientSocket, welcomeMessage.c_str(), welcomeMessage.size(), 0);
// 接收下一个命令
// 判断下一个命令是否为 DATA
case MAKE_INT32("DATA"):
// 发送接收数据的响应
std::string dataResponse = "354 Start mail input; end with <CRLF>.<CRLF>\r\n";
send(clientSocket, dataResponse.c_str(), static_cast<int>(dataResponse.size()), 0);
// 接收邮件内容
std::string emailContent;
while (true) {
char buffer[BUFFER_SIZE];
int bytesRead = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0);
if (bytesRead <= 0) {
std::cerr << "Error receiving email content." << std::endl;
break;
}
buffer[bytesRead] = '\0';
emailContent += buffer;
// 判断是否接收完毕
if (emailContent.length() >= 5 && emailContent.substr(emailContent.length() - 5) == "\r\n.\r\n") {
break;
}
}
// 保存邮件到文件
saveEmailToFile(emailContent, sender, recipient);
break;
case MAKE_INT32("QUIT"):
break;
default:
break;
}
// 发送接收成功的响应
std::string response = "250 OK\r\n";
send(clientSocket, response.c_str(), static_cast<int>(response.size()), 0);
if (!receiveCommand(clientSocket, command)) {
std::cerr << "Error receiving command." << std::endl;
closesocket(clientSocket);
break;
}
}
// 关闭客户端连接
closesocket(clientSocket);
std::cout << "Client disconnected." << std::endl;
}
// 关闭服务器套接字
closesocket(serverSocket);
// 清理 Winsock
WSACleanup();
return 0;
}
将接收到的邮件保存到txt文本文件,用来接收验证码超级给力,纯中文与chatgpt3.5交互获得的代码,真没想到中文编程会以这种方式实现 |
|