smtp协议c语言,编写SMTP协议邮箱发信(QQ邮箱为例)

语言:C/C++

编程软件:VS2015

字符集:ASCII码

主要使用:Winsock套接字库

说明:这里拿QQ邮箱做为例子,其他126、163邮箱也一样可以,大同小异。

首先你要知道QQ提供的用于管理邮箱SMTP服务器监听端口和服务器域名或IP地址。

一、如何查询QQ的SMTP服务器:

QQ提供的SMTP服务器

从上面可以知道:

SMTP服务器:smtp.qq.com

监听端口号:465、587.(使用25端口也行)

二、打开QQ邮箱的SMTP/POP3服务:

打开QQ邮箱-->设置-->账户-->找到以下选项:

POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务

点击开启“POP3/SMTP服务”选项.

这时,QQ会提供一个字符串密钥(如:QKBE KQQW UDVC BJAB),这个密钥充当着登录密码的作用.

如果你获取密钥后,修改了QQ密码,那么密钥会无效,那就要重新获取.

如果你早已打开了该SMTP服务,但没有密钥,关闭重新打开服务.

得到密钥:QKBE KQQW UDVC BJAB  实际使用密钥时:qkbekqqwudvcbjab

三、上传QQ账户和密钥时,要转换成“Base64编码”再上传给QQ的SMTP服务器:

使用以下的EncodeBase64函数即可将它们转换成Base64编码:

struct Base64Date6

{

unsigned int d4 : 6;

unsigned int d3 : 6;

unsigned int d2 : 6;

unsigned int d1 : 6;

};//转换为Base64编码函数

void EncodeBase64(char *dbuf, char *buf128, int len)

{   //参数1:接收新Base64编码的缓冲区   参数2:要转换的字符串缓冲区  参数3:要转换的字符串长度

struct Base64Date6 *ddd = NULL;

int           i = 0;

char          buf[256] = { 0 };

char          *tmp = NULL;

char          cc = ' ';

memset(buf, 0, 256);

strcpy_s(buf, 256, buf128);

for (i = 1; i d1);

dbuf[(i - 1) * 4 + 1] = ConvertToBase64((unsigned int)ddd->d2);

dbuf[(i - 1) * 4 + 2] = ConvertToBase64((unsigned int)ddd->d3);

dbuf[(i - 1) * 4 + 3] = ConvertToBase64((unsigned int)ddd->d4);

}

if (len % 3 == 1)

{

tmp = buf + (i - 1) * 3;

cc = tmp[2];

tmp[2] = tmp[0];

tmp[0] = cc;

ddd = (struct Base64Date6 *)tmp;

dbuf[(i - 1) * 4 + 0] = ConvertToBase64((unsigned int)ddd->d1);

dbuf[(i - 1) * 4 + 1] = ConvertToBase64((unsigned int)ddd->d2);

dbuf[(i - 1) * 4 + 2] = '=';

dbuf[(i - 1) * 4 + 3] = '=';

}

if (len % 3 == 2)

{

tmp = buf + (i - 1) * 3;

cc = tmp[2];

tmp[2] = tmp[0];

tmp[0] = cc;

ddd = (struct Base64Date6 *)tmp;

dbuf[(i - 1) * 4 + 0] = ConvertToBase64((unsigned int)ddd->d1);

dbuf[(i - 1) * 4 + 1] = ConvertToBase64((unsigned int)ddd->d2);

dbuf[(i - 1) * 4 + 2] = ConvertToBase64((unsigned int)ddd->d3);

dbuf[(i - 1) * 4 + 3] = '=';

}

return;

}

//辅助计算的函数

char ConvertToBase64(char uc)

