imap/smtp polishing;
This commit is contained in:
parent
f5a2d2b38f
commit
f42c6b1dbe
56
include/ilib/curl_imapsmtp.h
Normal file
56
include/ilib/curl_imapsmtp.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.";
|
||||
*
|
||||
* (c) Alexander Vdolainen 2007, 2026 <alex@vapaa.xyz>
|
||||
* 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 <stddef.h>
|
||||
|
||||
#include <ilib/configuration.h>
|
||||
|
||||
#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__ */
|
||||
@ -1,38 +0,0 @@
|
||||
/* mail_engine.h - IMAP fetching & SMTP fan-out engine using libcurl */
|
||||
#ifndef __MAIL_ENGINE_H__
|
||||
#define __MAIL_ENGINE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <ilib/configuration.h>
|
||||
|
||||
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__ */
|
||||
@ -24,7 +24,7 @@
|
||||
#include <ilib/configuration.h>
|
||||
#include <ilib/subscribers.h>
|
||||
#include <ilib/pending.h>
|
||||
#include <ilib/mail_engine.h>
|
||||
#include <ilib/curl_imapsmtp.h>
|
||||
|
||||
typedef struct mail_processor {
|
||||
subrelay_config_t *cfg;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.";
|
||||
*
|
||||
* (c) Alexander Vdolainen 2007, 2026 <alex@vapaa.xyz>
|
||||
* subrelay: a minimalistic maillist server based on external IMAPs/SMTPs
|
||||
*
|
||||
* curl_imapsmtp.c: IMAPS SMTPs functions using libcurl
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <ilib/mail_engine.h>
|
||||
#include <ilib/curl_imapsmtp.h>
|
||||
|
||||
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;
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include <ilib/configuration.h>
|
||||
#include <ilib/subscribers.h>
|
||||
#include <ilib/pending.h>
|
||||
#include <ilib/mail_engine.h>
|
||||
#include <ilib/curl_imapsmtp.h>
|
||||
#include <ilib/mail_processor.h>
|
||||
#include <ilib/local.h>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user