使用SMTP 和POP3 协议实现收发邮件(C/C++)

来源:互联网 发布:广东移动网络宽带测速 编辑:程序博客网 时间:2024/05/18 00:41


SMTP协议和POP3协议就不详细阐述了 ,网上一搜索会有一大把给你解释的。


下面直接贴代码:

首先写一个class Sock类,这个类的功能主要是创建套接字(即int sock),用套接字來连接邮箱服务器。类里面还带有send_socket和recv_socket两个函数,其功能分别是向邮箱服务器发送协议指令和接收服务器反馈回来的信息。

sock.h文件

  #ifndef __SOCK_H__
  #define __SOCK_H__
 
  #include <iostream>
  #include <sys/socket.h>
  #include <sys/epoll.h>
  #include <stdio.h>
  #include <netinet/in.h>
 
 class Sock
 {
 public:
     Sock();
      bool Connect(const char *host_id, constint &port);
      void send_socket(const char *s);
      int recv_socket();
      constchar * get_recvbuf();
      ~Sock();
       private:
      char recvbuf[BUFSIZ];
      int sock;
      int num;
      struct sockaddr_in server;
      struct hostent *hp;
   };
  #endif

sock.cpp文件

#include"sock.h"
#include<stdexcept>
#include<netdb.h>
#include<string.h>
#include<sys/types.h>
 
Sock::Sock()
{
     sock= socket(AF_INET, SOCK_STREAM, 0);
      if(sock == -1)
      {
           throw std::runtime_error("socketinit error\n");
      }
}
Sock::~Sock()
 {
      close(sock);
 }
bool Sock::Connect(constchar *host_id, const int &port)
{
      server.sin_family = AF_INET;
      hp = gethostbyname(host_id);
      if(hp == (struct hostent *) 0)
      {
           std::cerr << "服务器地址获取失败!" << std::endl;
           return false;
      }
      memcpy((char *)&server.sin_addr,
      (char *)hp->h_addr, hp->h_length);
      server.sin_port = htons(port);
      if(connect(sock, (sockaddr *) &server,sizeof server) == -1)
      {
           std::cerr << "连接服务器失败!" << std::endl;
           return false;
      }
      else
            return true;
 }
 
 void Sock::send_socket(const char *s)
 {
      send(sock, s, strlen(s), 0);
 }
 int Sock::recv_socket()
 {
     memset(recvbuf,0,BUFSIZ);
     returnrecv(sock, recvbuf, BUFSIZ, 0);
  }
 const char * Sock::get_recvbuf()
 {
      return recvbuf;
 }


下面是用SMTP协议发送邮件,格式就如代码所示。了解下SMTP协议,依葫芦画瓢了。

#include "sock.h"
#include <iostream>
 