{

if (uc 

{

return 'A' + uc;

}

if (uc 

{

return 'a' + (uc - 26);

}

if (uc 

{

return '0' + (uc - 52);

}

if (uc == 62)

{

return '+';

}

return '/';

}

四、开始编写:

通信步骤:

1、连接QQ的SMTP服务器  //2开始,每一个命令都要接收一个服务器响应码

2、编辑邮件内容和标题格式:

From:

头文件:#pragma once

#include#include#include#includeusing namespace std;

#pragma comment(lib, "Ws2_32.lib")

源文件:#include "头文件"

//将要发送的邮件内容                                                   (这里的From和To只用于在邮件上显示的)

char EmailContents[] = "From:rn"                    //这里只是说明发件人(QQ会检查,标记为垃圾邮件而发送失败)

"To:;rn" //这里只是说明收件人(可以乱填的)

"Subject:第一封测试邮件rnrn"                 //邮件标题

"Hello World, Hello Email!";                   //邮件内容

//上面的EncodeBase64函数这里就不列出来了

//上面的ConvertToBase64函数这里就不列出来了

int main()

{

system("color 4e");

char buf[1500];

char login[128];

char pass[128];

ZeroMemory(buf, 1500);

ZeroMemory(login, 128);

ZeroMemory(pass, 128);

//加载Winsock库

WSADATA WSAData;

WSAStartup(MAKEWORD(2, 2), &WSAData);

//创建TCP套接字

SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);

SOCKADDR_IN dest;

//端口25

dest.sin_port = htons(25);//587也可以

dest.sin_family = AF_INET;

//获取smtp.qq.com服务器域名所代表的IP地址

hostent* hptr = gethostbyname("smtp.qq.com");

memcpy(&dest.sin_addr.S_un.S_addr, hptr->h_addr_list[0], hptr->h_length);

//连接腾讯的邮件SMTP服务器

int ok = connect(sockfd, (SOCKADDR*)&dest, sizeof(SOCKADDR));

if (ok != 0)

exit(0);

//用于向服务器标明用户身份,可以为发件人的服务器域名或者主机名

sprintf_s(buf, 1500, "EHLO Aaron-PCrn");

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//开启安全传输层协议(TLS)

//这里的STARTTLS空格的后面要加一些字符才行,这里不是很懂,但这就可以了.

sprintf_s(buf, 1500, "STARTTLS arn");

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//邮箱认证,发送该命令后依次发送邮箱账号和密码(账号密码均使用Base64编码)

sprintf_s(buf, 1500, "AUTH LOGINrn");

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//发送QQ账号

ZeroMemory(buf, 1500);

sprintf_s(buf, 1500, "3093575@qq.com");//你的邮箱账号

//将QQ账号转换为Base64编码再发送

EncodeBase64(login, buf, strlen(buf));

sprintf_s(buf, 1500, "%srn", login);

send(sockfd, buf, strlen(buf), 0);

cout <

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//发送密钥(相当于QQ密码,在上面的步骤得到)

sprintf_s(buf, 1500, "qkbekqqwudvcbjab");

//将密钥转换为Base64编码再发送

EncodeBase64(pass, buf, strlen(buf));

sprintf_s(buf, 1500, "%srn", pass);

send(sockfd, buf, strlen(buf), 0);

cout <

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//发送MAIL FROM命令指定发件人

ZeroMemory(buf, 1500);

sprintf_s(buf, 1500, "MAIL FROM:rn");

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//发送一个或多个RCPT TO命令指定收件人

sprintf_s(buf, 1500, "RCPT TO:rn", "109333576@qq.com"); //109333576@qq.com为收件人1

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

sprintf_s(buf, 1500, "RCPT TO:rn", "509333576@qq.com"); //509333576@qq.com为收件人2

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//发送一个DATA命令表示准备开始发送邮件内容

sprintf_s(buf, 1500, "DATArn");

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//发送邮件内容,格式:以rn.rn作为结束标记

sprintf_s(buf, 1500, "%srn.rn", EmailContents);    //邮件的内容

send(sockfd, buf, strlen(buf), 0);

//接收服务器响应

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//使用QUIT命令退出

sprintf_s(buf, 1500, "QUITrn");

send(sockfd, buf, strlen(buf), 0);

ZeroMemory(buf, 1500);

recv(sockfd, buf, 1500, 0);

cout <

//清理工作

closesocket(sockfd);

WSACleanup();

getchar();

return 0;

}

补充说明:想要知道其中细节的问题,需要学习SMTP协议,例如SMTP命令以及SMTP服务器三位数字响应码

缺点:

1、360会报告有第三方软件在使用邮箱发件.

2、明文传输账号和密码,有被人分析程序和抓包得到账号密码的风险。

与QQ的SMTP服务器交流过程:

F2tvXbTpsjJk3R1lkAi

测试发送结果:(我发送到了一个163邮箱、自己的QQ邮箱中)

hXuMJ9q0aP5wzEC5DE6OEhMXKQ

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值