用 C++ 发送带有附件的电子邮件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7298762/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Send email with attachment in C++
提问by Mohammad Salman
I am working on a project in C++, which includes a feature of sending information to someone as 'email attachment'.
我正在使用 C++ 开发一个项目,其中包括将信息作为“电子邮件附件”发送给某人的功能。
Everything is done except this 'email' thing. I do not know how to make this program able to send an email without using any email client or opening a browser. I have searched a lot over the internet but could not find any working thing (I do not have any knowledge of socket, Winsock, etc).
除了这个“电子邮件”之外,一切都完成了。我不知道如何使该程序能够在不使用任何电子邮件客户端或打开浏览器的情况下发送电子邮件。我寻觅了很多在互联网上,但无法找到任何工作的事情(我没有任何知识socket,Winsock等等)。
回答by Davide Piras
I am not sure I agree with what you are doing in spying the users on what they do, but regardless here is some C++ code useful to send emails:
我不确定我是否同意您在监视用户所做的事情方面所做的事情,但无论如何这里有一些 C++ 代码可用于发送电子邮件:
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <fstream.h>
#include <iostream.h>
#include <windows.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
// Insist on at least Winsock v1.1
const VERSION_MAJOR = 1;
const VERSION_MINOR = 1;
#define CRLF "\r\n" // carriage-return/line feed pair
void ShowUsage(void)
{
cout << "Usage: SENDMAIL mailserv to_addr from_addr messagefile" << endl
<< "Example: SENDMAIL smtp.myisp.com [email protected] [email protected] message.txt" << endl;
exit(1);
}
// Basic error checking for send() and recv() functions
void Check(int iStatus, char *szFunction)
{
if((iStatus != SOCKET_ERROR) && (iStatus))
return;
cerr << "Error during call to " << szFunction << ": " << iStatus << " - " << GetLastError() << endl;
}
int main(int argc, char *argv[])
{
int iProtocolPort = 0;
char szSmtpServerName[64] = "";
char szToAddr[64] = "";
char szFromAddr[64] = "";
char szBuffer[4096] = "";
char szLine[255] = "";
char szMsgLine[255] = "";
SOCKET hServer;
WSADATA WSData;
LPHOSTENT lpHostEntry;
LPSERVENT lpServEntry;
SOCKADDR_IN SockAddr;
// Check for four command-line args
if(argc != 5)
ShowUsage();
// Load command-line args
lstrcpy(szSmtpServerName, argv[1]);
lstrcpy(szToAddr, argv[2]);
lstrcpy(szFromAddr, argv[3]);
// Create input stream for reading email message file
ifstream MsgFile(argv[4]);
// Attempt to intialize WinSock (1.1 or later)
if(WSAStartup(MAKEWORD(VERSION_MAJOR, VERSION_MINOR), &WSData))
{
cout << "Cannot find Winsock v" << VERSION_MAJOR << "." << VERSION_MINOR << " or later!" << endl;
return 1;
}
// Lookup email server's IP address.
lpHostEntry = gethostbyname(szSmtpServerName);
if(!lpHostEntry)
{
cout << "Cannot find SMTP mail server " << szSmtpServerName << endl;
return 1;
}
// Create a TCP/IP socket, no specific protocol
hServer = socket(PF_INET, SOCK_STREAM, 0);
if(hServer == INVALID_SOCKET)
{
cout << "Cannot open mail server socket" << endl;
return 1;
}
// Get the mail service port
lpServEntry = getservbyname("mail", 0);
// Use the SMTP default port if no other port is specified
if(!lpServEntry)
iProtocolPort = htons(IPPORT_SMTP);
else
iProtocolPort = lpServEntry->s_port;
// Setup a Socket Address structure
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = iProtocolPort;
SockAddr.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
// Connect the Socket
if(connect(hServer, (PSOCKADDR) &SockAddr, sizeof(SockAddr)))
{
cout << "Error connecting to Server socket" << endl;
return 1;
}
// Receive initial response from SMTP server
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() Reply");
// Send HELO server.com
sprintf(szMsgLine, "HELO %s%s", szSmtpServerName, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() HELO");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() HELO");
// Send MAIL FROM: <[email protected]>
sprintf(szMsgLine, "MAIL FROM:<%s>%s", szFromAddr, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() MAIL FROM");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() MAIL FROM");
// Send RCPT TO: <[email protected]>
sprintf(szMsgLine, "RCPT TO:<%s>%s", szToAddr, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() RCPT TO");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() RCPT TO");
// Send DATA
sprintf(szMsgLine, "DATA%s", CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() DATA");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() DATA");
// Send all lines of message body (using supplied text file)
MsgFile.getline(szLine, sizeof(szLine)); // Get first line
do // for each line of message text...
{
sprintf(szMsgLine, "%s%s", szLine, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() message-line");
MsgFile.getline(szLine, sizeof(szLine)); // get next line.
} while(MsgFile.good());
// Send blank line and a period
sprintf(szMsgLine, "%s.%s", CRLF, CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() end-message");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() end-message");
// Send QUIT
sprintf(szMsgLine, "QUIT%s", CRLF);
Check(send(hServer, szMsgLine, strlen(szMsgLine), 0), "send() QUIT");
Check(recv(hServer, szBuffer, sizeof(szBuffer), 0), "recv() QUIT");
// Report message has been sent
cout << "Sent " << argv[4] << " as email message to " << szToAddr << endl;
// Close server socket and prepare to exit.
closesocket(hServer);
WSACleanup();
return 0;
}
plenty of links on internet for a similar problem, I've found this:
互联网上有很多类似问题的链接,我发现了这个:
回答by datenwolf
Kudos to you for trying to code it yourself. This lifts you above the average script kiddy.
感谢您尝试自己编写代码。这使您高于平均脚本小子。
But shame yourself on spying on your brother. His private business is HIS business and none of yours.
但是为监视你的兄弟而感到羞耻。他的私人生意是他的生意,与你无关。
Also, if your brother is only a bit clever, he'll not fall for some executable email attachment. Additionally, most email programs and webmailers will warn against executing this thing. If you were to make this foolproof you'd need to find vulnerabilities in the email client(s) used, to inject code, best way to go is attacking image loader and compression routines, but you'll have to find a 0day ideally, otherwise those exploits may have been patched before you get your spyware out. Some topics you may want to read upon are
此外,如果你的兄弟只是有点聪明,他也不会爱上某些可执行的电子邮件附件。此外,大多数电子邮件程序和网络邮件程序会警告不要执行此操作。如果你要做到这一点,你需要找到所使用的电子邮件客户端中的漏洞,注入代码,最好的方法是攻击图像加载器和压缩例程,但理想情况下你必须找到一个 0day,否则,在您将间谍软件取出之前,这些漏洞可能已被修补。您可能想阅读的一些主题是
- stack overflow exploits
- heap spraying
- return based programming (used to counter W^X protection and mild implementations of address space randomization)
- 堆栈溢出漏洞利用
- 堆喷
- 基于返回的编程(用于对抗 W^X 保护和地址空间随机化的温和实现)
Sending email boils down to implement the SMTP protocol documented in http://www.faqs.org/rfcs/rfc821.html
发送电子邮件归结为实现http://www.faqs.org/rfcs/rfc821.html 中记录的 SMTP 协议
Technically one could send an email directly to a target server, but those will usually reject mails coming directly from dialup connections, since this is a cheap yet effective method to counter spam. So you better go over an MTA with proper MX records. Freemailers are your friend, Hotmail is very popular for this. However you'll have to implement SMTP-Auth then, too. Documented in http://www.faqs.org/rfcs/rfc2554.html
从技术上讲,人们可以将电子邮件直接发送到目标服务器,但那些通常会拒绝直接来自拨号连接的邮件,因为这是一种廉价但有效的反垃圾邮件方法。因此,您最好使用具有正确 MX 记录的 MTA。Freemailers 是您的朋友,Hotmail 非常受欢迎。但是,您也必须实现 SMTP-Auth。记录在http://www.faqs.org/rfcs/rfc2554.html
Of course instead of sending an email you could as well just upload a file somewhere. Or you could implement IMAP and use a IMAP capable freemailer to store the data in the IMAP Drafts directory.
当然,您也可以将文件上传到某个地方,而不是发送电子邮件。或者您可以实施 IMAP 并使用支持 IMAP 的免费邮件程序将数据存储在 IMAP 草稿目录中。
So if you manage to pull this off yourself, with your own code, then I think you deserve the success, but only if this doesn't involve third party libraries of malware construction kits (yes they exist).
因此,如果您设法使用自己的代码自行解决这个问题,那么我认为您应该获得成功,但前提是这不涉及恶意软件构建工具包的第三方库(是的,它们存在)。
回答by Minhas Kamal
A Working Solution for Sending Email Using cURL
使用cURL发送电子邮件的可行解决方案
Download cURLfrom here, and extract. Now, run the executable from C++ code using WinExec()from windows.h.
从这里下载cURL并解压。现在,使用from运行 C++ 代码中的可执行文件。WinExec()windows.h
Here is a demonstration for Gmail:
这是 Gmail 的演示:
#include <windows.h>
int main(void){
char* command = "curl smtp://smtp.gmail.com:587 -v --mail-from \"[email protected]\" --mail-rcpt \"[email protected]\" --ssl -u [email protected]:PASSWORD -T \"ATTACHMENT.FILE\" -k --anyauth";
WinExec(command, SW_HIDE);
return 0;
}
Place curl.exein the same directory. Enter your email address and password in the command. Here, message is saved in a text file (ATTACHMENT.FILE).
将curl.exe放在同一目录中。输入您的电子邮件地址和密码command。此处,消息保存在文本文件 (ATTACHMENT.FILE) 中。
Caution:The commandmay not support some special characters (like- &).
注意:在command可能不支持一些特殊字符(喜欢- &)。
For more in-depth application, you may use libcurl.
对于更深入的应用,您可以使用 libcurl。
回答by Shaun07776
indy also has components for sending emails via SMTP
indy 也有通过 SMTP 发送电子邮件的组件
TIdSMTP *IdSMTP1 = new TIdSMTP(this);
IdSMTP1->Host = "myhost";
IdSMTP1->Port = 25;
TIdMessage *MSG = new TIdMessage(this);
MSG->Clear();
MSG->From->Address = "[email protected]";
MSG->From->Name = "Someone";
MSG->Subject = "Spy Email";
MSG->Recipients->EMailAddresses = "[email protected]";
MSG->Body->Text = "your being watched ";
IdSMTP1->Connect();
IdSMTP1->Send(MSG);
IdSMTP1->Disconnect(true);
delete MSG;
delete IdSMTP1;
and it comes installed with Builder now
它现在随 Builder 一起安装

