C语言发送email

    应用:分布式评测系统中检测到连接断开后向管理员发送邮件。

 

一、 认证方式


  ESMTP(Extension SMTP)即认证的邮件传输方式,是邮件服务器系统为了限制非本系统的正式用户利用本系统散发垃圾邮件或其他不当行
为而开设的一项安全认证服务。它与传统的SMTP方式相比,主要的不同有两点:
  1) 支持8-bit MIME格式的编码。
  2) 支持用户身份的验证。
  多了一道用户身份的验证手续,验证之后的邮件发送过程与传统的SMTP方式一致。为了方便用户的使用,绝大多数的ESMTP服务器都继承了
POP3服务器的帐号和密码设置体系,也就是说收发邮件都用同一个帐号和密码。

  根据[RFC 2554]规范,SMTP的认证功能主要是增加了AUTH命令。AUTH命令有多种用法,而且有多种认证机制。AUTH支持的认证机制主要有LOGIN,CRAM-MD5[注1]等。LOGIN应该是大多数免费邮件服务器都支持的,网易与新浪都支持。下面主要针对LOGIN方式进行介绍,其它方式请根据相应的RFC 规范进行修改。
     几乎所有的ESMTP服务器都继承了POP3服务器的账号和密码设置体系,也就是说收发邮件用相同的账号和密码。当然,也可以用不同的账号和密码,但那样无论是电子邮件服务提供商的维护还是用户的使用都会很麻烦,故而很少采用。

LOGIN 方式口令-应答过程如下(S:表示服务器返回,C:表示客户端发送)
  1. C: AUTH LOGIN
  2. S: 334 dXNlcm5hbWU6      // dXNlcm5hbWU6是username:的BASE64编码
  3. C: dXNlcm5hbWU6
  4. S: 334 cGFzc3dvcmQ6     // cGFzc3dvcmQ6是password:的BASE64编码
  5. C: cGFzc3dvcmQ6
  6. S: 235 Authentication successful.
  (1). 为客户端向服务器发送认证指令。
  (2). 服务端返回base64编码串,成功码为334。编码字符串解码后为"username:",说明要求客户端发送用户名。
  (3). 客户端发送用base64编码的用户名,此处为"username:"。
  (4). 服务端返回base64编码串,成功码为334。编码字符串解码后为"password:",说明要求客户端发送用户口令。
  (5). 客户端发送用base64编码的口令,此处为"password:"。
  (6). 成功后,服务端返回码为235,表示认证成功可以发送邮件了

二:BASE64编码原理

  Base64编码其实是将3个8位字节转换为4个6位字节,( 3*8 = 4*6 = 24 ) 这4个六位字节 其实仍然是8位,只不过高两位被设置为0. 当一个字
节只有6位有效时,它的取值空间为0~63。
事实上,0~63之间的ASCII码有许多不可见字符,所以应该再做一个映射,映射表为
‘A‘ ~ ‘Z‘ ? ASCII(0 ~ 25)
‘a’ ~ ‘z‘ ? ASCII(26 ~ 51)
‘0’ ~ ‘9‘ ? ASCII(52 ~ 61)
‘+‘ ? ASCII(62)
‘/‘ ? ASCII(63)
这样就可以将3个8位字节,转换为4个可见字符。
具体的字节拆分方法为:(图(画得不好,领会精神 :-))
aaaaaabb ccccdddd eeffffff   //abcdef其实就是1或0,为了看的清楚就用abcdef代替
00aaaaaa 00bbcccc 00ddddee 00ffffff
注:上面的三个字节位原文,下面四个字节为Base64编码,其前两位均为0。

这样拆分的时候,原文的字节数量应该是3的倍数,当这个条件不能满足时,用全零字节补足,转化时Base64编码用=号代替,这就是为什么有
些Base64编码以一个或两个等号结束的原因,但等号最多有两个,因为:如果F(origin)代表原文的字节数,F(remain)代表余数,则
F(remain) = F(origin) MOD 3 成立。
所以F(remain)的可能取值为0,1,2.
如果设 n = [F(origin) – F(remain)] / 3
当F(remain) = 0 时,恰好转换为4*n个字节的Base64编码。
当F(remain) = 1 时,由于一个原文字节可以拆分为属于两个Base64编码的字节,为了让Base64编码是4的倍数,所以应该为补2个等号。
当F(remain) = 2 时,由于两个原文字节可以拆分为属于3个Base64编码的字节,同理,应该补上一个等号。

 

三、发送步骤


1)获得邮件服务器的地址。调用gethostbyname(),将smtp.sina.com作为参数传入,保存返回的 hostent结构的地址,用它的h_addr_list[0]来初始化sockaddr_in结构的sin_addr.S_un.S_addr成员,端口写成25,这是邮件服务标准端口。

 

2)TCP Socket连接。

 

