利用QT实现邮件发送功能使用telnet通过smtp协议来发送邮件

10 阅读 作者:yy_coderrrrrr 2020-08-10

要做一个监测软件,出问题时需要发送一封邮件,所以最近就在网上找了下qt5怎么发邮件,下面贴出方法(代码部分是网上找的一个,自己测试可以使用,直接拷过去就可以了)。

基本原理就是使用telnet通过smtp协议来发送邮件。先简单说下telnet和smtp。

Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。smtp(simple mail transfer protocol)则是简单的邮件传输协议。(具体还是自己去找下度娘吧)

然后就是先熟悉一下telnet怎么发送邮件了首先需要打开电脑的telnet功能,先进入到控制面板界面,点击下图(左)中红框部分,然后在下右图中勾选telnet客户端,点击确定,稍等一下就可以了。

 接下来是尝试在telnet中发送邮件:

1.使用telnet连接邮箱服务器,名称的格式基本都是smtp.xxx.com,例如:qq邮箱为smtp.qq.com,163邮箱为smtp.163.com,然后端口为25,如下左图

 

2.连接上之后会打印上右图第一行,然后输入helo sis,这句只是打招呼,收到250回复之后再输入auth login,收到334回复即可输入用户名,这里需要输入base64格式数据,即需要把你的邮箱先base64编码再输入进来,密码也是一样。(如果是qq邮箱需要先到邮箱-->设置里面打开smtp功能并使用授权码当做密码登陆)

3.登陆完成之后即可开始发送邮件了,如下图mail from会显示在收件人的邮件里面,rcpt to为收件人的邮箱地址,如果要向多个人同时发邮件可使用rcpt to多个邮箱(看到网上这么写的,我并没有试过同时向多个人发邮件)写完数据之后以“回车  .  回车”结束,最后回复250 ok即发送成功(下图中有3此报错,其实我连同下面第4次输入的都是同一个邮箱,这里不太明白为什么会报错)

 qt中的实现思路也是如此,下面贴上代码:

