电子邮件客户端程序设计与实现

今天是课程设计的第二天,这次课程设计我只打算做五个实验,这是第二个。

设计步骤

调试过程

首先要配置测试使用的QQ邮箱,不然会出现服务器响应为:Error: need EHLO and AUTH first !”问题。

配置qq邮箱的步骤及填写授权码

1、首先在QQ邮箱当中开启“POP3/SMTP服务”

开启“POP3/SMTP服务”

2、开启后点击下方生成授权码

3、使用base64加密账号与密码

4、使用base64加密后的授权码替代登陆密码,如下图所示:

使用base64加密后的账号与密码填写

5.尝试调试程序

调试成功

设计结果及结果分析

查看邮件:

查看邮件

发送邮件:

发送邮件

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <iostream>
#include <string>
#include <WinSock2.h>
#include <stdio.h>
#include <unistd.h>

using namespace std;
#pragma comment(lib, "ws2_32.lib") /*链接ws2_32.lib动态链接库*/

void mail(){
char buff[50000]; //收到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);
SOCKADDR_IN addrServer; //服务端地址
HOSTENT *pHostent;//hostent是host entry的缩写,该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表
SOCKET sockClient; //客户端的套接字
/*
使用 MAIL 命令指定发送者
使用 RCPT 命令指定接收者,可以重复使用RCPT指定多个接收者
*/
cout << "你想查看邮件还是发邮件?\n\t1.查看邮箱\n\t2.发送邮件\n";
int call;
cin >> call;
if (call == 2)
{
sockClient = socket(AF_INET, SOCK_STREAM, 0); //建立socket对象
pHostent = gethostbyname("smtp.qq.com"); //得到有关于域名的信息,链接到qq邮箱服务器
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)); //向服务器发送请求
buff[recv(sockClient, buff, 500, 0)] = '\0';
/*
登录邮件服务器
*/
message = "ehlo qq.com\r\n";
send(sockClient, message.c_str(), message.length(), 0); //发送ehlo命令
buff[recv(sockClient, buff, 500, 0)] = '\0'; //接收返回值
// cout <<"1" << buff << endl;

message = "auth login\r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout <<"2" << buff << endl;
/*
发送base64加密的用户名、密码
*/
message = "MTAyNTE0MjkzMg==\r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout <<"3" << buff << endl;

message = "bXhkeXd1ZnVhcHVnYmVlag==\r\n";/**/
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout <<"4" << buff << endl;

/*
Author:hyn
Time:2021.12.28
*/

string mail;
cout << "请输入收件人邮箱:";
cin >> mail;
//1025142932@qq.com
message = "MAIL FROM:<1025142932@qq.com> \r\nRCPT TO:<";
message.append(mail);
message.append("> \r\n");
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
cout <<"5" << buff << endl;
buff[recv(sockClient, buff, 500, 0)] = '\0';
/*
使用 DATA 命令告诉服务器要发送邮件内容
*/
message = "DATA\r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout <<"6" << buff << endl;
message = "From: 1025142932@qq.com\r\nTo: " + mail + "\r\nsubject:";
cout << "主题:";
cin >> subject;
message.append(subject);
message.append("\r\n\r\n");
cout << "内容:";
cin >> info;
message.append(info);
message.append("\r\n.\r\n");

send(sockClient, message.c_str(), message.length(), 0);
// cout <<"7" << buff << endl;
message = "QUIT\r\n";
send(sockClient, message.c_str(), message.length(), 0);
buff[recv(sockClient, buff, 500, 0)] = '\0';
// cout <<"8" << buff << endl;

cout << "发送成功!" << endl;
//system("pause");
}
if (call == 1)
{
sockClient = socket(AF_INET, SOCK_STREAM, 0); //建立socket对象
const char *host_id = "pop3.126.com";
pHostent = gethostbyname("pop.qq.com");
int port = 110;
addrServer.sin_addr.S_un.S_addr = *((DWORD *) pHostent->h_addr_list[0]); //得到smtp服务器的网络字节序的ip地址
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(port); //连接端口110
err = connect(sockClient, (SOCKADDR *) &addrServer, sizeof(SOCKADDR)); //向服务器发送请求
buff[recv(sockClient, buff, 500, 0)] = '\0';

message = "user 1025142932@qq.com\r\n";
send(sockClient, message.c_str(), message.length(), 0); //发送账号
buff[recv(sockClient, buff, 500, 0)] = '\0'; //接收返回值
// std::cout << "Client : send name \nServer:"
// << buff << std::endl;

message = "pass mxdywufuapugbeej\r\n";
send(sockClient, message.c_str(), message.length(), 0); //发送授权码
buff[recv(sockClient, buff, 500, 0)] = '\0'; //接收返回值
//std::cout << "Client : send pass \nServer:"
// << buff << std::endl;

message = "stat\r\n";
send(sockClient, message.c_str(), message.length(), 0); //发送状态
buff[recv(sockClient, buff, 500, 0)] = '\0'; //接收返回值
// sleep(1);
//std::cout << "Client : send stat \nServer : "
// << buff << std::endl;

message = "list\r\n";
send(sockClient, message.c_str(), message.length(), 0); //发送状态
buff[recv(sockClient, buff, 50000, 0)] = '\0'; //接收返回值
// sleep(1);
cout << "Client : send list \nServer :"
<< buff << endl;
while(1)
{
int n,option;
cout << "你先想查看那一封邮件?输入序号"
<< endl;
cin >> n;
message = "retr " + to_string(n) + "\r\n";

send(sockClient, message.c_str(), message.length(), 0); //发送状态
// sleep(1);
cout << "Client : send retr (...) \n";

buff[recv(sockClient, buff, 50000, 0)] = '\0'; //接收返回值
cout << "Server :" << buff << endl;

cout<<"1.继续查看 2.退出";
cin>>option;
if(option == 1)
;
else
break;
}
}
}

int main()
{
while(1){
mail();
}
}