#include #include #include "cfg.h" #include "common.h" #include "thread.h" #include "xlist.h" #include "elog.h" #include "lock.h" #include "sqlite_handle.h" #include #include "mail.h" #if 1 #define LOGD log_d #define LOGE log_e #define LOGW log_w #else #define LOGD printf #define LOGE printf #define LOGW printf #endif typedef struct { char sub[128]; char body[2048]; char attach[128]; }mail_pkt_t; typedef struct { handle_t list; mail_info_t *info; GlobalDeviceManager *dm; int inited; }mail_handle_t; static mail_handle_t maHandle; static char send_buff[4096]; struct upload_status { size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } data = &send_buff[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); if(room < len) len = room; memcpy(ptr, data, len); upload_ctx->bytes_read += len; return len; } return 0; } static void fill_send_buff(char *dst_buf, const char *to,const char *from,const char *subject,const char *body) { time_t timer;//time_t就是long int 类型 struct tm *tblock; timer = time(NULL); tblock = localtime(&timer); sprintf(dst_buf,"Subject: %s\r\n" "From: %s\r\n" "To: %s\r\n" "Date: %s\r\n" "\r\n" "%s\r\n" "\r\n",subject,from,to,asctime(tblock),body); } static int curl_add_files(curl_mime *mm, char *attach) { curl_mimepart *part; int nlen=strlen(attach); char *p,*tmp=strdup(attach),*p2; if(!tmp) { return -1; } p = tmp; p2 = tmp+nlen; while(*p) { if((*p)==';') *p=0; p++; } p = tmp; while(1) { if(p>=p2) break; part = curl_mime_addpart(mm); if(!part) { printf("____part is null!\n"); free(tmp); return -1; } curl_mime_name(part, "file"); curl_mime_filedata(part, p); p += strlen(p)+1; } free(tmp); return 0; } static int send_mail(mail_send_t *send, void *addr, char *sub, char *body, char *attach, int multi) { int i=0; CURLcode r=CURLE_OK; char tmp[100]; char url_buff[256]={0}; char to_buff[256]={0}; mail_handle_t *h=&maHandle; struct upload_status upload_ctx = { 0 }; struct curl_slist *recipients = NULL; mail_recv_t *recv=(mail_recv_t*)addr; curl_mime *mm=NULL,*alt=NULL; curl_mimepart *part=NULL; struct curl_slist *slist=NULL; struct curl_slist *headers=NULL; const char **cpp; lock_s_hold(LOCK_ID_MAIL); CURL *curl = curl_easy_init(); if(!curl) { goto out; } sprintf(url_buff,"%s:%s",send->server,send->port); r = curl_easy_setopt(curl,CURLOPT_URL,url_buff); //curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "EXPN"); //curl_easy_setopt(curl, CURLOPT_MAIL_AUTH, ""); //curl_easy_setopt(curl, CURLOPT_SASL_AUTHZID, "ursel"); //sprintf(tmp, "AUTH=%s", send->auth); //curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, tmp); r = curl_easy_setopt(curl, CURLOPT_USERNAME, send->account); //setting user r = curl_easy_setopt(curl, CURLOPT_PASSWORD, send->password); //setting password if(strcmp(send->port, "587")==0) { //tls r = curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); //setting openssl/tls //curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem"); } curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //curl_easy_setopt(curl, CURLOPT_USERAGENT, CLIENT_USERAGENT); r = curl_easy_setopt(curl, CURLOPT_MAIL_FROM, send->account); r = curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); r = curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); if(multi) { for(int i=0; i0) { recipients = curl_slist_append(recipients, recv[i].account); //recipients = curl_slist_append(recipients, CC_MAIL); strcat(to_buff,recv[i].account); strcat(to_buff,";"); } } } else { char *sendto=(char*)addr; recipients = curl_slist_append(recipients,sendto); strcat(to_buff,sendto); strcat(to_buff,";"); } fill_send_buff(send_buff,to_buff,send->account,sub,body); if(attach && strlen(attach)>0) { mm = curl_mime_init(curl); alt = curl_mime_init(curl); headers = curl_slist_append(headers, send_buff); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); part = curl_mime_addpart(alt); curl_mime_data(part, sub, CURL_ZERO_TERMINATED); part = curl_mime_addpart(mm); curl_mime_subparts(part, alt); curl_mime_type(part, "multipart/alternative"); slist = curl_slist_append(NULL, "Content-Disposition: inline"); curl_mime_headers(part, slist, 1); //part = curl_mime_addpart(mm); //curl_mime_name(part, "file"); //curl_mime_filedata(part, attach); curl_add_files(mm, attach); curl_easy_setopt(curl, CURLOPT_MIMEPOST, mm); } r = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); r = curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); r = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); r = curl_easy_perform(curl); if(r != CURLE_OK) { LOGE("send mail failed, %s\n", curl_easy_strerror(r)); } else { LOGD("send mail ok!\n"); } curl_slist_free_all(recipients); curl_mime_free(mm); out: if(curl) curl_easy_cleanup(curl); lock_s_release(LOCK_ID_MAIL); return (r==CURLE_OK)?0:-1; } //////////////////////////////////////////////////////////////////////////// static void sleep_ms(int ms) { usleep(ms*1000); } static void* mail_thread(void *arg) { #ifdef USE_MAIL int r; thread_handle_t *th=(thread_handle_t*)arg; mail_handle_t *h=(mail_handle_t*)th->arg; list_node_t *ln=NULL; mail_pkt_t *pkt=NULL; mail_send_t *send=&h->info->send; mail_recv_t *recv=h->info->recv; while(th->quit==0) { r = xlist_take_node(h->list, &ln, 0); if(r==0) { pkt = (mail_pkt_t*)ln->data.buf; send_mail(send, recv, pkt->sub, pkt->body, pkt->attach, 1); xlist_back_node(h->list, ln); } sleep_ms(100); } #endif pthread_exit(NULL); } int mail_init(void) { #ifdef USE_MAIL list_cfg_t lc; mail_handle_t *h=&maHandle; GlobalDeviceManager *dm=&__globalDeviceManage; lc.mode = LIST_FULL_FIFO; lc.max = 100; lc.log = 0; h->list = xlist_init(&lc); h->dm = dm; h->info = &h->dm->mailInfo; dev_mail_init(dm->db, h->info); thread_start(THREAD_ID_MAIL, mail_thread, h); h->inited = 1; //mail_test(); #endif return 0; } int mail_deinit(void) { #ifdef USE_MAIL mail_handle_t *h=&maHandle; thread_stop(THREAD_ID_MAIL); xlist_free(h->list); h->inited = 0; #endif return 0; } static int post_data(char *sub, char *body, char *attach) { int r=0; #ifdef USE_MAIL mail_pkt_t pkt; mail_handle_t *h=&maHandle; snprintf(pkt.sub, sizeof(pkt.sub), "%s", sub?sub:""); snprintf(pkt.body, sizeof(pkt.body), "%s", body?body:""); snprintf(pkt.attach, sizeof(pkt.attach), "%s", attach?attach:""); r = xlist_append(h->list, 0, &pkt, sizeof(pkt)); #endif return r; } int mail_send(char *sub, char *body, char *attach) { int r=-1; #ifdef USE_MAIL mail_handle_t *h=&maHandle; if(!h->inited || !h->info || !h->info->send.mode) { return -1; } r = send_mail(&h->info->send, h->info->recv, sub?sub:"", body?body:"", attach?attach:"", 1); #endif return r; } int mail_post(char *sub, char *body, char *attach) { int r=-1; #ifdef USE_MAIL mail_handle_t *h=&maHandle; if(!h->inited || !h->info || !h->info->send.mode) { return -1; } r = post_data(sub, body, attach); #endif return r; } int mail_post_alarm(int type, int subtype, int alarm_type, char *content) { int r=0; #ifdef USE_MAIL mail_pkt_t pkt; char temp[128]; mail_handle_t *h=&maHandle; if(!h->inited || !content || !h->info || !h->info->send.mode) { return -1; } char *prod_name=h->dm->_globalDevInfo.product.name; int prod_id=h->dm->_globalDevInfo.product.id; int langID=h->dm->_globalDevInfo.product.language; switch(type) { case ALARM_TYPE_POWER: { if(subtype) { switch(alarm_type) { case ENABLE_TAC_V_UP: case ENABLE_TAC_V_DOWN: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]); break; case ENABLE_TAC_A_UP: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]); break; case ENABLE_TAC_W_UP: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]); break; case ENABLE_TAC_P_UP: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]); break; case ENABLE_TAC_STIME: case ENABLE_TAC_ETIME: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]); break; default: return -1; } } else { switch(alarm_type) { case WARNING_V_UP: case WARNING_V_DOWN: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]); break; case WARNING_A_UP: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]); break; case WARNING_W_UP: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]); break; case WARNING_P_UP: snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]); break; case 0 ... 2: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]); break; default: return -1; } } } break; case ALARM_TYPE_SENSOR: { switch(subtype) { case SENSOR_TYPE_TEMP_DOUBLE: case SENSOR_TYPE_TEMP_HUMI: case SENSOR_TYPE_TEMP: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_temperature[langID], language_alarm[langID]); break; case SENSOR_TYPE_SMOKE: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_smoke[langID], language_alarm[langID]); break; case SENSOR_TYPE_WATER: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_humidity[langID], language_alarm[langID]); break; case SENSOR_TYPE_ACCESS: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_access[langID], language_alarm[langID]); break; case SENSOR_TYPE_GAS: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_gas[langID], language_alarm[langID]); break; case SENSOR_TYPE_AIR_PRESS: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_pressure[langID], language_alarm[langID]); break; case SENSOR_TYPE_LEAK: snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_leak[langID], language_alarm[langID]); break; default: return -1; } } break; case ALARM_TYPE_NETWORK: { snprintf(temp, sizeof(temp), "%s %d %s", prod_name, prod_id, language_alarm_Type_Network[langID]); } break; default: return -1; } replace_sequences(content, h->dm->alarmTab); r = post_data(temp, content, NULL); #endif return r; } int mail_test(void) { int r=0,cnt=0; #ifdef USE_MAIL char temp[200]; mail_handle_t *h=&maHandle; mail_info_t info={ .send = { .id = 0, .mode = 1, #if 0 .account = "rcp064867@163.com", .password = "YWKVURARCJXYXQVS", .server = "smtp.163.com", .port = "25", //.port = "465", //.port = "587", .auth = "PLAIN", //.auth = "LOGIN", //.auth = "CRAM-MD5", #else .account = "jiuci4902@gmail.com", .password = "wmfoedxaycdwllvs", .server = "smtp.gmail.com", //.port = "25", //.port = "465", .port = "587", //.auth = "PLAIN", .auth = "LOGIN", //.auth = "CRAM-MD5", #endif }, .recv = { {0, 1, "1556907721@qq.com"}, {1, 1, "rcp064867@163.com"}, {2, 1, "cijiu0219@sina.com"}, {3, 1, "jiuci4902@gmail.com"}, {4, 1, "cijiu0219@hotmail.com"}, {5, 1, "cijiu990219@outlook.com"}, {6, 1, "iauther@163.com"}, } }; *h->info = info; char *sub="123"; char *body="hello everyone"; while(cnt++<5) { sprintf(temp, "%s %d", body, cnt); r = mail_send(sub, temp, NULL); sleep(2); } #endif return r; }