C++实现 电子邮件客户端程序(简易版)
#Windows操作系统下
- 用命令行工具实现发送邮件(编程前工作)
步骤:
1.telnet连接服务器(以用QQ邮箱向网易邮箱发送邮件为例,端口号25)
2.返回220 说明连接成功
3.ehlo发送用户名(QQ邮箱用户名默认是QQ号)
返回了一堆登录方式码
4.常用auth login登录方式
返回334,成功
5.输入base64编码后的QQ邮箱账号和密码(为了保护数据)
在线转码:http://www1.tc711.com/tool/BASE64.htm
(马赛克部分分别是账号,密码)
返回 334,235表示成功
6.输入发件地址和收件地址
返回250 OK为成功
7.data命令表示要开始输入发送的数据了
按照邮件格式:
from:<发件地址>
to:<收件地址>
subject:主题
......内容......
. //输入一个点,表示内容结束了,回车即发送该邮件
8.查看163邮箱是否接收到邮件
- 代码实现
#include <iostream> #include <string> #include <WinSock2.h> //适用平台 Windows using namespace std; #pragma comment(lib, "ws2_32.lib") /*链接ws2_32.lib动态链接库*/ int main()
{
char buff[500]; //recv函数返回的结果
string message;
string info;
string subject;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 1);
//WSAStarup,即WSA(Windows SocKNDs Asynchronous,Windows套接字异步)的启动命令
int err = WSAStartup(wVersionRequested, &wsaData);
// cout << "WSAStartup:" << err << endl;
SOCKET sockClient; //客户端的套接字
sockClient = socket(AF_INET, SOCK_STREAM, 0); //建立socket对象
HOSTENT* pHostent;//hostent是host entry的缩写,该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表
pHostent = gethostbyname("smtp.qq.com"); //得到有关于域名的信息,链接到qq邮箱服务器
SOCKADDR_IN addrServer; //服务端地址
addrServer.sin_addr.S_un.S_addr = *((DWORD *)pHostent->h_addr_list[0]); //得到smtp服务器的网络字节序的ip地址
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(25); //连接端口25
//int connect (SOCKET s , const struct sockaddr FAR *name , int namelen ); //函数原型
err = connect(sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR)); //向服务器发送请求
//cout << "connect:" << err << endl;
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout << "connect:" << buff << endl;
/*
登录邮件服务器
*/
message = "ehlo qq.com\r\n";
send(sockClient, message.c_str(), message.length(), 0); //发送ehlo命令
buff[recv(sockClient, buff, 500, 0)] = '\0'; //接收返回值
// cout << "helo:" << buff << endl; //输出返回值
message = "auth login \r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
//cout << "auth login:" << buff << endl;
/*
发送base64加密的用户名、密码
*/
message = "XXXXXXXX\r\n"; //base64 编码的用户名
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
//cout << "usrname:" << buff << endl;
message = "XXXXXXXXXXXX\r\n";//base64 编码的密码
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout << "password:" << buff << endl;
/*
使用 MAIL 命令指定发送者
使用 RCPT 命令指定接收者,可以重复使用RCPT指定多个接收者
*/
string mail;
cout << "输入收件人邮箱:";
cin >> mail;
message = "MAIL FROM:<XXX@qq.com> \r\nRCPT TO:<";
// message = "MAIL FROM:<XXX@qq.com> \r\nRCPT TO:<XXX@163.com> \r\n";
message.append(mail);
message.append("> \r\n");
//cout << "message=" << message;
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout << "mail from: " << buff << endl;
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout << "rcpt to: " << buff << endl;
/*
使用 DATA 命令告诉服务器要发送邮件内容
*/
message = "DATA\r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
//cout << "data: " << buff << endl;
message = "From: XXX@qq.com\r\n\
To: XXX@163.com\r\n\
subject:";
cout<<"主题:";
cin>>subject;
message.append(subject);
message.append("\r\n\r\n");
cout<<"内容:";
cin>>info;
message.append(info);
message.append("\r\n.\r\n");
// cout<<"message="<<message;
/*message = "From: XXX@qq.com\r\n\
To: XXX@163.com\r\n\
subject: test\r\n\r\n\
Just a test!\r\n\
your friend\r\n\
Ctt\r\n.\r\n"; //注意subject关键字与正文之间要有一个空行*/
send(sockClient, message.c_str(), message.length(), 0);
message = "QUIT\r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
//cout << "QUIT:" << buff << endl;
cout << "发送成功!"<<endl;
system("pause");
}
运行界面
查看邮箱(有bug,主题没有正确设定)
- 常见报错的解决方式与注意事项:
1.保持网络畅通
2.报错502 有时候指令不能被识别,就重新输入一次指令,再试