先是smtp.c文件:

  1. #include "smtp.h"
  2. Smtp::Smtp(QString smtphost, QString smtpusername, QString smtppass)
  3. {
  4. this->smtphost = smtphost;
  5. this->smtpusername = smtpusername;
  6. this->smtppass = smtppass;
  7. }
  8. bool Smtp::Send( const QString &to, const QString &subject, const QString &body )
  9. {
  10. qDebug()<<"####"<<Q_FUNC_INFO;
  11. bool res = false;
  12. int waittime = 5 * 1000;
  13. this->from = smtpusername;
  14. rcpt = to;
  15. ErrorMSG.clear();
  16. Timeout = waittime;
  17. linesend = 0;
  18. isconnect = false;
  19. QString tmp = "=?utf-8?B?"+ QByteArray().append(subject).toBase64()+"?=";
  20. message.append("Subject:" + tmp + "\n");
  21. message.append("To: " + to + "\n");
  22. message.append("From: "+smtpusername+" <" + smtpusername + ">\n");
  23. message.append("Content-Type: text/html; charset=UTF8;\n"); /* or txt */
  24. message.append("Content-transfer-encoding: 7BIT\n\n\n\n");
  25. message.append(body);
  26. message.replace( tr( "\n" ), tr( "\r\n" ) );
  27. message.replace( tr( "\r\n.\r\n" ),tr( "\r\n..\r\n" ) );
  28. smtpsocket = new QTcpSocket(this);
  29. connect( this, SIGNAL(SendLine()), this ,SLOT(PutSendLine()));
  30. if (smtphost.size() > 0)
  31. {
  32. smtpsocket->connectToHost(smtphost,25);
  33. } else {
  34. smtpsocket->connectToHost("localhost",25);
  35. }
  36. if (smtpsocket->waitForConnected(Timeout))
  37. {
  38. if (smtpsocket->waitForReadyRead(Timeout))
  39. {
  40. isconnect = true;
  41. return ReadLiner();
  42. }
  43. }
  44. else
  45. {
  46. ErrorCloseAll();
  47. }
  48. return res;
  49. }
  50. bool Smtp::ReadLiner()
  51. {
  52. bool res = false;
  53. if (isconnect)
  54. {
  55. QTextCodec *codecx;
  56. codecx = QTextCodec::codecForMib(106);
  57. t = new QTextStream( smtpsocket );
  58. t->setCodec(codecx);
  59. int loops = 0;
  60. while (!t->atEnd())
  61. {
  62. loops++;
  63. response = t->readLine();
  64. }
  65. if (response.size() > 0)
  66. {
  67. RemoteServerName = response;
  68. mailstatus = response.left(3);
  69. if (mailstatus == "220")
  70. {
  71. response="";
  72. linesend = 1;
  73. res = true;
  74. }
  75. }
  76. else
  77. {
  78. ErrorCloseAll();
  79. }
  80. }
  81. return res;
  82. }
  83. Smtp::~Smtp()
  84. {
  85. delete smtpsocket;
  86. delete t;
  87. }
  88. /* LINE SENDER */
  89. bool Smtp::PutSendLine()
  90. {
  91. static bool res = true;
  92. int current = linesend;
  93. switch(current)
  94. {
  95. case 1:
  96. response = SendLineAndGrab("ehlo localhost");
  97. if (response.size() > 0)
  98. {
  99. ErrorMSG.append(response);
  100. linesend = 2;
  101. emit SendLine();
  102. }
  103. else
  104. {
  105. res=false;
  106. }
  107. response ="";
  108. break;
  109. case 2:
  110. response = SendLineAndGrab("AUTH LOGIN");
  111. if (response.size() > 0)
  112. {
  113. ErrorMSG.append(response);
  114. linesend = 3;
  115. emit SendLine();
  116. }
  117. else
  118. {
  119. res= false;
  120. }
  121. response ="";
  122. break;
  123. case 3:
  124. response = SendLineAndGrab(encodeBase64(smtpusername)); /* username send */
  125. if (response.size() > 0)
  126. {
  127. ErrorMSG.append(response);
  128. if (response.contains("334", Qt::CaseInsensitive))
  129. {
  130. linesend = 4;
  131. emit SendLine();
  132. }
  133. }
  134. else
  135. {
  136. res=false;
  137. }
  138. response ="";
  139. break;
  140. case 4:
  141. response = SendLineAndGrab(encodeBase64(smtppass)); /* pass send */
  142. if (response.size() > 0)
  143. {
  144. ErrorMSG.append(response);
  145. if (response.contains("235", Qt::CaseInsensitive))
  146. {
  147. linesend = 5;
  148. emit SendLine();
  149. }
  150. else
  151. {
  152. res= false;
  153. }
  154. }
  155. else
  156. {
  157. res= false;
  158. }
  159. response ="";
  160. break;
  161. case 5:
  162. response = SendLineAndGrab(tr("MAIL FROM: %1").arg(smtpusername));
  163. if (response.size() > 0)
  164. {
  165. linesend = 6;
  166. emit SendLine();
  167. }
  168. break;
  169. case 6:
  170. response = SendLineAndGrab("RCPT TO: "+rcpt);
  171. if (response.size() > 0)
  172. {
  173. ErrorMSG.append(response);
  174. response ="";
  175. response = SendLineAndGrab("DATA");
  176. if (!response.contains("not", Qt::CaseInsensitive))
  177. {
  178. ErrorMSG.append(response);
  179. response ="";
  180. linesend = 7;
  181. emit SendLine();
  182. }
  183. }
  184. response ="";
  185. break;
  186. case 7:
  187. response = SendLineAndGrab(message+"\r\n.");
  188. if (response.size() && response.contains("ok", Qt::CaseInsensitive) )
  189. {
  190. ErrorMSG.append(response);
  191. linesend = 8;
  192. emit SendLine();
  193. }
  194. response ="";
  195. break;
  196. case 8:
  197. SendLineAndGrab("QUIT");
  198. break;
  199. default:
  200. break;
  201. }
  202. return res;
  203. }
  204. /* SENDER AND RECIVER */
  205. QString Smtp::SendLineAndGrab(QString senddata)
  206. {
  207. QString incommingData = "";
  208. if (isconnect)
  209. {
  210. int current = linesend;
  211. int loops = 0;
  212. *t << senddata << "\r\n";
  213. t->flush();
  214. if (senddata != "QUIT") {
  215. if (smtpsocket->waitForReadyRead(Timeout))
  216. {
  217. while (!t->atEnd())
  218. {
  219. loops++;
  220. QString opera = t->readLine()+"\n";
  221. incommingData = opera + incommingData;
  222. }
  223. }
  224. } else
  225. {
  226. 原文地址:https://blog.csdn.net/qq_16254831/article/details/82748700
广告一下
热门教程
PHP7报A non well formed numeric value encountered 0
Linux系统下关闭mongodb的几种命令分享 0
mongodb删除数据、删除集合、删除数据库的命令 0
Git&Github极速入门与攻坚实战课程 0
python爬虫教程使用Django和scrapy实现 0
libnetsnmpmibs.so.31: cannot open shared object file 0
数据结构和算法视频教程 0
redis的hash结构怎么删除数据呢? 0
C++和LUA解析器的数据交互实战视频 0
mongodb errmsg" : "too many users are authenticated 0
C++基础入门视频教程 0
用30个小时精通C++视频教程可能吗? 0
C++分布式多线程游戏服务器开发视频教程socket tcp boost库 0
C++培训教程就业班教程 0
layui的util工具格式时间戳为字符串 0
C++实战教程之远程桌面远程控制实战 1
网络安全培训视频教程 0
LINUX_C++软件工程师视频教程高级项目实战 0
C++高级数据结构与算法视频教程 0
跨域问题很头疼?通过配置nginx轻松解决ajax跨域问题 0
相关文章
【译】JavaScript数据结构(3):单向链表与双向链表 16
10个JavaScript难点 16
【译】苹果拒绝支持PWA,有损Web的未来 16
iView 一周年了,同时发布了 2.0 正式版,但这只是开始... 16
nodejs+mongodb构建一个简单登录注册功能 16
【译】JavaScript数据结构(4):树 16
组件化开发与黑箱 16
TypeScript - 不止稳,而且快 16
webpack3+anujs+ReactCSSTransitionGroup 16
原生js实现图片放大镜效果 16
WEB缓存探究第二弹——实战 16
纯笔记:vfork 的一些使用场景(顺便讲一下 fork 的原理) 16
Android APP 内部捐赠实现(支付宝&amp;微信) 16
WKWebView 的一些小总结 16
模型评价(一) AUC大法 16
开始使用GraphQL 16
Webpack模块化原理简析 16
gulp使用问题记录 16
使用Angular4动画为页面添彩 16
Python27 Matplotlib (win64 python2.7) 安装及简单使用 16