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

时间:2021-08-17 19:04:08
SMTP协议和POP3协议就不详细阐述了 ,网上一搜索会有一大把给你解释的。

 

下面直接贴代码:

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

sock.h文件

[cpp]
  1. 1 #ifndef __SOCK_H__ 
  2. 2 #define __SOCK_H__ 
  3. 3  
  4. 4 #include <iostream> 
  5. 5 #include <sys/socket.h> 
  6. 6 #include <sys/epoll.h> 
  7. 7 #include <stdio.h> 
  8. 8 #include <netinet/in.h> 
  9. 9  
  10. 10 class Sock 
  11. 11 { 
  12. 12     public
  13. 13         Sock(); 
  14. 14         bool Connect(const char *host_id, const int &port); 
  15. 15         void send_socket(const char *s); 
  16. 16         int recv_socket(); 
  17. 17         const char * get_recvbuf(); 
  18. 18         ~Sock(); 
  19. 19         private
  20. 20         char recvbuf[BUFSIZ]; 
  21. 21         int sock; 
  22. 22         int num; 
  23. 23         struct sockaddr_in server; 
  24. 24         struct hostent *hp; 
  25. 25 }; 
  26. 26  
  27. 27 #endif 
sock.cpp文件
[cpp]
  1. 1 #include "sock.h" 
  2.   2 #include <stdexcept> 
  3.   3 #include <netdb.h> 
  4.   4 #include <string.h> 
  5.   5 #include <sys/types.h> 
  6.   6  
  7.   7 Sock::Sock() 
  8.   8 { 
  9.   9     sock = socket(AF_INET, SOCK_STREAM, 0); 
  10. 10     if(sock == -1) 
  11. 11     { 
  12. 12         throw std::runtime_error("socket init error\n"); 
  13. 13     } 
  14. 14 } 
  15. 15 Sock::~Sock() 
  16. 16 { 
  17. 17     close(sock); 
  18. 18 } 
  19. 19 bool Sock::Connect(const char *host_id, const int &port) 
  20. 20 { 
  21. 21     server.sin_family = AF_INET; 
  22. 22     hp = gethostbyname(host_id); 
  23. 23     if(hp == (struct hostent *) 0) 
  24. 24     { 
  25. 25         std::cerr << "服务器地址获取失败!" << std::endl; 
  26. 26         return false
  27. 27     } 
  28. 28     memcpy((char *)&server.sin_addr, 
  29. 29             (char *)hp->h_addr, hp->h_length); 
  30. 30     server.sin_port = htons(port); 
  31. 31     if(connect(sock, (sockaddr *) &server, sizeof server) == -1) 
  32. 32     { 
  33. 33         std::cerr << "连接服务器失败!" << std::endl; 
  34. 34         return false
  35. 35     } 
  36. 36     else 
  37. 37         return true
  38. 38 } 
  39.  
  40. void Sock::send_socket(const char *s) 
  41. 40 { 
  42. 41     send(sock, s, strlen(s), 0); 
  43. 42 } 
  44. 43 int Sock::recv_socket() 
  45. 44 { 
  46. 45     memset(recvbuf, 0,BUFSIZ); 
  47. 46     return recv(sock, recvbuf, BUFSIZ, 0); 
  48. 47 } 
  49. 48 const char * Sock::get_recvbuf() 
  50. 49 { 
  51. 50     return recvbuf; 
  52. 51 } 
