以前以为协议非常高神,但做了这个之后发现还好,没想象的那么艰难。

先要了解邮件的原理

再者就是上面2协议

可以先用telnet测试一下,以初步了解那2协议:http://hi.baidu.com/343243581/item/113c7212ced7e0e05e53b1d8

实现大致思想,SMTP,POP3相关介绍:http://www.doc88.com/p-929298657611.html

主要人家都讲得很好很详细了,天冷,我也懒得打字了。

/*这里面放一些公共的头文件*/

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h> //字节序转换函数
#include <netdb.h> //地址查询 extern int BUFFMAX;
extern void recvCntInfo(int cnt,char thisBuff[]);

头文件

#include <stdio.h>

/*下面定义常量*/
const int BUFFMAX=; //接受消息缓冲区大小 /*处理的函数*/ void recvCntInfo(int cnt,char thisBuff[])
{
if(cnt==-)
{
printf("recv出错,退出程序!\n");
exit();
}
else if(cnt==)
{
printf("无可用消息或对方已经按序结束!\n");
}
else
{
thisBuff[cnt]='\0';
printf("发回:%s\n",thisBuff);
}
}

一点自定义东西

#include "myHead.h"

static const char* SEND_DES="smtp.163.com";  //访问163邮箱
static const int SEND_PORT=; //smtp的端口号 /*下面定义邮箱命令的标号*/
static const int HELO=;
static const int AUTHLOGIN=;
static const int USERNAME=;
static const int PASSWORD=;
static const int MAILFROM=;
static const int RCPTTO=;
static const int DATA=;
static const int CONTENT=;
static const int QUIT=; int main(void)
{
/*主机信息*/
struct hostent* host; //这里面的地址采用网络字节序
if((host=gethostbyname(SEND_DES))==NULL) //获得域名对应的主机信息
{
printf("gethostbyname 错误!程序退出!\n");
exit();
}
printf("\n域名对应主机名:%s\n",host->h_name); /*创建socket*/
int sockfd=socket(AF_INET,SOCK_STREAM,); //ipv4 tcp
if(sockfd==-)
{
printf("socket 创建错误!\n");
exit();
}
printf("socket 创建成功!\n"); /*目的地地址信息*/
struct sockaddr_in serAddr;
serAddr.sin_family=AF_INET; //ipv4
serAddr.sin_port=htons(SEND_PORT); //端口号变换成网络字节须
serAddr.sin_addr=*((struct in_addr *)host->h_addr);//server ip 注意这里的细节东西
bzero(&(serAddr.sin_zero),); //加0以成功转化为struct sockaddr类型 /*下面进行操作,共分为三大步:建立连接,对话及发送邮件信息,关闭连接*/
char buff[BUFFMAX];
int cnt; /*第一步:建立连接*/
printf("\n请求:连接IP地址 %s 端口 %d 的服务.... ",SEND_DES,SEND_PORT);
if((connect(sockfd,(struct sockaddr*)&serAddr,sizeof(struct sockaddr)))==-) //结构体强制转换
{
printf("connect 错误!\n");
exit();
}
printf("connect 成功!\n"); cnt=recv(sockfd,buff,BUFFMAX,); //接受请求这个端口后的回答
recvCntInfo(cnt,buff); /*第二步:对话及发送邮件信息*/ /*初始化每次对话要发送的信息*/
char* msg[]={""}; //分别对应每次的发送消息
msg[HELO]="helo 163\n"; //打招呼
msg[AUTHLOGIN]="auth login\n"; //登录命令
msg[USERNAME]="MTU2MDg0MTk0NTA=\n"; //已经转化为base64编码方式
msg[PASSWORD]="MjY2MTQ3\n"; //base64编码方式
msg[MAILFROM]="MAIL FROM:<15608419450@163.com>\n"; //发邮件人
msg[RCPTTO]="RCPT TO:<1150614705@qq.com>\n"; //预期接受人
msg[DATA]="data\n"; //准备发送邮件数据的命令
msg[CONTENT]="FROM:15608419450@163.com\nTO:1150614705@qq.com\nSubject:163 to qq\n\nfffdfdfddddfdd HELLO! 163 TO QQ EMAIL!\nNow it is 20:44\n.\n";
msg[QUIT]="quit\n"; /*下面开始发送各个消息*/
int step;
for(step=HELO;step<=CONTENT;step++) //每个step对应一次发送消息及接受消息的对话
{
printf("< %d > 发送信息如下:\n%s",step,msg[step]);
if((send(sockfd,msg[step],strlen(msg[step]),))==-) //注意这里一定要用strlen()而不是sizeof....
{
printf("send 出错!\n");
}
printf("send 成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,);
recvCntInfo(cnt,buff);
} /*第三步,退出程序*/
printf("邮件已成功从此客户端发送到邮件服务器!现在发送退出连接邮件服务器消息:\n");
if((send(sockfd,msg[QUIT],strlen(msg[QUIT]),))==-) //注意这里一定要用strlen()而不是sizeof....
{
printf("quit 发送出错!\n");
}
printf("quit 发送成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,);
recvCntInfo(cnt,buff);
}

发送程序

#include "myHead.h"

const char* GET_DES="pop3.163.com";
const int GET_PORT=; /*下面定义常量,其实标号不重要,只是当作下标,好记*/
static const int USR=;
static const int PSW=;
static const int QUIT=;
static const int LIST=;
static const int RETR=;
static const int DELE=;
static const int RSET=; static char* msg[]={""}; //装指向字符串的指针数组,仅此文件可见 int showOprate(void); //显示选择,返回输入项 int main(void)
{
/*初始化命令*/
msg[USR]="user 15608419450@163.com\n";
msg[PSW]="pass 266147\n";
msg[QUIT]="quit\n";
msg[LIST]="LIST\n";
msg[RSET]="RSET\n"; /*主机信息*/
struct hostent* host; //这里面的地址采用网络字节序
if((host=gethostbyname(GET_DES))==NULL) //获得域名对应的主机信息
{
printf("gethostbyname 错误!程序退出!\n");
exit();
}
printf("\n域名对应主机名:%s\n",host->h_name); /*创建socket*/
int sockfd=socket(AF_INET,SOCK_STREAM,); //ipv4 tcp
if(sockfd==-)
{
printf("socket 创建错误!\n");
exit();
}
printf("socket 创建成功!\n"); /*目的地地址信息*/
struct sockaddr_in serAddr;
serAddr.sin_family=AF_INET; //ipv4
serAddr.sin_port=htons(GET_PORT); //端口号变换成网络字节须
serAddr.sin_addr=*((struct in_addr *)host->h_addr);//server ip 注意这里的细节东西
bzero(&(serAddr.sin_zero),); //加0以成功转化为struct sockaddr类型 /*下面进行操作,共分为三个状态*/
char buff[BUFFMAX];
int cnt; /*一:认证状态*/
/*先连接主机*/
printf("\n请求:连接IP地址 %s 端口 %d 的服务.... ",GET_DES,GET_PORT);
if((connect(sockfd,(struct sockaddr*)&serAddr,sizeof(struct sockaddr)))==-) //结构体强制转换
{
printf("connect 错误!\n");
exit();
}
printf("connect 成功!\n"); cnt=recv(sockfd,buff,BUFFMAX,); //接受请求这个端口后的回答
recvCntInfo(cnt,buff); /*再输入用户名和密码*/
printf("下面登录邮箱:\n");
int step=USR;
for(;step<=PSW;step++) //其实就2步发送
{
printf("< %d > 发送信息如下:\n%s",step,msg[step]);
if((send(sockfd,msg[step],strlen(msg[step]),))==-) //注意这里一定要用strlen()而不是sizeof....
{
printf("send 出错!\n");
}
printf("send 成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,);
recvCntInfo(cnt,buff);
} /*二,处理状态*/
int choise=showOprate();
while(choise!=) //循环显示
{
/*下面处理输入的情况*/
if(choise>|choise<)
{
printf("选择 %d 为非法输入!请重新输入!\n",choise);
}
else
{
int sendChoise; //发送的消息对应的下标
int val; //命令的参数
char sendStr[]={'\0'}; //待发送的字符串 switch(choise)
{
case :sendChoise=LIST;break; //仅仅列表
case :{
printf("请输入要返回的邮件编号:");
scanf("%d",&val); //需要编号
getchar();
sprintf(sendStr,"%s%d%c","retr ",val,'\n'); //注意也要把换行符加进去
sendChoise=RETR;
msg[RETR]=sendStr;
break;
}
case :{
printf("请输入要删除的邮件编号");
scanf("%d",&val); //需要编号
getchar();
sprintf(sendStr,"%s%d%c","dele ",val,'\n');
sendChoise=DELE;
msg[DELE]=sendStr;
break;
}
case :sendChoise=RSET;break;
} printf("发送请求:\n%s",msg[sendChoise]);
if((send(sockfd,msg[sendChoise],strlen(msg[sendChoise]),))==-) //注意这里一定要用strlen()而不是sizeof....
{
printf("send 出错!\n");
}
printf("send 成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,);
recvCntInfo(cnt,buff);
} choise=showOprate();
} /*三,更新状态*/
printf("操作结束,现在发送退出连接邮件服务器消息以完成更新操作\n");
if((send(sockfd,msg[QUIT],strlen(msg[QUIT]),))==-) //注意这里一定要用strlen()而不是sizeof....
{
printf("quit 发送出错!\n");
}
printf("quit 发送成功! 等待回发....\n"); cnt=recv(sockfd,buff,BUFFMAX,);
recvCntInfo(cnt,buff);
} int showOprate(void)
{
printf("\n邮件操作选项如下:\n");
printf("1:LIST 2:RETR\n");
printf("3:DELE 4:RSET\n");
printf("请输入操作序号(0结束):");
int choise;
scanf("%d",&choise);
getchar();
return choise;
}

接收程序

exec:send get

send:send.o myFunc.o
gcc send.o myFunc.o -o send
get:get.o myFunc.o
gcc get.c myFunc.o -o get send.o:send.c myHead.h
gcc send.c -c
get.o:get.c myHead.h
gcc get.c -c
myFunc.:myFunc.c
gcc myFunc.c -c

make工程管理

那个。。。貌似有我的邮箱用户名和密码,我也不用。。。哈哈

Linux C SMTP POP3 极简陋邮件客户端的更多相关文章

  1. 使用java语言基于SMTP协议手写邮件客户端

    使用java语言基于SMTP协议手写邮件客户端 1. 说明 电子邮件是互联网上常见的应用,他是互联网早期的产品,直至今日依然受到广大用户的喜爱(在中国可能因为文化背景不同,电子邮件只在办公的时候常用) ...

  2. linux配置邮件客户端

    linux配置邮件客户端 1. 申请一个163邮箱,并配置客户端授权密码 l 开启POP3/SMTP/IMAP l 设置客户端授权密码 ###此密码不能跟邮箱密码相同,此密码用来在linux邮件客户端 ...

  3. POP3是收邮件的协议,SMTP是发邮件的协议,IMAP是一种邮箱通信协议。

    我也是第一次接触这种服务,是因为我自己在做一个小小的自动推送天气情况到自己邮箱.所以才碰到这个的/ 看一下标题,我们可以先这样理解. POP3(Post Office Protocol - Versi ...

  4. centos 邮件服务 腾讯企业邮箱(免费) 使用iRedmail 需要有公网的centos主机 发邮件协议:smtp 端口25 收邮件协议:pop3 端口110 iredmail安装配置 使用邮箱系统 第三十一节课

    centos   邮件服务  腾讯企业邮箱(免费) 使用iRedmail 需要有公网的centos主机 发邮件协议:smtp 端口25  收邮件协议:pop3 端口110  iredmail安装配置 ...

  5. linux邮件客户端mutt日志文件,发不出邮件

    linux上面使用很方便的收发邮件客户端(即MUA),还有一个是mail,大家也可以试试. 在网上找了很多,都说需要msmtp配合使用,其实mutt里面也内建了smtp支持的. mutt and SM ...

  6. mutt+msmtp做linux邮件客户端

    mutt+msmtp做linux邮件客户端 1. 安装配置msmtp l  安装 wget https://sourceforge.net/projects/msmtp/files/msmtp/1.4 ...

  7. linux下支持托盘的邮件客户端Sylpheed

    在网上搜索了很多客户端想支持系统托盘,发现一个很不错的邮件客户端Sylpheed.设置方式和foxmail很像,最为重要的是支持系统托盘,很方便,默认没有开启,简单设置下:配置->通用首选项-& ...

  8. POP3与SMTP以及python实现邮件的发送

    什么是POP3协议: POP3是Post Office Protocol 3的简称,即邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议.它是因特网 ...

  9. SMTP、POP3和IMAP邮件协议

    目录 SMTP POP IMAP 总结 DNS记录中的MX记录 今天入职第一天,公司让配置个人的内网.外网邮箱,这可把我给搞晕了,本来以前就对邮箱这块不是很了解,平时也不怎么用邮箱,顶多有个QQ邮箱而 ...

随机推荐

  1. Office 365 Certificate Exam Resources

    70-321 Deploying Office 365 Deploying Office 365 Jump Start (01): Infrastructure Planning Deploying ...

  2. 苹果Swift语言中文教程资源汇总

    苹果swift语言中文教程(零)搭配环境以及代码执行成功http://vjiazhi.com/kaifa/1014.html 苹果Swift语言中文教程(一)基础数据类型 http://vjiazhi ...

  3. Http Message Converters with the Spring Framework--转载

    原文:http://www.baeldung.com/spring-httpmessageconverter-rest 1. Overview This article describes how t ...

  4. 《JavaScript学习指南》第2版 学习笔记1

    1.<noscript> 标签 noscript 元素用来定义在脚本未被执行时的替代内容(文本). 注释:如果浏览器支持脚本,那么它不会显示出 noscript 元素中的文本.无法识别 & ...

  5. php创建文件夹后设置文件夹权限(转)

    原文链接:http://www.phpstudy.net/b.php/69873.html PHP mkdir()无写权限的问题解决方法 使用mkdir创建文件夹时,发现这个函数有两个参数,第二个参数 ...

  6. WampServer下修改和重置MySQL密码(转)

    转自:www.2cto.com/database/201504/387589.html WampServer安装后密码是空的, 修改一般有两种方式: 一是通过phpMyAdmin直接修改: 二是使用W ...

  7. [设计模式]<<设计模式之禅>>关于里氏替换原则

    在面向对象的语言中,继承是必不可少的.非常优秀的语言机制,它有如下优点:● 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性:● 提高代码的重用性:● 子类可以形似父类,但又异于父类,“龙 ...

  8. poj 1364 差分约束

    思路:设dis[i]为从0点到第i点的序列总和.那么对于A B gt  k 来讲意思是dis[B+A]-dis[A]>k; 对于A B lt k来讲就是dis[B+A]-dis[A]<k; ...

  9. [Yii2]Access to debugger is denied due to IP address restriction. The requesting IP address is

    在更新到正式平台,看到runtime/app.log 有 Access to debugger is denied due to IP address restriction. The request ...

  10. 实用工具推荐(Live Writer)(2015年05月26日)

    1.写博客的实用工具 推荐软件:Live Writer 使用步骤: 1.安装 Live Essential 2011,下载地址:http://explore.live.com/windows-live ...