From f42c6b1dbeeda52f89a4b8a28ffa873f1f8eb6f0 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 15 Oct 2026 02:26:58 +0300 Subject: [PATCH] imap/smtp polishing; --- include/ilib/curl_imapsmtp.h | 56 ++++++++++++++++++++ include/ilib/mail_engine.h | 38 -------------- include/ilib/mail_processor.h | 2 +- src/Makefile.am | 4 +- src/{mail_engine.c => curl_imapsmtp.c} | 73 ++++++++++++++++++-------- src/subrelayd.c | 2 +- 6 files changed, 110 insertions(+), 65 deletions(-) create mode 100644 include/ilib/curl_imapsmtp.h delete mode 100644 include/ilib/mail_engine.h rename src/{mail_engine.c => curl_imapsmtp.c} (76%) diff --git a/include/ilib/curl_imapsmtp.h b/include/ilib/curl_imapsmtp.h new file mode 100644 index 0000000..d3af1b0 --- /dev/null +++ b/include/ilib/curl_imapsmtp.h @@ -0,0 +1,56 @@ +/* + * this is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * this is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see ."; + * + * (c) Alexander Vdolainen 2007, 2026 + * subrelay: a minimalistic maillist server based on external IMAPs/SMTPs + * + * curl_imapsmtp.h: IMAPS SMTPs functions using libcurl + * + */ +#ifndef __MAIL_ENGINE_H__ +#define __MAIL_ENGINE_H__ + +#include + +#include + +#define MAX_IMAP_RESPONSE (25u * 1024u * 1024u) + +typedef struct mail_message { + char *raw_data; /* Full raw RFC 822 byte payload */ + size_t size; /* Size of raw payload */ + unsigned long uid; /* IMAP Unique Identifier */ +} mail_message_t; + +typedef struct mail_list_results { + unsigned long *uids; + size_t count; +} mail_list_results_t; + +/* Initialize and cleanup global libcurl environment */ +int mail_engine_global_init(void); +void mail_engine_global_cleanup(void); + +/* IMAP Client API */ +int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *results); +int imap_fetch_message(const subrelay_config_t *cfg, unsigned long uid, mail_message_t *msg); +int imap_expunge_message(const subrelay_config_t *cfg, unsigned long uid); +void mail_message_free(mail_message_t *msg); +void mail_list_results_free(mail_list_results_t *res); + +/* SMTP Client API */ +int smtp_send_message(const subrelay_config_t *cfg, const char **recipients, + size_t recipient_count, const char *raw_msg, size_t msg_len); + +#endif /* __MAIL_ENGINE_H__ */ diff --git a/include/ilib/mail_engine.h b/include/ilib/mail_engine.h deleted file mode 100644 index b78baaf..0000000 --- a/include/ilib/mail_engine.h +++ /dev/null @@ -1,38 +0,0 @@ -/* mail_engine.h - IMAP fetching & SMTP fan-out engine using libcurl */ -#ifndef __MAIL_ENGINE_H__ -#define __MAIL_ENGINE_H__ - -#include - -#include - -typedef struct mail_message { - char *raw_data; /* Full raw RFC 822 byte payload */ - size_t size; /* Size of raw payload */ - unsigned long uid; /* IMAP Unique Identifier */ -} mail_message_t; - -typedef struct mail_list_results { - unsigned long *uids; - size_t count; -} mail_list_results_t; - -/* Initialize and cleanup global libcurl environment */ -int mail_engine_global_init(void); -void mail_engine_global_cleanup(void); - -/* IMAP Client API */ -int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *results); -int imap_fetch_message(const subrelay_config_t *cfg, unsigned long uid, mail_message_t *msg); -int imap_expunge_message(const subrelay_config_t *cfg, unsigned long uid); -void mail_message_free(mail_message_t *msg); -void mail_list_results_free(mail_list_results_t *res); - -/* SMTP Client API */ -int smtp_send_message(const subrelay_config_t *cfg, - const char **recipients, - size_t recipient_count, - const char *raw_msg, - size_t msg_len); - -#endif /* __MAIL_ENGINE_H__ */ diff --git a/include/ilib/mail_processor.h b/include/ilib/mail_processor.h index fbbbcbd..4d2781b 100644 --- a/include/ilib/mail_processor.h +++ b/include/ilib/mail_processor.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include typedef struct mail_processor { subrelay_config_t *cfg; diff --git a/src/Makefile.am b/src/Makefile.am index 64234d6..dec4334 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,7 +3,7 @@ bin_PROGRAMS = subrelayd sbrlctrl noinst_HEADERS = \ $(top_srcdir)/include/ilib/configuration.h \ $(top_srcdir)/include/ilib/local.h \ - $(top_srcdir)/include/ilib/mail_engine.h \ + $(top_srcdir)/include/ilib/curl_imapsmtp.h \ $(top_srcdir)/include/ilib/mail_processor.h \ $(top_srcdir)/include/ilib/pending.h \ $(top_srcdir)/include/ilib/splay.h \ @@ -20,7 +20,7 @@ subrelayd_SOURCES = \ pending.c \ configuration.c \ template.c \ - mail_engine.c \ + curl_imapsmtp.c \ mail_processor.c \ local.c diff --git a/src/mail_engine.c b/src/curl_imapsmtp.c similarity index 76% rename from src/mail_engine.c rename to src/curl_imapsmtp.c index 407c239..fd2476d 100644 --- a/src/mail_engine.c +++ b/src/curl_imapsmtp.c @@ -1,11 +1,33 @@ -/* mail_engine.c - libcurl IMAP and SMTP implementation */ +/* + * this is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * this is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see ."; + * + * (c) Alexander Vdolainen 2007, 2026 + * subrelay: a minimalistic maillist server based on external IMAPs/SMTPs + * + * curl_imapsmtp.c: IMAPS SMTPs functions using libcurl + * + */ + + #include #include +#include #include #include #include -#include +#include typedef struct memory_buffer { char *data; @@ -20,24 +42,28 @@ typedef struct upload_buffer { /* Callback for libcurl to append fetched HTTP/IMAP bytes into memory */ static size_t write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp) { - size_t real_size = size * nmemb; - memory_buffer_t *mem = (memory_buffer_t *)userp; + memory_buffer_t *mem = userp; - char *ptr = realloc(mem->data, mem->size + real_size + 1); - if (!ptr) return 0; /* Out of memory */ + if (size != 0 && nmemb > SIZE_MAX / size) return 0; + size_t n = size * nmemb; + if (n > MAX_IMAP_RESPONSE - mem->size) return 0; + + char *ptr = realloc(mem->data, mem->size + n + 1); + if (!ptr) return 0; mem->data = ptr; - memcpy(&(mem->data[mem->size]), contents, real_size); - mem->size += real_size; - mem->data[mem->size] = 0; + memcpy(mem->data + mem->size, contents, n); + mem->size += n; + mem->data[mem->size] = '\0'; - return real_size; + return n; } /* Callback for libcurl to read bytes when sending outbound mail via SMTP */ static size_t read_payload_callback(char *buffer, size_t size, size_t nitems, void *userp) { upload_buffer_t *upload = (upload_buffer_t *)userp; + if (size != 0 && nitems > SIZE_MAX / size) return CURL_READFUNC_ABORT; size_t max_bytes = size * nitems; if (upload->bytes_remaining == 0) return 0; /* EOF */ @@ -61,9 +87,7 @@ void mail_engine_global_cleanup(void) curl_global_cleanup(); } -/* -------------------------------------------------------------------------- */ -/* IMAP Operations */ -/* -------------------------------------------------------------------------- */ +/* IMAPs */ int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *results) { @@ -77,6 +101,7 @@ int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *re snprintf(url, sizeof(url), "imaps://%s:%d/INBOX", cfg->imap_host, cfg->imap_port); memory_buffer_t buf = { calloc(1, 1), 0 }; + if(!buf.data) return -ENOMEM; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_USERNAME, cfg->maillist_addr); @@ -97,12 +122,18 @@ int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *re /* Parse IMAP response string (e.g., "* SEARCH 101 102 103\r\n") */ char *search_str = strstr(buf.data, "* SEARCH"); if (search_str) { - search_str += 8; /* Skip "* SEARCH" */ + search_str += 8; /* skip "* SEARCH" */ char *token = strtok(search_str, " \r\n"); while (token) { unsigned long uid = strtoul(token, NULL, 10); if (uid > 0) { - results->uids = realloc(results->uids, sizeof(unsigned long) * (results->count + 1)); + unsigned long *tmp = realloc(results->uids, sizeof(unsigned long) * (results->count + 1)); + if(!tmp) { + free(buf.data); + mail_list_results_free(results); + return -ENOMEM; + } + results->uids = tmp; results->uids[results->count++] = uid; } token = strtok(NULL, " \r\n"); @@ -125,6 +156,7 @@ int imap_fetch_message(const subrelay_config_t *cfg, unsigned long uid, mail_mes snprintf(url, sizeof(url), "imaps://%s:%d/INBOX;UID=%lu", cfg->imap_host, cfg->imap_port, uid); memory_buffer_t buf = { calloc(1, 1), 0 }; + if(!buf.data) return -ENOMEM; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_USERNAME, cfg->maillist_addr); @@ -179,15 +211,10 @@ int imap_expunge_message(const subrelay_config_t *cfg, unsigned long uid) return (res == CURLE_OK) ? 0 : -EIO; } -/* -------------------------------------------------------------------------- */ -/* SMTP Operations */ -/* -------------------------------------------------------------------------- */ +/* SMTPS */ -int smtp_send_message(const subrelay_config_t *cfg, - const char **recipients, - size_t recipient_count, - const char *raw_msg, - size_t msg_len) +int smtp_send_message(const subrelay_config_t *cfg, const char **recipients, size_t recipient_count, + const char *raw_msg, size_t msg_len) { if (!cfg || !recipients || recipient_count == 0 || !raw_msg) return -EINVAL; diff --git a/src/subrelayd.c b/src/subrelayd.c index ad31881..691e371 100644 --- a/src/subrelayd.c +++ b/src/subrelayd.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include