下面是用SMTP协议发送邮件,格式就如代码所示。了解下SMTP协议,依葫芦画瓢了。
[cpp]
  1. 1 #include "sock.h" 
  2.   2 #include <iostream> 
  3.   3  
  4.   4 int main() 
  5.   5 { 
  6.   6     Sock sock; 
  7.   7     const char *host_id = "smtp.126.com"
  8.   8     int port = 25;//smtp协议专用端口 
  9.   9     char wkstr[100] = "hello,how are you?";//邮件内容 
  10. 10     if(sock.Connect(host_id, port) == false
  11. 11         return 1; 
  12. 12     sock.recv_socket(); 
  13. 13     std::cout << "Client : connected! \nServer :" 
  14. 14         << sock.get_recvbuf() << std::endl; 
  15. 15  
  16. 16    /* EHLO指令是必须首先发的,相当于和服务器说hello */ 
  17. 17     sock.send_socket("EHLO **********\r\n");//邮箱用户名 
  18. 18     sock.recv_socket(); 
  19. 19     std::cout << "Client : send helo \nServer :" 
  20. 20         << sock.get_recvbuf() << std::endl; 
  21. 21  
  22. 22     /*发送 auth login 指令,告诉服务器要登录邮箱*/ 
  23. 23     sock.send_socket("auth login\r\n"); 
  24. 24     sock.recv_socket(); 
  25. 25     std::cout << "Client : send auth login \nServer :" 
  26. 26         << sock.get_recvbuf() << std::endl; 
  27. 27  
  28. 28     /*告诉服务器要登录后,接着就是把用户名发过去了.
  29. 29       不过这个用户名是经过了base64编码的,smtp也支持
  30. 30       明文传送,至于具体有什么区别上网上找资料看看就知道了*/ 
  31. 31     sock.send_socket("**********");//经过base64编码后的邮箱用户名 
  32. 32     sock.send_socket("\r\n"); 
  33. 33     sock.recv_socket(); 
  34. 34     std::cout << "Client : send name \nServer :" 
  35. 35         << sock.get_recvbuf() << std::endl; 
  36.  
  37. 37    /* 用户名发过去后接着就是用户密码了,当然也是经过base64编码后的*/ 
  38. 38     sock.send_socket("base64编码后的密码"); 
  39. 39     sock.send_socket("\r\n"); 
  40. 40     sock.recv_socket(); 
  41. 41     std::cout << "Client : send password \nServer :" 
  42. 42         << sock.get_recvbuf() << std::endl; 
  43. 43  
  44. 44     /*发送 mail from 指令,相当于填写发件人*/ 
  45. 45     sock.send_socket("mail from: <"); 
  46. 46     sock.send_socket("yuzhenxiong0823@126.com"); 
  47. 47     sock.send_socket(">"); 
  48. 48     sock.send_socket("\r\n"); 
  49. 49     sock.recv_socket(); 
  50. 50     std::cout << "Client: send mail from \nServer :" 
  51. 51         << sock.get_recvbuf() << std::endl; 
  52. 52  
  53. 53     /*发送 rcpt to 指令,就是填写收件人了 */ 
  54. 54     sock.send_socket("rcpt to: <"); 
  55. 55     sock.send_socket("120091241@qq.com"); 
  56. 56     sock.send_socket(">"); 
  57. 57     sock.send_socket("\r\n"); 
  58. 58     sock.recv_socket(); 
  59. 59     std::cout << "Client : send rcpt to \nServer" 
  60. 60         << sock.get_recvbuf() << std::endl; 
  61. 61  
  62. 62     /*发送data,标志着后面开始发送邮件的主题部分*/ 
  63. 63     sock.send_socket("data\r\n"); 
  64. 64     sock.recv_socket(); 
  65. 65     std::cout << "Client : send data \nServer :" 
  66. 66         << sock.get_recvbuf() << std::endl; 
  67. 67     /*发送邮件主体部分,先是邮件主题(subject),后面是邮件内容。
  68. 68      下面就是发送主体的格式*/ 
  69. 69     sock.send_socket("subject:"); 
  70. 70     sock.send_socket("testmail\r\n"); 
  71. 71     sock.send_socket("\r\n\r\n"); 
  72. 72     sock.send_socket("hello,how are you.\r\n"); 
  73. 73     sock.send_socket(".\r\n"); 
  74. 74     sock.recv_socket(); 
  75. 75     std::cout << "Client : send content \nServer :" 
  76. 76         << sock.get_recvbuf() << std::endl; 
  77.  
  78.   sock.send_socket("quit\r\n"); 
  79. 79     sock.recv_socket(); 
  80. 80     std::cout << "Client : send quit \nServer :" 
  81. 81         << sock.get_recvbuf() << std::endl; 
  82. 82  
  83. 83 }