3)使用SMTP来通信了。该通信是个同步的过程,遵守一发一收的规则,连接上后先接收服务器的反馈信息,然后发送“HELO [信息]/r/n”表明身份,命令EHLO和后面的信息要有空格,信息可以什么信息都不加,接收后继续发送“AUTH LOGIN/r/n”,接收后发送用户名(即邮箱地址中@前边的部分),再发送密码,此时服务器返回是否验证成功的信息,若成功则返回代码为235的信息,否则返回535,注意有可能由于服务器的繁忙而导致验证失败,并不是用户名和密码的问题,所以失败后要继续从头开始,连接-发送-接收-验证,另外,用户名和密码采用base64编码。
       验证后就可以发送具体的邮件信息了。首先发送发件人,“MAIL FROM: <用户名@邮件服务器>/r/n”。其次发送收件人,这个可是要起作用的,发送 “RCPT TO: <目的邮箱>”,要发送给几个人,就发送几个“RCPT TO: <目的邮箱>”,然后发送“DATA/r/n”表示要发送具体数据了,数据格式为:邮件头+邮件体
       邮件头:
       From: "想要显示的发件人"<想要显示的邮箱名>/r/n
       To: <想要显示的收件人邮箱地址>/r/n
       Subject: 主题名/r/n/r/n  此处的两个/r/n表示邮件头结束
       邮件体:
       邮件内容
       结束标志为/r/n./r/n
       将这些信息组成一个字符串发送出去就可以了,最后发送“QUIT /r/n”断开连接。
      至此,邮件发送程序便编写完成了。

4)断开TCP连接。

 

四、关键代码

void sendemail(char *mailsrv, char *mailfrom, char *mailto, char *body)
{
    int sockfd = 0,i=0;
    struct sockaddr_in their_addr = {0};
    char buf[1500] = {0};
    char rbuf[1500] = {0};
    char login[128] = {0};
    char pass[128] = {0};

    struct hostent *hp = gethostbyname(mailsrv);
       
    memset(&their_addr, 0, sizeof(their_addr));
    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(25);
    their_addr.sin_addr.s_addr = *(int*)(*hp->h_addr_list);

    sockfd = open_socket((struct sockaddr *)&their_addr);
    memset(rbuf,0,1500);
    while(recv(sockfd, rbuf, 1500, 0) == 0)
    {
        printf("reconnect.../n");
        sleep(2);
        close(sockfd);
        sockfd = open_socket((struct sockaddr *)&their_addr);
        memset(rbuf,0,1500);
    }
    printf("%d.%s/n",i++, rbuf);
   
    //1.EHLO
    memset(buf, 0, 1500);
    sprintf(buf, "EHLO caoli/r/n");
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //2.AUTH LOGIN
    memset(buf, 0, 1500);
    sprintf(buf, "AUTH LOGIN/r/n");
    send(sockfd, buf, strlen(buf), 0);
    printf("%s/n", buf);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //3.USER
    memset(buf, 0, 1500);
    sprintf(buf,"caoli");
    memset(login, 0, 128);
    base64(login, buf, strlen(buf));
    sprintf(buf, "%s/r/n", login);
    send(sockfd, buf, strlen(buf), 0);
    printf("%s/n", buf);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //4.PASSWD
    sprintf(buf, "33060808");
    memset(pass, 0, 128);
    base64(pass, buf, strlen(buf));
    sprintf(buf, "%s/r/n", pass);
    send(sockfd, buf, strlen(buf), 0);
    printf("%s/n", buf);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //5.MAIL FROM
    memset(buf, 0, 1500);
    sprintf(buf, "MAIL FROM:<%s>/r/n",mailfrom);
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //6.MAIL TO ...(multiple destination)
    sprintf(buf, "RCPT TO:<%s>/r/n", mailto);
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d:%d.%s/n",__LINE__,i++, rbuf);
/*
    sprintf(buf, "RCPT TO:starryheavens@hotmail.com/r/n");
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
*/
    //7.DATA
    sprintf(buf, "DATA/r/n");
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //8.CONTENT
    sprintf(buf, "%s/r/n./r/n", body);
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);
    //9.QUIT
    sprintf(buf, "QUIT/r/n");
    send(sockfd, buf, strlen(buf), 0);
    memset(rbuf, 0, 1500);
    recv(sockfd, rbuf, 1500, 0);
    printf("%d.%s/n",i++, rbuf);

    close(sockfd);
    return;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言 email server指的是使用C语言编写的邮件服务器邮件服务器是一种运行在网络上的应用程序,负责接收、发送、存储和转发电子邮件。使用C语言编写邮件服务器有以下几个优点: 第一,C语言是一种高效、可靠的编程语言,具有较高的执行速度和较少的内存占用。这使得C语言非常适合编写需要处理大量邮件服务器程序。 第二,C语言具有丰富的系统函数和网络库,可以方便地进行网络通信和邮件处理相关的操作。这些库包括socket编程库和SMTP、POP3等邮件协议相关的库,能够满足邮件服务器的各种需求。 第三,C语言具有较高的可移植性,可以在不同的操作系统上运行。这对于邮件服务器来说非常重要,因为不同的用户可能使用不同的操作系统发送和接收邮件。 实现C语言 email server需要考虑以下几个方面的功能: 1. 接收邮件邮件服务器需要监听指定端口,接收来自客户端的连接请求并接收邮件内容。 2. 存储邮件邮件服务器需要将接收到的邮件存储到指定的位置,每个用户可能有不同的邮件存储路径。 3. 转发邮件邮件服务器需要能够将用户发送邮件转发给指定的收件人。这需要验证发送者的身份、查找收件人的地址并进行邮件路由。 4. 邮件过滤和防垃圾邮件邮件服务器需要实现垃圾邮件过滤机制,以减少垃圾邮件对用户的骚扰。 5. 定时任务:邮件服务器还需要支持定时任务,如定期清理过期的邮件、定时发送提醒邮件等。 总之,使用C语言编写email server可以实现一个高效、可靠的邮件服务器,并提供完善的邮件收发、存储和转发功能,从而满足用户的邮件通信需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值