int main()
{
      Socksock;
      constchar *host_id = "smtp.126.com";
      intport = 25;//smtp协议专用端口
      charwkstr[100] = "hello,how are you?";//邮件内容
      if(sock.Connect(host_id,port) == false)
           return1;
      sock.recv_socket();
      std::cout<< "Client : connected! \nServer :"
            << sock.get_recvbuf() <<std::endl;
 
      /*EHLO指令是必须首先发的,相当于和服务器说hello*/
      sock.send_socket("EHLO**********\r\n");//邮箱用户名
      sock.recv_socket();
      std::cout<< "Client : send helo \nServer :"
           <<sock.get_recvbuf() << std::endl;
 
      /*发送 auth login 指令,告诉服务器要登录邮箱*/
      sock.send_socket("authlogin\r\n");
      sock.recv_socket();
      std::cout<< "Client : send auth login \nServer :"
           <<sock.get_recvbuf() << std::endl;
 
     /*告诉服务器要登录后,接着就是把用户名发过去了.
      不过这个用户名是经过了base64编码的,smtp也支持
      明文传送,至于具体有什么区别上网上找资料看看就知道了*/
      sock.send_socket("**********");//经过base64编码后的邮箱用户名
      sock.send_socket("\r\n");
      sock.recv_socket();
      std::cout<< "Client : send name \nServer :"
           <<sock.get_recvbuf() << std::endl;
 
      /*用户名发过去后接着就是用户密码了,当然也是经过base64编码后的*/
      sock.send_socket("base64编码后的密码");
      sock.send_socket("\r\n");
      sock.recv_socket();
      std::cout<< "Client : send password \nServer :"
           <<sock.get_recvbuf() << std::endl;
 
       /*发送 mail from 指令,相当于填写发件人*/
     sock.send_socket("mail from<");
      sock.send_socket("yuzhenxiong0823@126.com");
     sock.send_socket(">");
      sock.send_socket("\r\n");
      sock.recv_socket();
      std::cout<< "Client: send mail from \nServer :"
           <<sock.get_recvbuf() << std::endl;
 
       /*发送 rcpt to 指令,就是填写收件人了 */
      sock.send_socket("rcptto <");
      sock.send_socket("120091241@qq.com");
      sock.send_socket(">");
      sock.send_socket("\r\n");
      sock.recv_socket();
      std::cout<< "Client : send rcpt to \nServer"
           <<sock.get_recvbuf() << std::endl;
 
       /*发送data,标志着后面开始发送邮件的主题部分*/
      sock.send_socket("data\r\n");
      sock.recv_socket();
      std::cout<< "Client : send data \nServer :"
           <<sock.get_recvbuf() << std::endl;
      /*发送邮件主体部分,先是邮件主题(subject),后面是邮件内容。
      下面就是发送主体的格式*/
      sock.send_socket("subject:");
      sock.send_socket("testmail\r\n");
      sock.send_socket("\r\n\r\n");
      sock.send_socket("hello,howare you.\r\n");
      sock.send_socket(".\r\n");
      sock.recv_socket();
      std::cout<< "Client : send content \nServer :"
            << sock.get_recvbuf() <<std::endl;
 
     sock.send_socket("quit\r\n");
      sock.recv_socket();
      std::cout<< "Client : send quit \nServer :"
          << sock.get_recvbuf() <<std::endl;
     
}


下面是用POP3协议指令接收邮件:

#include "sock.h"
#include <iostream>
#include <string.h>

int main()
{
 Sock sock;
 const char *host_id = "pop3.126.com";
 int port = 110;
 if(sock.Connect(host_id, port) == false)
    return 1;
 std::cout << "connected\n";
 sock.recv_socket();
 std::cout << "Client:connect successfully! \nServer:"
  << sock.get_recvbuf() << std::endl;
 
 sock.send_socket("user ********@126.com\r\n");//输入邮箱用户名
 sock.recv_socket();
 std::cout << "Client : send name \nServer:"
    << sock.get_recvbuf() << std::endl;

 sock.send_socket("pass *****\r\n");//邮箱密码
 sock.recv_socket();
 std::cout << "Client : send password \n Server :"
     << sock.get_recvbuf() << std::endl;

 sock.send_socket("stat\r\n");
 sock.recv_socket();
 std::cout << "Client : send stat \nServer : "
  << sock.get_recvbuf() << std::endl;
 sleep(1);

 sock.send_socket("list\r\n");
 std::cout << "Client : send list \nServer :"
  << sock.get_recvbuf() << std::endl;
 sleep(1);

 sock.send_socket("retr 5\r\n");
 std::cout << "Client : send retr (...) \n";
          //下面的while循环有些问题,目前还没有想到解决方法。以后改正!
           while(1)
 {
     int num = sock.recv_socket();
      std::cout << "Server :" << sock.get_recvbuf() << std::endl;
    if(num <= 0)
    {
       break;
    }
 }
 
 sock.send_socket("quit\r\n");
 std::cout << "Client : send quit \nServer :"
        << sock.get_recvbuf() << std::endl;
}


pop3连接邮箱是有时候会被服务器拒绝连接,多运行几次编译文件即可!

接收到的邮件是经过编码后的,需要解码!作为一个初学者,实在是无能为力了,也希望各位大神能多指点一二。