mail.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. #include <stdint.h>
  2. #include <pthread.h>
  3. #include "cfg.h"
  4. #include "common.h"
  5. #include "thread.h"
  6. #include "xlist.h"
  7. #include "elog.h"
  8. #include "lock.h"
  9. #include "sqlite_handle.h"
  10. #include <curl/curl.h>
  11. #include "mail.h"
  12. #if 1
  13. #define LOGD log_d
  14. #define LOGE log_e
  15. #define LOGW log_w
  16. #else
  17. #define LOGD printf
  18. #define LOGE printf
  19. #define LOGW printf
  20. #endif
  21. typedef struct {
  22. char sub[128];
  23. char body[2048];
  24. char attach[128];
  25. }mail_pkt_t;
  26. typedef struct {
  27. handle_t list;
  28. mail_info_t *info;
  29. GlobalDeviceManager *dm;
  30. int inited;
  31. }mail_handle_t;
  32. static mail_handle_t maHandle;
  33. static char send_buff[4096];
  34. struct upload_status
  35. {
  36. size_t bytes_read;
  37. };
  38. static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
  39. {
  40. struct upload_status *upload_ctx = (struct upload_status *)userp;
  41. const char *data;
  42. size_t room = size * nmemb;
  43. if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
  44. return 0;
  45. }
  46. data = &send_buff[upload_ctx->bytes_read];
  47. if(data) {
  48. size_t len = strlen(data);
  49. if(room < len)
  50. len = room;
  51. memcpy(ptr, data, len);
  52. upload_ctx->bytes_read += len;
  53. return len;
  54. }
  55. return 0;
  56. }
  57. static void fill_send_buff(char *dst_buf, const char *to,const char *from,const char *subject,const char *body)
  58. {
  59. time_t timer;//time_t就是long int 类型
  60. struct tm *tblock;
  61. timer = time(NULL);
  62. tblock = localtime(&timer);
  63. sprintf(dst_buf,"Subject: %s\r\n"
  64. "From: %s\r\n"
  65. "To: %s\r\n"
  66. "Date: %s\r\n"
  67. "\r\n"
  68. "%s\r\n"
  69. "\r\n",subject,from,to,asctime(tblock),body);
  70. }
  71. static int curl_add_files(curl_mime *mm, char *attach)
  72. {
  73. curl_mimepart *part;
  74. int nlen=strlen(attach);
  75. char *p,*tmp=strdup(attach),*p2;
  76. if(!tmp) {
  77. return -1;
  78. }
  79. p = tmp;
  80. p2 = tmp+nlen;
  81. while(*p) {
  82. if((*p)==';') *p=0;
  83. p++;
  84. }
  85. p = tmp;
  86. while(1) {
  87. if(p>=p2) break;
  88. part = curl_mime_addpart(mm);
  89. if(!part) {
  90. printf("____part is null!\n");
  91. free(tmp); return -1;
  92. }
  93. curl_mime_name(part, "file");
  94. curl_mime_filedata(part, p);
  95. p += strlen(p)+1;
  96. }
  97. free(tmp);
  98. return 0;
  99. }
  100. static int send_mail(mail_send_t *send, void *addr, char *sub, char *body, char *attach, int multi)
  101. {
  102. int i=0;
  103. CURLcode r=CURLE_OK;
  104. char tmp[100];
  105. char url_buff[256]={0};
  106. char to_buff[256]={0};
  107. mail_handle_t *h=&maHandle;
  108. struct upload_status upload_ctx = { 0 };
  109. struct curl_slist *recipients = NULL;
  110. mail_recv_t *recv=(mail_recv_t*)addr;
  111. curl_mime *mm=NULL,*alt=NULL;
  112. curl_mimepart *part=NULL;
  113. struct curl_slist *slist=NULL;
  114. struct curl_slist *headers=NULL;
  115. const char **cpp;
  116. lock_s_hold(LOCK_ID_MAIL);
  117. CURL *curl = curl_easy_init();
  118. if(!curl) {
  119. goto out;
  120. }
  121. sprintf(url_buff,"%s:%s",send->server,send->port);
  122. r = curl_easy_setopt(curl,CURLOPT_URL,url_buff);
  123. //curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "EXPN");
  124. //curl_easy_setopt(curl, CURLOPT_MAIL_AUTH, "<secret@cave>");
  125. //curl_easy_setopt(curl, CURLOPT_SASL_AUTHZID, "ursel");
  126. //sprintf(tmp, "AUTH=%s", send->auth);
  127. //curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, tmp);
  128. r = curl_easy_setopt(curl, CURLOPT_USERNAME, send->account); //setting user
  129. r = curl_easy_setopt(curl, CURLOPT_PASSWORD, send->password); //setting password
  130. if(strcmp(send->port, "587")==0) { //tls
  131. r = curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); //setting openssl/tls
  132. //curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem");
  133. }
  134. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
  135. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
  136. //curl_easy_setopt(curl, CURLOPT_USERAGENT, CLIENT_USERAGENT);
  137. r = curl_easy_setopt(curl, CURLOPT_MAIL_FROM, send->account);
  138. r = curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
  139. r = curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
  140. if(multi) {
  141. for(int i=0; i<MAIL_RECV_MAX; i++) {
  142. if(recv[i].use && strlen(recv[i].account)>0) {
  143. recipients = curl_slist_append(recipients, recv[i].account);
  144. //recipients = curl_slist_append(recipients, CC_MAIL);
  145. strcat(to_buff,recv[i].account);
  146. strcat(to_buff,";");
  147. }
  148. }
  149. }
  150. else {
  151. char *sendto=(char*)addr;
  152. recipients = curl_slist_append(recipients,sendto);
  153. strcat(to_buff,sendto);
  154. strcat(to_buff,";");
  155. }
  156. fill_send_buff(send_buff,to_buff,send->account,sub,body);
  157. if(attach && strlen(attach)>0) {
  158. mm = curl_mime_init(curl);
  159. alt = curl_mime_init(curl);
  160. headers = curl_slist_append(headers, send_buff);
  161. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  162. part = curl_mime_addpart(alt);
  163. curl_mime_data(part, sub, CURL_ZERO_TERMINATED);
  164. part = curl_mime_addpart(mm);
  165. curl_mime_subparts(part, alt);
  166. curl_mime_type(part, "multipart/alternative");
  167. slist = curl_slist_append(NULL, "Content-Disposition: inline");
  168. curl_mime_headers(part, slist, 1);
  169. //part = curl_mime_addpart(mm);
  170. //curl_mime_name(part, "file");
  171. //curl_mime_filedata(part, attach);
  172. curl_add_files(mm, attach);
  173. curl_easy_setopt(curl, CURLOPT_MIMEPOST, mm);
  174. }
  175. r = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
  176. r = curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
  177. r = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  178. r = curl_easy_perform(curl);
  179. if(r != CURLE_OK) {
  180. LOGE("send mail failed, %s\n", curl_easy_strerror(r));
  181. }
  182. else {
  183. LOGD("send mail ok!\n");
  184. }
  185. curl_slist_free_all(recipients);
  186. curl_mime_free(mm);
  187. out:
  188. if(curl) curl_easy_cleanup(curl);
  189. lock_s_release(LOCK_ID_MAIL);
  190. return (r==CURLE_OK)?0:-1;
  191. }
  192. ////////////////////////////////////////////////////////////////////////////
  193. static void sleep_ms(int ms)
  194. {
  195. usleep(ms*1000);
  196. }
  197. static void* mail_thread(void *arg)
  198. {
  199. #ifdef USE_MAIL
  200. int r;
  201. thread_handle_t *th=(thread_handle_t*)arg;
  202. mail_handle_t *h=(mail_handle_t*)th->arg;
  203. list_node_t *ln=NULL;
  204. mail_pkt_t *pkt=NULL;
  205. mail_send_t *send=&h->info->send;
  206. mail_recv_t *recv=h->info->recv;
  207. while(th->quit==0) {
  208. r = xlist_take_node(h->list, &ln, 0);
  209. if(r==0) {
  210. pkt = (mail_pkt_t*)ln->data.buf;
  211. send_mail(send, recv, pkt->sub, pkt->body, pkt->attach, 1);
  212. xlist_back_node(h->list, ln);
  213. }
  214. sleep_ms(100);
  215. }
  216. #endif
  217. pthread_exit(NULL);
  218. }
  219. int mail_init(void)
  220. {
  221. #ifdef USE_MAIL
  222. list_cfg_t lc;
  223. mail_handle_t *h=&maHandle;
  224. GlobalDeviceManager *dm=&__globalDeviceManage;
  225. lc.mode = LIST_FULL_FIFO;
  226. lc.max = 100;
  227. lc.log = 0;
  228. h->list = xlist_init(&lc);
  229. h->dm = dm;
  230. h->info = &h->dm->mailInfo;
  231. dev_mail_init(dm->db, h->info);
  232. thread_start(THREAD_ID_MAIL, mail_thread, h);
  233. h->inited = 1;
  234. //mail_test();
  235. #endif
  236. return 0;
  237. }
  238. int mail_deinit(void)
  239. {
  240. #ifdef USE_MAIL
  241. mail_handle_t *h=&maHandle;
  242. thread_stop(THREAD_ID_MAIL);
  243. xlist_free(h->list);
  244. h->inited = 0;
  245. #endif
  246. return 0;
  247. }
  248. static int post_data(char *sub, char *body, char *attach)
  249. {
  250. int r=0;
  251. #ifdef USE_MAIL
  252. mail_pkt_t pkt;
  253. mail_handle_t *h=&maHandle;
  254. snprintf(pkt.sub, sizeof(pkt.sub), "%s", sub?sub:"");
  255. snprintf(pkt.body, sizeof(pkt.body), "%s", body?body:"");
  256. snprintf(pkt.attach, sizeof(pkt.attach), "%s", attach?attach:"");
  257. r = xlist_append(h->list, 0, &pkt, sizeof(pkt));
  258. #endif
  259. return r;
  260. }
  261. int mail_send(char *sub, char *body, char *attach)
  262. {
  263. int r=-1;
  264. #ifdef USE_MAIL
  265. mail_handle_t *h=&maHandle;
  266. if(!h->inited || !h->info || !h->info->send.mode) {
  267. return -1;
  268. }
  269. r = send_mail(&h->info->send, h->info->recv, sub?sub:"", body?body:"", attach?attach:"", 1);
  270. #endif
  271. return r;
  272. }
  273. int mail_post(char *sub, char *body, char *attach)
  274. {
  275. int r=-1;
  276. #ifdef USE_MAIL
  277. mail_handle_t *h=&maHandle;
  278. if(!h->inited || !h->info || !h->info->send.mode) {
  279. return -1;
  280. }
  281. r = post_data(sub, body, attach);
  282. #endif
  283. return r;
  284. }
  285. int mail_post_alarm(int type, int subtype, int alarm_type, char *content)
  286. {
  287. int r=0;
  288. #ifdef USE_MAIL
  289. mail_pkt_t pkt;
  290. char temp[128];
  291. mail_handle_t *h=&maHandle;
  292. if(!h->inited || !content || !h->info || !h->info->send.mode) {
  293. return -1;
  294. }
  295. char *prod_name=h->dm->_globalDevInfo.product.name;
  296. int prod_id=h->dm->_globalDevInfo.product.id;
  297. int langID=h->dm->_globalDevInfo.product.language;
  298. switch(type) {
  299. case ALARM_TYPE_POWER:
  300. {
  301. if(subtype) {
  302. switch(alarm_type) {
  303. case ENABLE_TAC_V_UP:
  304. case ENABLE_TAC_V_DOWN:
  305. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]);
  306. break;
  307. case ENABLE_TAC_A_UP:
  308. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]);
  309. break;
  310. case ENABLE_TAC_W_UP:
  311. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]);
  312. break;
  313. case ENABLE_TAC_P_UP:
  314. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]);
  315. break;
  316. case ENABLE_TAC_STIME:
  317. case ENABLE_TAC_ETIME:
  318. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]);
  319. break;
  320. default:
  321. return -1;
  322. }
  323. }
  324. else {
  325. switch(alarm_type) {
  326. case WARNING_V_UP:
  327. case WARNING_V_DOWN:
  328. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]);
  329. break;
  330. case WARNING_A_UP:
  331. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]);
  332. break;
  333. case WARNING_W_UP:
  334. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]);
  335. break;
  336. case WARNING_P_UP:
  337. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]);
  338. break;
  339. case 0 ... 2:
  340. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]);
  341. break;
  342. default:
  343. return -1;
  344. }
  345. }
  346. }
  347. break;
  348. case ALARM_TYPE_SENSOR:
  349. {
  350. switch(subtype) {
  351. case SENSOR_TYPE_TEMP_DOUBLE:
  352. case SENSOR_TYPE_TEMP_HUMI:
  353. case SENSOR_TYPE_TEMP:
  354. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_temperature[langID], language_alarm[langID]);
  355. break;
  356. case SENSOR_TYPE_SMOKE:
  357. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_smoke[langID], language_alarm[langID]);
  358. break;
  359. case SENSOR_TYPE_WATER:
  360. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_humidity[langID], language_alarm[langID]);
  361. break;
  362. case SENSOR_TYPE_ACCESS:
  363. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_access[langID], language_alarm[langID]);
  364. break;
  365. case SENSOR_TYPE_GAS:
  366. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_gas[langID], language_alarm[langID]);
  367. break;
  368. case SENSOR_TYPE_AIR_PRESS:
  369. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_pressure[langID], language_alarm[langID]);
  370. break;
  371. case SENSOR_TYPE_LEAK:
  372. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_leak[langID], language_alarm[langID]);
  373. break;
  374. default:
  375. return -1;
  376. }
  377. }
  378. break;
  379. case ALARM_TYPE_NETWORK:
  380. {
  381. snprintf(temp, sizeof(temp), "%s %d %s", prod_name, prod_id, language_alarm_Type_Network[langID]);
  382. }
  383. break;
  384. default:
  385. return -1;
  386. }
  387. replace_sequences(content, h->dm->alarmTab);
  388. r = post_data(temp, content, NULL);
  389. #endif
  390. return r;
  391. }
  392. int mail_test(void)
  393. {
  394. int r=0,cnt=0;
  395. #ifdef USE_MAIL
  396. char temp[200];
  397. mail_handle_t *h=&maHandle;
  398. mail_info_t info={
  399. .send = {
  400. .id = 0,
  401. .mode = 1,
  402. #if 0
  403. .account = "rcp064867@163.com",
  404. .password = "YWKVURARCJXYXQVS",
  405. .server = "smtp.163.com",
  406. .port = "25",
  407. //.port = "465",
  408. //.port = "587",
  409. .auth = "PLAIN",
  410. //.auth = "LOGIN",
  411. //.auth = "CRAM-MD5",
  412. #else
  413. .account = "jiuci4902@gmail.com",
  414. .password = "wmfoedxaycdwllvs",
  415. .server = "smtp.gmail.com",
  416. //.port = "25",
  417. //.port = "465",
  418. .port = "587",
  419. //.auth = "PLAIN",
  420. .auth = "LOGIN",
  421. //.auth = "CRAM-MD5",
  422. #endif
  423. },
  424. .recv = {
  425. {0, 1, "1556907721@qq.com"},
  426. {1, 1, "rcp064867@163.com"},
  427. {2, 1, "cijiu0219@sina.com"},
  428. {3, 1, "jiuci4902@gmail.com"},
  429. {4, 1, "cijiu0219@hotmail.com"},
  430. {5, 1, "cijiu990219@outlook.com"},
  431. {6, 1, "iauther@163.com"},
  432. }
  433. };
  434. *h->info = info;
  435. char *sub="123";
  436. char *body="hello everyone";
  437. while(cnt++<5) {
  438. sprintf(temp, "%s %d", body, cnt);
  439. r = mail_send(sub, temp, NULL);
  440. sleep(2);
  441. }
  442. #endif
  443. return r;
  444. }