diff options
| author | arf20 <aruizfernandez05@gmail.com> | 2025-11-10 18:12:50 +0100 |
|---|---|---|
| committer | arf20 <aruizfernandez05@gmail.com> | 2025-11-10 18:12:50 +0100 |
| commit | 36b52bd0f856f1b6cfcf8ac1a7459f06939dfafa (patch) | |
| tree | 30c0a260f8eb6e6b6084114c9b78398cf9b601c8 | |
| parent | 47992fa660c9c82858120c4d16fba0501903ceb9 (diff) | |
| download | arfnet2-status-36b52bd0f856f1b6cfcf8ac1a7459f06939dfafa.tar.gz arfnet2-status-36b52bd0f856f1b6cfcf8ac1a7459f06939dfafa.zip | |
email alerts working
| -rw-r--r-- | alert.c | 89 | ||||
| -rw-r--r-- | config.c | 21 | ||||
| -rw-r--r-- | config.h | 3 | ||||
| -rw-r--r-- | events.log | 5 | ||||
| -rw-r--r-- | monitor.cfg.example | 11 |
5 files changed, 111 insertions, 18 deletions
@@ -25,7 +25,6 @@ size_t alerts_size = 0, alerts_capacity = INIT_VEC_CAPACITY; static const char *type_str[] = { "api", "email" }; static const char *status_str[] = { "down", "up" }; -static const char *from = NULL; static size_t @@ -73,15 +72,93 @@ send_api(const target_t *target, const char *endpoint, const char *content_type, printf("%ld\n", http_code); - return http_code == 200 ? STATUS_UP : STATUS_DOWN; + return http_code; } +typedef struct { + size_t bytes_read; + char *body; +} email_send_status_t; + +static size_t +read_cb(char *ptr, size_t size, size_t nmemb, void *userp) +{ + email_send_status_t *send_status = (email_send_status_t *)userp; + const char *data; + size_t len; + + if ((size * nmemb) == 0) { + return 0; + } + + data = &send_status->body[send_status->bytes_read]; + + len = strlen(data); + if(size * nmemb < len) + len = size * nmemb; + memcpy(ptr, data, len); + send_status->bytes_read += len; + + return len; +} static int -send_email(const target_t *target, const char *address, const char *subject_tmpl, - const char *body_tmpl) +send_email(const target_t *target, const char *address, + const char *subject_tmpl, const char *body_tmpl) { + static char buff[4096], buff2[1024], buff3[1024], timestr[256]; + + CURL *curl = curl_easy_init(); + if (!curl) { + fprintf(stderr, "Error allocating cURL handle\n"); + return -1; + } + + curl_easy_setopt(curl, CURLOPT_URL, alert_config.mail_server); + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, alert_config.from); + + curl_easy_setopt(curl, CURLOPT_USERNAME, alert_config.user); + curl_easy_setopt(curl, CURLOPT_PASSWORD, alert_config.password); + + time_t now = time(NULL); + struct tm *tm_now = gmtime(&now); + strftime(timestr, 256, "%a, %d %b %Y %T %z", tm_now); + + snprintf(buff2, 1024, subject_tmpl, target->name, + status_str[target->status]); + snprintf(buff3, 1024, body_tmpl, target->name, status_str[target->status]); + snprintf(buff, 4096, "Date: %s\r\nTo: %s\r\nFrom: %s\r\n" + "Subject: %s\r\n\r\n%s\r\n", timestr, address, alert_config.from, + buff2, buff3); + + email_send_status_t send_status = { + .bytes_read = 0, + .body = buff + }; + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); + curl_easy_setopt(curl, CURLOPT_READDATA, &send_status); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + + struct curl_slist *recipients = NULL; + recipients = curl_slist_append(recipients, address); + curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); + + CURLcode curl_code = curl_easy_perform(curl); + if (curl_code != CURLE_OK) { + printf("curl_easy_perform() failed: %s\n", + curl_easy_strerror(curl_code)); + return STATUS_DOWN; + } + + long resp_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code); + + curl_easy_cleanup(curl); + + printf("%ld\n", resp_code); + + return resp_code; } @@ -90,8 +167,6 @@ alert_init() { alerts = malloc(INIT_VEC_CAPACITY * sizeof(alert_t)); - from = alert_config.from; - printf("alerts:\n"); char line[256]; @@ -157,7 +232,7 @@ alert_trigger(const target_t *target) strftime(timestr, 256, "%F %T", tm_now); for (int i = 0; i < alerts_size; i++) { - printf("[%s] [monitor] alerted %.16s about %s\n", + printf("[%s] [monitor] alerted %.16s about %s: ", timestr, alerts[i].target, target->name); send_funcs[alerts[i].type](target, alerts[i].target, alerts[i].extra, alerts[i].body_tmpl); @@ -8,7 +8,7 @@ unsigned short port = DEFAULT_PORT; char *log_path = DEFAULT_LOG_PATH; monitor_config_t monitor_config = { .interval = DEFAULT_INTERVAL }; -alert_config_t alert_config; +alert_config_t alert_config = { 0 }; int config_load(const char *conf_path) @@ -64,11 +64,23 @@ config_load(const char *conf_path) value[strlen(value) - 1] = '\0'; log_path = strdup(value); printf("\tlog path: %s\n", log_path); - } else if (strcmp(line, "from") == 0) { + } else if (strcmp(line, "mailserver") == 0) { + value[strlen(value) - 1] = '\0'; + alert_config.mail_server = strdup(value); + printf("\tmailserver: %s\n", alert_config.mail_server); + } else if (strcmp(line, "mailfrom") == 0) { value[strlen(value) - 1] = '\0'; alert_config.from = strdup(value); printf("\tfrom: %s\n", log_path); - } else if (strcmp(line, "target") == 0) { + } else if (strcmp(line, "mailuser") == 0) { + value[strlen(value) - 1] = '\0'; + alert_config.user = strdup(value); + } else if (strcmp(line, "mailpassword") == 0) { + value[strlen(value) - 1] = '\0'; + alert_config.password = strdup(value); + } + + else if (strcmp(line, "target") == 0) { target_pos += snprintf(target_pos, cfgsize - (target_pos - monitor_config.target_config), "%s", value); @@ -85,6 +97,9 @@ config_load(const char *conf_path) fclose(cfgf); + if (!alert_config.from || !alert_config.mail_server) + fprintf(stderr, "[config] W: no mail\n"); + return 0; } @@ -19,7 +19,10 @@ typedef struct { } monitor_config_t; typedef struct { + char *mail_server; char *from; + char *user; + char *password; char *alert_config; } alert_config_t; @@ -78,8 +78,3 @@ dns,2025-10-27T15:43:17+0000,up https,2025-10-27T15:43:17+0000,up http,2025-11-04T18:39:12Z,down http,2025-11-04T18:40:12Z,up -test,2025-11-10T12:34:07+0000,down -test,2025-11-10T12:42:29+0000,up -test,2025-11-10T12:42:54+0000,down -test,2025-11-10T12:45:09+0000,up -test,2025-11-10T12:46:50+0000,down diff --git a/monitor.cfg.example b/monitor.cfg.example index 226a88e..821f108 100644 --- a/monitor.cfg.example +++ b/monitor.cfg.example @@ -15,13 +15,18 @@ target=reach,ipv4,2.59.235.35 target=dns,dns,arf20.com target=web,http,http://arf20.com target=web,https,https://arf20.com +target=web,test,http://localhost:8989 # email From -from=status@arf20.com +mailfrom=ARFNET Status Monitor <status@arf20.com> +mailserver=smtps://mail.example.com:465 +mailuser=username +mailpassword=password # what to alert # alert=api,<url>,<content-type>,<body template> -alert=api,https://arf20.com/%s,application/json,{"content":"%s is %s"} +alert=api,https://discord.com/api/webhooks/example,application/json,{"content":"%s is %s"} +alert=api,https://api.telegram.org/botexample/sendMessage,application/json,{"chat_id": "exampleroom", "text": "%s is %s", "disable_notification": false} # alert=email,<address>,<subject template>,<body template> -alert=email,arf20@arf20.com,%s is %s,%s is %s +alert=email,it@example.com,%s is %s,%s is %s |
