- 邮件发送功能的初步实现
- 需要加载 ws2_32.dll文件
#pragma comment (lib, "ws2_32.lib")
- 参考相关结构体定义
struct hostent
{
char *h_name; //正式主机名
char **h_aliases; //主机别名
int h_addrtype; //主机IP地址类型:IPV4-AF_INET
int h_length; //主机IP地址字节长度,对于IPv4是四字节,即32位
char **h_addr_list; //主机的IP地址列表
};
#define h_addr h_addr_list[0] //保存的是IP地址
struct sockaddr_in
{
/*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/
short sin_family;
/*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/
unsigned short sin_port;
/*IP address in network byte order(Internet address)*/
struct in_addr sin_addr;
/*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/
unsigned char sin_zero[8];
};
- 下面是代码部分
// email_new.cpp : 定义控制台应用程序的入口点。
//
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include<iostream>
#include<stdio.h>
#include<winsock2.h>
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
using namespace std;
// 连接服务器
SOCKET connect_server(char *host, int port); // (swtp.163.com, 25)
// 断开连接
void disconnect(SOCKET c);
void send_msg(SOCKET c, char *msg);
void recv_msg(SOCKET c);
char* base64_encode(const char* data, int data_len);
const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
SOCKET connect_server(char *host, int port)
{
WSADATA wd;
int ret = 0;
SOCKET c;
SOCKADDR_IN saddr; // ??结构体
struct hostent *pHostent;
ret = WSAStartup(MAKEWORD(2, 2), &wd);
if (ret != 0)
{
return 0;
}
if (HIBYTE(wd.wVersion) != 2 || LOBYTE(wd.wVersion) != 2)
{
cout << "初始化失败" << endl;
WSACleanup();
return 1;
}
c = socket(AF_INET, SOCK_STREAM, 0);
pHostent = gethostbyname(host); //获取IP地址,解析
saddr.sin_addr.S_un.S_addr = *((unsigned long*)pHostent->h_addr_list[0]);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
connect(c, (SOCKADDR*)&saddr, sizeof(SOCKADDR));
return c;
}
void disconnect(SOCKET c)
{
closesocket(c);
WSACleanup();
}
void recv_msg(SOCKET c)
{
char text[BUFSIZ];
strnset(text, '\0', BUFSIZ);
recv(c, text, BUFSIZ, 0);
cout << endl << "recv:" << text << endl;
}
void send_msg(SOCKET c, char *msg)
{
cout << endl << "send:" << msg << endl;
send(c, msg, strlen(msg), 0);
}
char *base64_encode(const char* data, int data_len)
{
//int data_len = strlen(data);
int prepare = 0;
int ret_len;
int temp = 0;
char *ret = NULL;
char *f = NULL;
int tmp = 0;
char changed[4];
int i = 0;
ret_len = data_len / 3;
temp = data_len % 3;
if (temp > 0)
{
ret_len += 1;
}
ret_len = ret_len * 4 + 1;
ret = (char *)malloc(ret_len);
if (ret == NULL)
{
printf("No enough memory.\n");
exit(0);
}
memset(ret, 0, ret_len);
f = ret;
while (tmp < data_len)
{
temp = 0;
prepare = 0;
memset(changed, '\0', 4);
while (temp < 3)
{
//printf("tmp = %d\n", tmp);
if (tmp >= data_len)
{
break;
}
prepare = ((prepare << 8) | (data[tmp] & 0xFF));
tmp++;
temp++;
}
prepare = (prepare << ((3 - temp) * 8));
//printf("before for : temp = %d, prepare = %d\n", temp, prepare);
for (i = 0; i < 4; i++)
{
if (temp < i)
{
changed[i] = 0x40;
}
else
{
changed[i] = (prepare >> ((3 - i) * 6)) & 0x3F;
}
*f = base[changed[i]];
//printf("%.2X", changed[i]);
f++;
}
}
*f = '\0';
return ret;
}
int main(void)
{
char sendbuf[BUFSIZ], recvbuf[BUFSIZ], recv_email[BUFSIZ], subject[BUFSIZ], content[BUFSIZ], email[200], pass[200];
char *pstr = NULL;
char *host = "smtp.163.com";
int port = 25;
SOCKET c;
c = connect_server(host, port);
recv_msg(c); // 接收服务器的数据
send_msg(c, "helo 163\r\n"); //跟服务器打招呼
recv_msg(c); // 接收服务器的数据
send_msg(c, "auth login\r\n"); //告诉服务器要登陆
recv_msg(c); // 接收服务器的数据
//提示用户输入邮箱地址
cout << "---onload email---" << endl << "Address:";
cin >> email;
cout << "Password:";
cin >> pass;
//加密邮箱地址
pstr = base64_encode(email, strlen(email));
strcpy(sendbuf, pstr);
strcat(sendbuf, "\r\n\0"); //加回车换行符号 ,\0字符串结束标志
send_msg(c, sendbuf);
recv_msg(c); //接收返回内容并显示
free(pstr); //释放base64加密中分配的内存
//加密邮箱密码
pstr = base64_encode(pass, strlen(pass));
strcpy(sendbuf, pstr);
strcat(sendbuf, "\r\n\0");
send_msg(c, sendbuf);
recv_msg(c);
free(pstr); //释放base64加密中分配的内存
//告诉服务器发件人是谁
strcpy(sendbuf, "mail from:<");
strcat(sendbuf, email);
strcat(sendbuf, ">");
strcat(sendbuf, "\r\n\0");
send_msg(c, sendbuf);
recv_msg(c);
//告诉服务器收件人是谁
cout << "destinate address:";
cin >> recv_email;
strcpy(sendbuf, "rcpt to:<");
strcat(sendbuf, recv_email);
strcat(sendbuf, ">");
strcat(sendbuf, "\r\n\0");
send_msg(c, sendbuf);
recv_msg(c);
//邮件内容
send_msg(c, "data\r\n");
recv_msg(c);
cout << "title:";
cin >> subject; //cin遇见空格结束
cout << endl;
cout << "content:";
cin >> content;
//选填发件人
strcpy(sendbuf, "From: ");
strcat(sendbuf, email);
strcat(sendbuf, "\n");
strcpy(sendbuf, "To: ");
strcat(sendbuf, recv_email);
strcat(sendbuf, "\n");
//发送标题和内容
strcat(sendbuf, "subject:");
strcat(sendbuf, subject);
strcat(sendbuf, "\r\n\r\n");
strcat(sendbuf, content);
strcat(sendbuf, "\r\n.\r\n\0");
send_msg(c, sendbuf);
recv_msg(c);
disconnect(c);
cout << "succeed arrive to:" << recv_email << endl;
getchar();
}