smtp_client.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. /*************************************************
  2. Copyright (c) 2019
  3. All rights reserved.
  4. File name: smtp_client.c
  5. Description: smtp源文件
  6. History:
  7. 1. Version: V1.0.0
  8. Date: 2019-10-10
  9. Author: WKJay
  10. Modify: 新建
  11. 2. Version: V1.0.1
  12. Date: 2019-10-28
  13. Author: WKJay
  14. Modify: 增加多个收件人功能
  15. 3. Version: V1.0.2
  16. Date: 2020-06-22
  17. Author: WKJay
  18. Modify: 增加附件功能
  19. *************************************************/
  20. #include <stdint.h>
  21. #include <string.h>
  22. #include <sys/socket.h>
  23. #include <dfs_posix.h>
  24. #include "smtp_client_private.h"
  25. #include "smtp_client_data.h"
  26. #include "smtp_client.h"
  27. #include "netdb.h"
  28. smtp_session_t smtp_session;
  29. #ifdef SMTP_CLIENT_USING_ATTACHMENT
  30. /**
  31. * Name: smtp_add_attachment
  32. * Brief: 添加附件
  33. * Input:
  34. * @file_path: 文件路径
  35. * @file_name: 文件名
  36. * Output: 成功:0 , 失败:-1
  37. */
  38. int smtp_add_attachment(char *file_path, char *file_name)
  39. {
  40. FILE *fp = NULL;
  41. if (strlen(file_path) > SMTP_MAX_FILE_PATH_LEN)
  42. {
  43. LOG_E("attachment's file path too large");
  44. return -1;
  45. }
  46. if (strlen(file_name) > SMTP_ATTACHMENT_MAX_NAME_LEN)
  47. {
  48. LOG_E("attachment's file name too large");
  49. return -1;
  50. }
  51. fp = fopen(file_path, "r");
  52. if (fp == NULL)
  53. {
  54. LOG_E("cannot open file %s", file_path);
  55. return -1;
  56. }
  57. fclose(fp);
  58. if (!smtp_session.attachments)
  59. {
  60. smtp_session.attachments = rt_malloc(sizeof(smtp_attachments_t));
  61. if (smtp_session.attachments)
  62. {
  63. rt_memset(smtp_session.attachments, 0, sizeof(smtp_attachments_t));
  64. rt_memcpy(smtp_session.attachments->file_path, file_path, strlen(file_path));
  65. rt_memcpy(smtp_session.attachments->file_name, file_name, strlen(file_name));
  66. }
  67. else
  68. {
  69. LOG_E("attachment memory allocate failed");
  70. return -1;
  71. }
  72. }
  73. else
  74. {
  75. smtp_attachments_t *cur_att = smtp_session.attachments;
  76. while (cur_att->next)
  77. {
  78. cur_att = cur_att->next;
  79. }
  80. cur_att->next = rt_malloc(sizeof(smtp_attachments_t));
  81. if (cur_att->next)
  82. {
  83. rt_memset(cur_att->next, 0, sizeof(smtp_attachments_t));
  84. rt_memcpy(cur_att->next->file_path, file_path, strlen(file_path));
  85. rt_memcpy(cur_att->next->file_name, file_name, strlen(file_name));
  86. }
  87. else
  88. {
  89. LOG_E("attachment memory allocate failed");
  90. return -1;
  91. }
  92. }
  93. return 0;
  94. }
  95. //清除所有附件
  96. void smtp_clear_attachments(void)
  97. {
  98. smtp_attachments_t *cur_attr, *next_attr;
  99. for (cur_attr = smtp_session.attachments; cur_attr; cur_attr = next_attr)
  100. {
  101. next_attr = cur_attr->next;
  102. LOG_D("delete attachment:%s", cur_attr->file_path);
  103. rt_free(cur_attr);
  104. }
  105. smtp_session.attachments = NULL;
  106. }
  107. #endif
  108. /**
  109. * Name: smtp_client_init
  110. * Brief: 初始化smtp客户端
  111. * Input: None
  112. * Output: None
  113. */
  114. void smtp_client_init(void)
  115. {
  116. memset(&smtp_session, 0, sizeof(smtp_session_t));
  117. }
  118. /**
  119. * Name: smtp_close_connection
  120. * Brief: smtp关闭连接,释放资源
  121. * Input: None
  122. * Output: 成功0,失败-1
  123. */
  124. static int smtp_close_connection(void)
  125. {
  126. int server_port_num = atoi(smtp_session.server_port);
  127. if (server_port_num == 25)
  128. {
  129. return closesocket(smtp_session.conn_fd);
  130. }
  131. #ifdef SMTP_CLIENT_USING_TLS
  132. else if (server_port_num == 465 || server_port_num == 587)
  133. {
  134. return smtp_mbedtls_close_connection();
  135. }
  136. #endif
  137. else
  138. {
  139. return -1;
  140. }
  141. }
  142. /**
  143. * Name: smtp_set_server_addr
  144. * Brief: 设置邮箱服务器域名和端口
  145. * 地址最大长度由 SMTP_MAX_ADDR_LEN 定义
  146. * Input:
  147. * @server_addr: 服务器地址
  148. * @addr_type: 地址类型
  149. * ADDR_TYPE_DOMAIN 域名类型
  150. * ADDR_TYPE_IP IP地址类型
  151. * @port: 服务器端口
  152. * Output: 0:设置成功,-1,:设置失败
  153. */
  154. int smtp_set_server_addr(const char *server_addr, uint8_t addr_type, const char *port)
  155. {
  156. uint16_t addr_len = 0;
  157. if (server_addr != NULL)
  158. {
  159. addr_len = strlen(server_addr);
  160. }
  161. else
  162. {
  163. LOG_E("server addr is null!");
  164. return -1;
  165. }
  166. if (addr_type == ADDRESS_TYPE_DOMAIN)
  167. {
  168. if (smtp_session.server_domain)
  169. {
  170. rt_free(smtp_session.server_domain);
  171. }
  172. smtp_session.server_domain = rt_strdup(server_addr);
  173. }
  174. else
  175. {
  176. if (addr_len > 15)
  177. {
  178. LOG_E("server addr type error!");
  179. return -1;
  180. }
  181. else
  182. {
  183. if (smtp_session.server_ip)
  184. {
  185. rt_free(smtp_session.server_ip);
  186. }
  187. smtp_session.server_ip = rt_strdup(server_addr);
  188. }
  189. }
  190. if (strlen(port) <= 0)
  191. {
  192. LOG_E("server port is null!");
  193. return -1;
  194. }
  195. else
  196. {
  197. if (smtp_session.server_port)
  198. {
  199. rt_free(smtp_session.server_port);
  200. }
  201. smtp_session.server_port = rt_strdup(port);
  202. }
  203. return 0;
  204. }
  205. /**
  206. * Name: smtp_set_auth
  207. * Brief: 设置连接smtp服务的用户名和密码
  208. * Input:
  209. * @username: 用户名
  210. * @password: 密码
  211. * Output: 设置成功:0,设置失败:-1
  212. */
  213. int smtp_set_auth(const char *username, const char *password)
  214. {
  215. uint32_t username_len = strlen(username);
  216. uint32_t password_len = strlen(password);
  217. if (!(username_len && password_len))
  218. {
  219. LOG_E("username or password invalid!");
  220. return -1;
  221. }
  222. //设置SMTP MAIL FROM属性,该属性必须与用户名一致
  223. if (username_len > SMTP_MAX_ADDR_LEN)
  224. {
  225. LOG_E("sender address id too long");
  226. return -1;
  227. }
  228. memset(smtp_session.address_from, 0, SMTP_MAX_ADDR_LEN);
  229. memset(smtp_session.username, 0, sizeof(smtp_session.username));
  230. memset(smtp_session.password, 0, sizeof(smtp_session.password));
  231. memcpy(smtp_session.address_from, username, username_len);
  232. if (smtp_base64_encode(smtp_session.username, SMTP_MAX_AUTH_LEN * 2, username, username_len) == 0)
  233. {
  234. LOG_E("username encode error!");
  235. return -1;
  236. }
  237. if (smtp_base64_encode(smtp_session.password, SMTP_MAX_AUTH_LEN * 2, password, password_len) == 0)
  238. {
  239. LOG_E("password encode error!");
  240. return -1;
  241. }
  242. return 0;
  243. }
  244. /**
  245. * Name: smtp_connect_server_by_hostname
  246. * Brief: 通过域名连接smtp服务器
  247. * Input: None
  248. * Output: 成功0,失败-1
  249. */
  250. static int smtp_connect_server_by_hostname(void)
  251. {
  252. int result = -1;
  253. char buf[3];
  254. struct addrinfo hints, *addr_list, *cur;
  255. memset(&hints, 0, sizeof(hints));
  256. hints.ai_family = AF_INET;
  257. hints.ai_socktype = SOCK_STREAM;
  258. hints.ai_protocol = IPPROTO_TCP;
  259. if (getaddrinfo(smtp_session.server_domain, smtp_session.server_port, &hints, &addr_list) != 0)
  260. {
  261. LOG_E("unknow server domain!");
  262. return -1;
  263. }
  264. for (cur = addr_list; cur != NULL; cur = cur->ai_next)
  265. {
  266. smtp_session.conn_fd = (int)socket(cur->ai_family, cur->ai_socktype,
  267. cur->ai_protocol);
  268. if (smtp_session.conn_fd < 0)
  269. {
  270. result = -1;
  271. continue;
  272. }
  273. if (connect(smtp_session.conn_fd, cur->ai_addr, (uint32_t)cur->ai_addrlen) == 0)
  274. {
  275. if (read(smtp_session.conn_fd, buf, 3) < 3)
  276. {
  277. LOG_E("smtp server connect fail");
  278. smtp_close_connection();
  279. result = -1;
  280. break;
  281. }
  282. else
  283. {
  284. if (memcmp(buf, "220", 3) == 0)
  285. {
  286. LOG_I("smtp server connect success!");
  287. LOG_I("smtp server domain -> %s!", smtp_session.server_domain);
  288. result = 0;
  289. break;
  290. }
  291. else
  292. {
  293. LOG_E("smtp connection response check fail");
  294. smtp_close_connection();
  295. result = -1;
  296. break;
  297. }
  298. }
  299. }
  300. LOG_E("smtp server connect fail");
  301. smtp_close_connection();
  302. result = -1;
  303. }
  304. freeaddrinfo(addr_list);
  305. return result;
  306. }
  307. /**
  308. * Name: smtp_connect_server_by_ip
  309. * Brief: 通过IP连接smtp服务器
  310. * Input: None
  311. * Output: 成功0,失败-1
  312. */
  313. static int smtp_connect_server_by_ip(void)
  314. {
  315. int result = -1;
  316. LOG_E("current version don't support ip connect,please use server domain!");
  317. return result;
  318. }
  319. /**
  320. * Name: smtp_flush
  321. * Brief: 清空smtp数据读取区缓存
  322. * Input: None
  323. * Output: 缓存中的数据个数,失败返回-1
  324. */
  325. static int smtp_flush(void)
  326. {
  327. int result = -1;
  328. int server_port = atoi(smtp_session.server_port);
  329. char buf[SMTP_RESPONSE_MAX_LEN];
  330. while (1)
  331. {
  332. if (server_port == 25)
  333. {
  334. result = read(smtp_session.conn_fd, buf, SMTP_RESPONSE_MAX_LEN);
  335. }
  336. #ifdef SMTP_CLIENT_USING_TLS
  337. else if (server_port == 465)
  338. {
  339. result = smtp_mbedtls_client_read(smtp_session.tls_session, buf, SMTP_RESPONSE_MAX_LEN);
  340. }
  341. else if (server_port == 587)
  342. {
  343. if (smtp_session.state == SMTP_FINISH_START_TLS)
  344. {
  345. return 0;
  346. }
  347. else if (smtp_session.state < SMTP_AUTH_LOGIN)
  348. {
  349. result = read(smtp_session.conn_fd, buf, SMTP_RESPONSE_MAX_LEN);
  350. }
  351. else
  352. {
  353. result = smtp_mbedtls_client_read(smtp_session.tls_session, buf, SMTP_RESPONSE_MAX_LEN);
  354. }
  355. }
  356. #endif
  357. else
  358. {
  359. LOG_E("smtp flush port invalid");
  360. return -1;
  361. }
  362. if (result <= 0)
  363. {
  364. LOG_E("smtp net connection flush fail");
  365. return -1;
  366. }
  367. return result;
  368. }
  369. }
  370. /**
  371. * Name: smtp_write
  372. * Brief: 根据不同的状态调用对应的write
  373. * Input:
  374. * @buf: 要写入的数据
  375. * @len: 写入长度
  376. * Output: 成功写入的个数,错误返回-1
  377. */
  378. static int smtp_write(uint8_t *buf, uint32_t len)
  379. {
  380. int server_port_num = atoi(smtp_session.server_port);
  381. if (server_port_num == 25)
  382. {
  383. return write(smtp_session.conn_fd, buf, len);
  384. }
  385. #ifdef SMTP_CLIENT_USING_TLS
  386. else if (server_port_num == 465)
  387. {
  388. return smtp_mbedtls_client_write(smtp_session.tls_session, buf, len);
  389. }
  390. else if (server_port_num == 587)
  391. {
  392. if (smtp_session.state < SMTP_FINISH_START_TLS)
  393. {
  394. return write(smtp_session.conn_fd, buf, len);
  395. }
  396. else
  397. {
  398. return smtp_mbedtls_client_write(smtp_session.tls_session, buf, len);
  399. }
  400. }
  401. #endif
  402. else
  403. {
  404. return -1;
  405. }
  406. }
  407. /**
  408. * Name: smtp_read
  409. * Brief: 根据不同的状态调用对应的read
  410. * Input:
  411. * @buf: 读取数据的存储区
  412. * @nbyte: 准备读取数据的长度
  413. * Output: 成功读取的个数,错误返回-1
  414. */
  415. static int smtp_read(void *buf, size_t nbyte)
  416. {
  417. int server_port_num = atoi(smtp_session.server_port);
  418. if (server_port_num == 25)
  419. {
  420. return read(smtp_session.conn_fd, buf, nbyte);
  421. }
  422. #ifdef SMTP_CLIENT_USING_TLS
  423. else if (server_port_num == 465)
  424. {
  425. return smtp_mbedtls_client_read(smtp_session.tls_session, buf, nbyte);
  426. }
  427. else if (server_port_num == 587)
  428. {
  429. if (smtp_session.state < SMTP_FINISH_START_TLS)
  430. {
  431. return read(smtp_session.conn_fd, buf, nbyte);
  432. }
  433. else
  434. {
  435. return smtp_mbedtls_client_read(smtp_session.tls_session, buf, nbyte);
  436. }
  437. }
  438. #endif
  439. else
  440. {
  441. return -1;
  442. }
  443. }
  444. /**
  445. * Name: smtp_connect_server
  446. * Brief: smtp连接服务器
  447. * Input: None
  448. * Output: 成功0,失败-1
  449. */
  450. static int smtp_connect_server(void)
  451. {
  452. int server_port_num = atoi(smtp_session.server_port);
  453. if (server_port_num == 25)
  454. {
  455. if (smtp_session.server_ip)
  456. {
  457. return smtp_connect_server_by_ip();
  458. }
  459. else if (smtp_session.server_domain)
  460. {
  461. return smtp_connect_server_by_hostname();
  462. }
  463. else
  464. {
  465. LOG_E("cannot find ip and domain");
  466. return -1;
  467. }
  468. }
  469. #ifdef SMTP_CLIENT_USING_TLS
  470. else if (server_port_num == 465)
  471. {
  472. return smtp_connect_server_by_tls();
  473. }
  474. else if (server_port_num == 587)
  475. {
  476. return smtp_connect_server_by_starttls();
  477. }
  478. #endif
  479. else
  480. {
  481. LOG_E("invalid port number!");
  482. return -1;
  483. }
  484. }
  485. /**
  486. * Name: smtp_send_data_with_response_check
  487. * Brief: smtp数据发送并校验响应
  488. * Input:
  489. * @buf: 待发送的数据
  490. * @response_code: 正确响应码
  491. * Output: 成功0,失败-1
  492. */
  493. static int smtp_send_data_with_response_check(char *buf, char *response_code)
  494. {
  495. char response_code_buf[3];
  496. memset(response_code_buf, 0, 3);
  497. if (smtp_session.conn_fd == 0
  498. #ifdef SMTP_CLIENT_USING_TLS
  499. && smtp_session.tls_session == 0)
  500. #else
  501. )
  502. #endif
  503. {
  504. LOG_E("cannot find net fd");
  505. return -1;
  506. }
  507. else
  508. {
  509. smtp_flush();
  510. if (smtp_write((uint8_t *)buf, strlen(buf)) != strlen(buf))
  511. {
  512. LOG_E("smtp send fail");
  513. smtp_close_connection();
  514. return -1;
  515. }
  516. else
  517. {
  518. if (smtp_read(response_code_buf, 3) < 3)
  519. {
  520. LOG_E("smtp read response fail");
  521. smtp_close_connection();
  522. return -1;
  523. }
  524. if (memcmp(response_code, response_code_buf, 3) != 0)
  525. {
  526. LOG_E("smtp check response fail");
  527. smtp_close_connection();
  528. return -1;
  529. }
  530. else
  531. {
  532. return 0;
  533. }
  534. }
  535. }
  536. }
  537. /**
  538. * Name: smtp_handshake
  539. * Brief: smtp握手认证
  540. * Input: None
  541. * Output: 成功0,失败-1
  542. */
  543. static int smtp_handshake(void)
  544. {
  545. int result = -1;
  546. result = smtp_send_data_with_response_check(SMTP_CMD_EHLO, "250");
  547. if (result != 0)
  548. {
  549. LOG_E("smtp helo fail");
  550. return -1;
  551. }
  552. #ifdef SMTP_CLIENT_USING_TLS
  553. //STARTTLS
  554. if (atoi(smtp_session.server_port) == 587)
  555. {
  556. smtp_session.state = SMTP_START_TLS;
  557. if (smtp_send_data_with_response_check(SMTP_CMD_STARTTLS, "220") != 0)
  558. {
  559. LOG_E("smtp start tls fail");
  560. smtp_close_connection();
  561. return -1;
  562. }
  563. smtp_flush();
  564. if (smtp_mbedtls_starttls(smtp_session.tls_session) != 0)
  565. {
  566. LOG_E("smtp start tls handshake fail");
  567. return -1;
  568. }
  569. return 0;
  570. }
  571. #endif
  572. return result;
  573. }
  574. /**
  575. * Name: smtp_auth_login
  576. * Brief: smtp用户登录
  577. * Input: None
  578. * Output: 成功0,失败-1
  579. */
  580. static int smtp_auth_login(void)
  581. {
  582. char auth_info_buf[SMTP_MAX_AUTH_LEN * 2 + 2];
  583. memset(auth_info_buf, 0, SMTP_MAX_AUTH_LEN * 2 + 2);
  584. #ifdef SMTP_CLIENT_USING_TLS
  585. if (atoi(smtp_session.server_port) == 587)
  586. {
  587. smtp_session.state = SMTP_FINISH_START_TLS;
  588. }
  589. #endif
  590. if (smtp_send_data_with_response_check(SMTP_CMD_AUTHLOGIN, "334") != 0)
  591. {
  592. LOG_E("smtp auth login fail");
  593. smtp_close_connection();
  594. return -1;
  595. }
  596. #ifdef SMTP_CLIENT_USING_TLS
  597. if (atoi(smtp_session.server_port) == 587)
  598. {
  599. smtp_session.state = SMTP_AUTH_LOGIN;
  600. }
  601. #endif
  602. //发送用户名信息
  603. sprintf(auth_info_buf, "%s\r\n", smtp_session.username);
  604. if (smtp_send_data_with_response_check(auth_info_buf, "334") != 0)
  605. {
  606. LOG_E("smtp send username fail");
  607. smtp_close_connection();
  608. return -1;
  609. }
  610. //发送密码信息
  611. sprintf(auth_info_buf, "%s\r\n", smtp_session.password);
  612. if (smtp_send_data_with_response_check(auth_info_buf, "235") != 0)
  613. {
  614. LOG_E("smtp password invalid");
  615. smtp_close_connection();
  616. return -1;
  617. }
  618. return 0;
  619. }
  620. /**
  621. * Name: smtp_set_sender_receiver
  622. * Brief: smtp设置邮箱的发件人与收件人
  623. * Input: None
  624. * Output: 发送成功0,发送失败-1
  625. */
  626. static int smtp_set_sender_receiver(void)
  627. {
  628. uint16_t mail_buf_len = SMTP_MAX_ADDR_LEN + strlen(SMTP_CMD_MAIL_HEAD) + strlen(SMTP_CMD_MAIL_END);
  629. uint16_t rcpt_buf_len = SMTP_MAX_ADDR_LEN + strlen(SMTP_CMD_RCPT_HEAD) + strlen(SMTP_CMD_RCPT_END);
  630. //使用较大的长度
  631. uint16_t buf_len = (mail_buf_len > rcpt_buf_len) ? mail_buf_len : rcpt_buf_len;
  632. smtp_address_to_t *smtp_address_to_temp = smtp_session.address_to;
  633. char addr_info_buf[buf_len];
  634. memset(addr_info_buf, 0, buf_len);
  635. sprintf(addr_info_buf, "%s%s%s", SMTP_CMD_MAIL_HEAD, smtp_session.address_from, SMTP_CMD_MAIL_END);
  636. if (smtp_send_data_with_response_check(addr_info_buf, "250") != 0)
  637. {
  638. LOG_E("smtp set mail from fail");
  639. smtp_close_connection();
  640. return -1;
  641. }
  642. while (smtp_address_to_temp)
  643. {
  644. sprintf(addr_info_buf, "%s%s%s", SMTP_CMD_RCPT_HEAD, smtp_address_to_temp->addr, SMTP_CMD_RCPT_END);
  645. if (smtp_send_data_with_response_check(addr_info_buf, "250") != 0)
  646. {
  647. LOG_E("smtp set rcpt to fail");
  648. smtp_close_connection();
  649. return -1;
  650. }
  651. smtp_address_to_temp = smtp_address_to_temp->next;
  652. }
  653. return 0;
  654. }
  655. /**
  656. * Name: smtp_send_content
  657. * Brief: smtp发送附件
  658. * Input: None
  659. * Output: None
  660. */
  661. static void smtp_send_attachment(void)
  662. {
  663. uint16_t attachments_cnt = 0;
  664. uint8_t attachment_buf[SMTP_SEND_DATA_MAX_LEN];
  665. smtp_attachments_t *cur_attr = smtp_session.attachments;
  666. while (cur_attr)
  667. {
  668. FILE *fp = fopen(cur_attr->file_path, "r");
  669. if (fp)
  670. {
  671. uint32_t read_size = 0;
  672. if (attachments_cnt < SMTP_MAX_ATTACHMENTS)
  673. {
  674. attachments_cnt++;
  675. }
  676. else
  677. {
  678. break;
  679. }
  680. //发送附件头
  681. rt_memset(attachment_buf, 0, sizeof(attachment_buf));
  682. sprintf((char *)attachment_buf,
  683. "--" SMTP_MAIL_BOUNDARY "\r\n"
  684. "Content-Type: text/plain; name=\"%s\"\r\n"
  685. "Content-Transfer-Encoding: binary\r\n"
  686. "Content-Disposition: attachment; filename=\"%s\"\r\n\r\n",
  687. cur_attr->file_name, cur_attr->file_name);
  688. smtp_write(attachment_buf, strlen((char *)attachment_buf));
  689. //发送附件数据
  690. rt_memset(attachment_buf, 0, sizeof(attachment_buf));
  691. read_size = fread(attachment_buf, 1, sizeof(attachment_buf), fp);
  692. while (read_size == sizeof(attachment_buf))
  693. {
  694. smtp_write(attachment_buf, read_size);
  695. read_size = fread(attachment_buf, 1, sizeof(attachment_buf), fp);
  696. rt_thread_mdelay(1);
  697. }
  698. smtp_write(attachment_buf, read_size);
  699. smtp_write((uint8_t *)"\r\n\r\n", strlen("\r\n\r\n"));
  700. fclose(fp);
  701. }
  702. else
  703. {
  704. LOG_E("add attachment %s failed,path: %s", cur_attr->file_name, cur_attr->file_path);
  705. }
  706. cur_attr = cur_attr->next;
  707. }
  708. if (attachments_cnt > 0)
  709. smtp_write((uint8_t *)("--" SMTP_MAIL_BOUNDARY "--\r\n"), strlen("--" SMTP_MAIL_BOUNDARY "--\r\n"));
  710. }
  711. /**
  712. * Name: smtp_send_content
  713. * Brief: smtp发送邮件内容
  714. * Input: None
  715. * Output: 发送成功0,发送失败-1
  716. */
  717. static int smtp_send_content(void)
  718. {
  719. char content_buf[SMTP_SEND_DATA_HEAD_MAX_LENGTH + SMTP_SEND_DATA_MAX_LEN];
  720. memset(content_buf, 0, SMTP_SEND_DATA_HEAD_MAX_LENGTH + SMTP_SEND_DATA_MAX_LEN);
  721. if (smtp_send_data_with_response_check(SMTP_CMD_DATA, "354") != 0)
  722. {
  723. LOG_E("smtp send data cmd fail");
  724. smtp_close_connection();
  725. return -1;
  726. }
  727. //拼接内容
  728. #ifdef SMTP_CLIENT_USING_ATTACHMENT
  729. if (smtp_session.attachments)
  730. {
  731. sprintf(content_buf,
  732. "FROM:<%s>\r\n"
  733. "TO:<%s>\r\n"
  734. "SUBJECT:%s\r\n"
  735. "Content-Type: multipart/mixed;"
  736. "boundary=\"smtp_client_boundary\"\r\n\r\n"
  737. "--" SMTP_MAIL_BOUNDARY "\r\n"
  738. "Content-Type: text/plain; charset=\"utf-8\"\r\n"
  739. "Content-Transfer-Encoding: 7bit\r\n\r\n"
  740. "%s\r\n\r\n",
  741. smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
  742. }
  743. else
  744. {
  745. sprintf(content_buf,
  746. "FROM: <%s>\r\n"
  747. "TO: <%s>\r\n"
  748. "SUBJECT:%s\r\n\r\n"
  749. "%s\r\n\r\n",
  750. smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
  751. }
  752. #else
  753. sprintf(content_buf,
  754. "FROM: <%s>\r\n"
  755. "TO: <%s>\r\n"
  756. "SUBJECT:%s\r\n\r\n"
  757. "%s\r\n\r\n",
  758. smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
  759. #endif
  760. smtp_write((uint8_t *)content_buf, strlen(content_buf));
  761. #ifdef SMTP_CLIENT_USING_ATTACHMENT
  762. smtp_send_attachment();
  763. #endif
  764. if (smtp_send_data_with_response_check(SMTP_CMD_BODY_FINISHED, "250") != 0)
  765. {
  766. LOG_E("smtp send data content fail");
  767. smtp_close_connection();
  768. return -1;
  769. }
  770. return 0;
  771. }
  772. /**
  773. * Name: smtp_quit
  774. * Brief: smtp 结束一次完整的通信
  775. * Input: None
  776. * Output: 成功0,失败-1
  777. */
  778. static int smtp_quit(void)
  779. {
  780. if (smtp_send_data_with_response_check(SMTP_CMD_QUIT, "221") != 0)
  781. {
  782. LOG_E("smtp quit fail");
  783. smtp_close_connection();
  784. return -1;
  785. }
  786. LOG_I("smtp mail send sussess!");
  787. //关闭连接
  788. smtp_close_connection();
  789. LOG_I("close smtp connection!");
  790. return 0;
  791. }
  792. /**
  793. * Name: smtp_send
  794. * Brief: 真实的发送函数
  795. * Input:
  796. * Output: 发送成功0,发送失败-1
  797. */
  798. static int smtp_send(void)
  799. {
  800. //连接服务器
  801. smtp_session.state = SMTP_NULL;
  802. if (smtp_connect_server() != 0)
  803. {
  804. return -1;
  805. }
  806. //握手确认
  807. smtp_session.state = SMTP_HELO;
  808. if (smtp_handshake() != 0)
  809. {
  810. return -1;
  811. }
  812. //用户认证
  813. smtp_session.state = SMTP_AUTH_LOGIN;
  814. if (smtp_auth_login() != 0)
  815. {
  816. return -1;
  817. }
  818. //设置发件人与收件人
  819. smtp_session.state = SMTP_MAIL;
  820. if (smtp_set_sender_receiver() != 0)
  821. {
  822. return -1;
  823. }
  824. //发送数据
  825. smtp_session.state = SMTP_DATA;
  826. if (smtp_send_content() != 0)
  827. {
  828. return -1;
  829. }
  830. //结束
  831. smtp_session.state = SMTP_QUIT;
  832. if (smtp_quit() != 0)
  833. {
  834. return -1;
  835. }
  836. return 0;
  837. }
  838. /**
  839. * Name: smtp_send_mail
  840. * Brief: smtp邮件发送
  841. * Input:
  842. * @subject: 主题
  843. * @body: 内容
  844. * Output: 成功0,失败-1
  845. */
  846. int smtp_send_mail(char *subject, char *body)
  847. {
  848. if (subject == NULL)
  849. {
  850. LOG_E("subject is null!");
  851. return -1;
  852. }
  853. else
  854. {
  855. smtp_session.subject = subject;
  856. }
  857. if (body == NULL)
  858. {
  859. LOG_E("body is null!");
  860. return -1;
  861. }
  862. else
  863. {
  864. smtp_session.body = body;
  865. }
  866. //调用真实的发送函数
  867. return smtp_send();
  868. }
  869. /**
  870. * Name: smtp_add_receiver
  871. * Brief: 增加收件人
  872. * Input:
  873. * @receiver_addr: 收件人地址
  874. * Output: 成功返回0,失败返回-1
  875. */
  876. int smtp_add_receiver(char *receiver_addr)
  877. {
  878. smtp_address_to_t *smtp_address_to_temp = RT_NULL;
  879. //用于释放问题节点
  880. smtp_address_to_t *smtp_address_to_free_temp = RT_NULL;
  881. if (receiver_addr == RT_NULL)
  882. {
  883. LOG_E("receiver addr is null");
  884. return -1;
  885. }
  886. if (smtp_session.address_to == RT_NULL)
  887. {
  888. smtp_session.address_to = rt_malloc(sizeof(smtp_address_to_t));
  889. if (smtp_session.address_to == RT_NULL)
  890. {
  891. LOG_E("smtp receiver address node allocate fail");
  892. return -1;
  893. }
  894. memset(smtp_session.address_to, 0, sizeof(smtp_address_to_t));
  895. smtp_address_to_temp = smtp_session.address_to;
  896. }
  897. else
  898. {
  899. smtp_address_to_temp = smtp_session.address_to;
  900. while (smtp_address_to_temp->next != RT_NULL)
  901. {
  902. smtp_address_to_temp = smtp_address_to_temp->next;
  903. }
  904. smtp_address_to_temp->next = rt_malloc(sizeof(smtp_address_to_t));
  905. smtp_address_to_temp = smtp_address_to_temp->next;
  906. if (smtp_address_to_temp == RT_NULL)
  907. {
  908. LOG_E("smtp receiver address node allocate fail");
  909. return -1;
  910. }
  911. memset(smtp_address_to_temp, 0, sizeof(smtp_address_to_t));
  912. }
  913. //新建一个收件人地址存储区
  914. smtp_address_to_temp->addr = rt_malloc(strlen(receiver_addr) + 1);
  915. if (smtp_address_to_temp->addr == RT_NULL)
  916. {
  917. LOG_E("smtp receiver address string allocate fail");
  918. LOG_W("start to free address node");
  919. //找出需要释放节点的上一个节点,并将其next指向空
  920. smtp_address_to_free_temp = smtp_session.address_to;
  921. while (smtp_address_to_free_temp->next != smtp_address_to_temp)
  922. {
  923. smtp_address_to_free_temp = smtp_address_to_free_temp->next;
  924. }
  925. smtp_address_to_free_temp->next = RT_NULL;
  926. //释放问题节点
  927. rt_free(smtp_address_to_temp);
  928. LOG_I("address node free success!");
  929. return -1;
  930. }
  931. memset(smtp_address_to_temp->addr, 0, strlen(receiver_addr) + 1);
  932. memcpy(smtp_address_to_temp->addr, receiver_addr, strlen(receiver_addr));
  933. return 0;
  934. }
  935. /**
  936. * Name: smtp_clear_receiver
  937. * Brief: 删除所有收件人
  938. * Input: None
  939. * Output: None
  940. */
  941. void smtp_clear_receiver(void)
  942. {
  943. //上一个节点指针
  944. smtp_address_to_t *cur_receiver, *next_receiver;
  945. for (cur_receiver = smtp_session.address_to; cur_receiver; cur_receiver = next_receiver)
  946. {
  947. next_receiver = cur_receiver->next;
  948. LOG_D("delete receiver:%s", cur_receiver->addr);
  949. rt_free(cur_receiver->addr);
  950. rt_free(cur_receiver);
  951. }
  952. smtp_session.address_to = NULL;
  953. }
  954. /**
  955. * Name: smtp_delete_receiver
  956. * Brief: 删除某个收件人
  957. * Input:
  958. * @receiver_addr: 收件人地址
  959. * Output: 成功返回0,失败返回-1
  960. */
  961. int smtp_delete_receiver(char *receiver_addr)
  962. {
  963. //上一个节点指针
  964. smtp_address_to_t *smtp_address_to_last = RT_NULL;
  965. //待删除节点指针
  966. smtp_address_to_t *smtp_address_to_delete = RT_NULL;
  967. //将待删除指针指向收件人链表头结点
  968. smtp_address_to_delete = smtp_session.address_to;
  969. while (smtp_address_to_delete)
  970. {
  971. if (memcmp(smtp_address_to_delete->addr, receiver_addr, strlen(receiver_addr)) == 0)
  972. {
  973. //不存在上一个节点,则当前节点为第一个节点
  974. if (smtp_address_to_last == RT_NULL)
  975. {
  976. //若有下一个节点则第一个节点指向待删除的下一个节点,若没有则为空
  977. smtp_session.address_to = smtp_address_to_delete->next;
  978. //释放内存
  979. rt_free(smtp_address_to_delete->addr);
  980. rt_free(smtp_address_to_delete);
  981. return 0;
  982. }
  983. else
  984. {
  985. //若有下一个节点则第一个节点指向待删除的下一个节点,若没有则为空
  986. smtp_address_to_last->next = smtp_address_to_delete->next;
  987. //释放内存
  988. rt_free(smtp_address_to_delete->addr);
  989. rt_free(smtp_address_to_delete);
  990. return 0;
  991. }
  992. }
  993. else
  994. {
  995. smtp_address_to_last = smtp_address_to_delete;
  996. smtp_address_to_delete = smtp_address_to_delete->next;
  997. }
  998. }
  999. LOG_W("smtp delete receiver fail, cannot find receiver : %s", receiver_addr);
  1000. return -1;
  1001. }