C语言编写smtp用户代理之协议操作

上一章写了socket 操作,这一章用上一章的内容写smtp协议相关操作的函数。
首先是smtp.h文件

#ifndef SMTP_H
#define SMTP_H
#include"renyj_sock.h"
//根据smtp协议,用来处理发送和接收EHLO的函数
int mail_say_hello(char *hello_domain);

//用来处理FROM命令和接受其回复的函数
int mail_from(char *from);

//用来处理RCPT TO命令和接收其回复的函数
int mail_to(char *to);

//用来处理DATA 命令和接收其回复的函数
int mail_data();

//用来处理QUIT命令和接收其回复的函数
int mail_quit();

//用来处理发送 . 和接收其回复的函数
int mail_eom();

//用来处理用户认证的函数
int mail_auth(char *uer,char *pass);

//用来发送邮件的函数
int send_the_mail(char *from,char *to,char *server,int port,char *user,
                        char *pass,char *subject,char *msgline,int timeout);
#endif

二、函数实现,smtp.c文件。

#include"smtp.h"
#include"mutils.h"

char mail_buff[1000] = "";

//用来读取邮件服务器回复的函数
int smtp_read_line()
{
    memset(mail_buff,0x00,sizeof(mail_buff));
    int rc = mysock_gets(mail_buff,100,10);
    if (rc < 0)
    {
        return rc;
    }
    debug("[S] -----> %s",mail_buff);
    return rc;
}

/*处理EHLO函数,这里我发现需要向服务器发送两次EHLO命令,可能时跟服务器有关系。如果有清楚的大神还请指点一下。我这样写是根据实际情况自己分析出来的。*/

int mail_say_hello(char *hello_domain)
{
    memset(mail_buff,0x00,sizeof(mail_buff));
    mysock_puts("EHLO ");
    int rc = smtp_read_line();
    sprintf(mail_buff,"EHLO %s\r\n",hello_domain);
    mysock_puts(mail_buff);
    do
    {
    rc = smtp_read_line();
    if (rc < 0)
    {
        debug("say hello error");
        return -1;
    }
    }while(NULL != strstr(mail_buff,"-"));
}

//处理FROM命令
int mail_from(char *from)
{
    memset(mail_buff,0x00,sizeof(mail_buff));
    sprintf(mail_buff,"MAIL FROM: <%s>\r\n",from);
    mysock_puts(mail_buff);
    memset(mail_buff,0x00,sizeof(mail_buff));
    int rc = smtp_read_line();
    if (rc<0)
    {
        debug("rcv mail from error");
        return -1;
    }

}

//处理TO命令
int mail_to(char *to)
{
    memset(mail_buff,0x00,sizeof(mail_buff));
    sprintf(mail_buff,"RCPT TO: <%s>\r\n",to);
    mysock_puts(mail_buff);
    memset(mail_buff,0x00,sizeof(mail_buff));
    int rc = smtp_read_line();
    if (rc<0)
    {
        debug("rcv mail to error");
        return -1;
    }

}

//处理DATA命令。
int mail_data()
{
    memset(mail_buff,0x00,sizeof(mail_buff));
    mysock_puts("DATA\r\n");    
    int rc = smtp_read_line();
    if (rc < 0)
    {
        debug("rcv data error");
        return -1;
    }
}

//发送 . 来让邮件结束输入
int mail_eom()
{

    mysock_puts("\r\n.\r\n");
    smtp_read_line();
}

//退出邮件
int mail_quit()
{
    mysock_puts("QUIT\r\n");
    smtp_read_line();
}

//邮件的认证
int mail_auth(char *user,char *pass)
{
    char *b64 = NULL;
    char buf[1000]="";
    //发送LOGIN认证,因为是针对qq服务器,我知道它支持这个。
    mysock_puts("AUTH LOGIN\r\n");
    int rc = smtp_read_line();
    if (rc < 0)
    {
        debug("auth login rcv error");
        return -1;
    }
    memset(mail_buff,0x00,sizeof(mail_buff));

    //这里需要对用户名进行base64的加密。不一定非要用这个函数,如果有人要用,我会上传源码
    b64=mutils_encode_base64_noformat(user,strlen(user));
    if (b64 == NULL)
    {
        debug("Could not base64 encode user: %s",user);
        return -1;
    }
    memset(buf,0,sizeof(buf));
    (void) snprintf(buf,sizeof(buf)-1,"%s\r\n",b64);
    mysock_puts(buf);
    memset(mail_buff,0x00,sizeof(mail_buff));
    rc = smtp_read_line();
    if (rc < 0)
    {
        debug("user error");
        return -1;
    }

    //这里需要对用户名进行base64的加密
    b64=mutils_encode_base64_noformat(pass,strlen(pass));
    if (b64 == NULL)
    {
        debug("Could not base64 encode passworf of user: %s",pass);
        return -1;
    }
    memset(buf,0,sizeof(buf));
    (void) snprintf(buf,sizeof(buf)-1,"%s\r\n",b64);
    mysock_puts(buf);
    memset(mail_buff,0x00,sizeof(mail_buff));
    rc = smtp_read_line();
    if (rc < -1)
    {
        debug("pass error");
        return -1;
    }
}


int send_the_mail(char *from,char *to,char *server,int port,char *user,
                                char *pass,char *subject,char *msgline,int timeout)
{
    //init the client socket
    int rc; 
    rc = myclient_sock(0,server,port,timeout);
    if (rc < 0)
    {
        debug("myclient_sock error");
        return -1;
    }
    set_socket(rc);

    //turn on the ssl
    char *cip = NULL;
    openssl_init(cip);
    turn_on_ssl(get_socket());

    //say ehlo  
    char *hello_domain = "localhost";
    mail_say_hello(hello_domain);

    //use login,and start AUTH
    debug("start AUTH");
    mail_auth(user,pass);

    //FROM 
    debug("start FROM");
    mail_from(from);    

    //TO
    debug("start TO");
    mail_to(to);

    //DATA
    debug("start DATA");
    mail_data();

    //send the Subject  
    char subjectbuff[150] = "";
    //这里就是标题内容
    sprintf(subjectbuff,"Subject: %s\r\n",subject);
    //from可能必须按照你登录的账号填写,要不然就会被当做垃圾邮件
    mysock_puts("From: xxxxxx@qq.com\r\n");
    mysock_puts("Date:\r\n");
    mysock_puts("To: xxxxxx@qq.com\r\n");
    mysock_puts(subjectbuff);
    //这里content-type必须写,要不然发出去的就不知道什么类型了,也不会吧你发的那句话当做消息。
    mysock_puts("Content-type: text/plain\r\n\r\n");
    mysock_puts(msgline);

    //use . end data 
    debug("start eom");
    mail_eom();

    //quit the msg
    debug("QUIT");
    mail_quit();
    mysock_close();

    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值