mail.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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_CONNECTTIMEOUT, 5L);
  176. //r = curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
  177. r = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
  178. r = curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
  179. r = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  180. r = curl_easy_perform(curl);
  181. if(r != CURLE_OK) {
  182. LOGE("send mail failed, %s\n", curl_easy_strerror(r));
  183. }
  184. else {
  185. LOGD("send mail ok!\n");
  186. }
  187. curl_slist_free_all(recipients);
  188. curl_mime_free(mm);
  189. out:
  190. if(curl) curl_easy_cleanup(curl);
  191. lock_s_release(LOCK_ID_MAIL);
  192. return (r==CURLE_OK)?0:-1;
  193. }
  194. ////////////////////////////////////////////////////////////////////////////
  195. static void sleep_ms(int ms)
  196. {
  197. usleep(ms*1000);
  198. }
  199. static void* mail_thread(void *arg)
  200. {
  201. #ifdef USE_MAIL
  202. int r;
  203. thread_handle_t *th=(thread_handle_t*)arg;
  204. mail_handle_t *h=(mail_handle_t*)th->arg;
  205. list_node_t *ln=NULL;
  206. mail_pkt_t *pkt=NULL;
  207. mail_send_t *send=&h->info->send;
  208. mail_recv_t *recv=h->info->recv;
  209. while(th->quit==0) {
  210. r = xlist_take_node(h->list, &ln, 0);
  211. if(r==0) {
  212. pkt = (mail_pkt_t*)ln->data.buf;
  213. send_mail(send, recv, pkt->sub, pkt->body, pkt->attach, 1);
  214. xlist_back_node(h->list, ln);
  215. }
  216. sleep_ms(100);
  217. }
  218. #endif
  219. pthread_exit(NULL);
  220. }
  221. int mail_init(void)
  222. {
  223. #ifdef USE_MAIL
  224. list_cfg_t lc;
  225. mail_handle_t *h=&maHandle;
  226. GlobalDeviceManager *dm=&__globalDeviceManage;
  227. lc.mode = LIST_FULL_FIFO;
  228. lc.max = 100;
  229. lc.log = 0;
  230. h->list = xlist_init(&lc);
  231. h->dm = dm;
  232. h->info = &h->dm->mailInfo;
  233. dev_mail_init(dm->db, h->info);
  234. thread_start(THREAD_ID_MAIL, mail_thread, h);
  235. h->inited = 1;
  236. //mail_test();
  237. #endif
  238. return 0;
  239. }
  240. int mail_deinit(void)
  241. {
  242. #ifdef USE_MAIL
  243. mail_handle_t *h=&maHandle;
  244. thread_stop(THREAD_ID_MAIL);
  245. xlist_free(h->list);
  246. h->inited = 0;
  247. #endif
  248. return 0;
  249. }
  250. static int post_data(char *sub, char *body, char *attach)
  251. {
  252. int r=0;
  253. #ifdef USE_MAIL
  254. mail_pkt_t pkt;
  255. mail_handle_t *h=&maHandle;
  256. snprintf(pkt.sub, sizeof(pkt.sub), "%s", sub?sub:"");
  257. snprintf(pkt.body, sizeof(pkt.body), "%s", body?body:"");
  258. snprintf(pkt.attach, sizeof(pkt.attach), "%s", attach?attach:"");
  259. r = xlist_append(h->list, 0, &pkt, sizeof(pkt));
  260. #endif
  261. return r;
  262. }
  263. int mail_send(char *sub, char *body, char *attach)
  264. {
  265. int r=-1;
  266. #ifdef USE_MAIL
  267. mail_handle_t *h=&maHandle;
  268. if(!h->inited || !h->info || !h->info->send.mode) {
  269. return -1;
  270. }
  271. r = send_mail(&h->info->send, h->info->recv, sub?sub:"", body?body:"", attach?attach:"", 1);
  272. #endif
  273. return r;
  274. }
  275. int mail_post(char *sub, char *body, char *attach)
  276. {
  277. int r=-1;
  278. #ifdef USE_MAIL
  279. mail_handle_t *h=&maHandle;
  280. if(!h->inited || !h->info || !h->info->send.mode) {
  281. return -1;
  282. }
  283. r = post_data(sub, body, attach);
  284. #endif
  285. return r;
  286. }
  287. int mail_post_alarm(int type, int subtype, int alarm_type, char *content)
  288. {
  289. int r=0;
  290. #ifdef USE_MAIL
  291. mail_pkt_t pkt;
  292. char temp[128];
  293. mail_handle_t *h=&maHandle;
  294. if(!h->inited || !content || !h->info || !h->info->send.mode) {
  295. return -1;
  296. }
  297. char *prod_name=h->dm->_globalDevInfo.product.name;
  298. int prod_id=h->dm->_globalDevInfo.product.id;
  299. int langID=h->dm->_globalDevInfo.product.language;
  300. switch(type) {
  301. case ALARM_TYPE_POWER:
  302. {
  303. if(subtype) {
  304. switch(alarm_type) {
  305. case ENABLE_TAC_V_UP:
  306. case ENABLE_TAC_V_DOWN:
  307. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]);
  308. break;
  309. case ENABLE_TAC_A_UP:
  310. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]);
  311. break;
  312. case ENABLE_TAC_W_UP:
  313. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]);
  314. break;
  315. case ENABLE_TAC_P_UP:
  316. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]);
  317. break;
  318. case ENABLE_TAC_STIME:
  319. case ENABLE_TAC_ETIME:
  320. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]);
  321. break;
  322. default:
  323. return -1;
  324. }
  325. }
  326. else {
  327. switch(alarm_type) {
  328. case WARNING_V_UP:
  329. case WARNING_V_DOWN:
  330. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]);
  331. break;
  332. case WARNING_A_UP:
  333. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]);
  334. break;
  335. case WARNING_W_UP:
  336. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]);
  337. break;
  338. case WARNING_P_UP:
  339. snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]);
  340. break;
  341. case 0 ... 2:
  342. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]);
  343. break;
  344. default:
  345. return -1;
  346. }
  347. }
  348. }
  349. break;
  350. case ALARM_TYPE_SENSOR:
  351. {
  352. switch(subtype) {
  353. case SENSOR_TYPE_TEMP_DOUBLE:
  354. case SENSOR_TYPE_TEMP_HUMI:
  355. case SENSOR_TYPE_TEMP:
  356. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_temperature[langID], language_alarm[langID]);
  357. break;
  358. case SENSOR_TYPE_SMOKE:
  359. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_smoke[langID], language_alarm[langID]);
  360. break;
  361. case SENSOR_TYPE_WATER:
  362. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_humidity[langID], language_alarm[langID]);
  363. break;
  364. case SENSOR_TYPE_ACCESS:
  365. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_access[langID], language_alarm[langID]);
  366. break;
  367. case SENSOR_TYPE_GAS:
  368. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_gas[langID], language_alarm[langID]);
  369. break;
  370. case SENSOR_TYPE_AIR_PRESS:
  371. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_pressure[langID], language_alarm[langID]);
  372. break;
  373. case SENSOR_TYPE_LEAK:
  374. snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_leak[langID], language_alarm[langID]);
  375. break;
  376. default:
  377. return -1;
  378. }
  379. }
  380. break;
  381. case ALARM_TYPE_NETWORK:
  382. {
  383. snprintf(temp, sizeof(temp), "%s %d %s", prod_name, prod_id, language_alarm_Type_Network[langID]);
  384. }
  385. break;
  386. default:
  387. return -1;
  388. }
  389. replace_sequences(content, h->dm->alarmTab);
  390. r = post_data(temp, content, NULL);
  391. #endif
  392. return r;
  393. }
  394. int mail_test(void)
  395. {
  396. int r=0,cnt=0;
  397. #ifdef USE_MAIL
  398. char temp[200];
  399. mail_handle_t *h=&maHandle;
  400. mail_info_t info={
  401. .send = {
  402. .id = 0,
  403. .mode = 1,
  404. #if 0
  405. .account = "rcp064867@163.com",
  406. .password = "YWKVURARCJXYXQVS",
  407. .server = "smtp.163.com",
  408. .port = "25",
  409. //.port = "465",
  410. //.port = "587",
  411. .auth = "PLAIN",
  412. //.auth = "LOGIN",
  413. //.auth = "CRAM-MD5",
  414. #else
  415. .account = "jiuci4902@gmail.com",
  416. .password = "wmfoedxaycdwllvs",
  417. .server = "smtp.gmail.com",
  418. //.port = "25",
  419. //.port = "465",
  420. .port = "587",
  421. //.auth = "PLAIN",
  422. .auth = "LOGIN",
  423. //.auth = "CRAM-MD5",
  424. #endif
  425. },
  426. .recv = {
  427. {0, 1, "1556907721@qq.com"},
  428. {1, 1, "rcp064867@163.com"},
  429. {2, 1, "cijiu0219@sina.com"},
  430. {3, 1, "jiuci4902@gmail.com"},
  431. {4, 1, "cijiu0219@hotmail.com"},
  432. {5, 1, "cijiu990219@outlook.com"},
  433. {6, 1, "iauther@163.com"},
  434. }
  435. };
  436. *h->info = info;
  437. char *sub="123";
  438. char *body="hello everyone";
  439. while(cnt++<5) {
  440. sprintf(temp, "%s %d", body, cnt);
  441. r = mail_send(sub, temp, NULL);
  442. sleep(2);
  443. }
  444. #endif
  445. return r;
  446. }