Probe external accounts through libcurl

This commit is contained in:
Mario Fetka
2026-07-16 14:45:22 +02:00
parent f126a9e0b8
commit 0f26be3eda
3 changed files with 68 additions and 4 deletions
+62
View File
@@ -41,6 +41,64 @@
CollectorGlobals Collector = {0};
static size_t DiscardCurlData(char *ptr, size_t size, size_t count, void *data)
{
(void) ptr; (void) data;
return size * count;
}
static int ProbeExternalAccount(sqlite3 *database,
const CollectorExternalAccount *account,
long now)
{
CURL *curl = NULL;
char secret[512];
char url[768];
char error[CURL_ERROR_SIZE] = {0};
const char *scheme;
CURLcode code;
int secretResult;
if (account->inbound_protocol[0] == '\0' || account->inbound_host[0] == '\0' ||
account->inbound_secret_id[0] == '\0') {
CollectorAccountsMarkResult(database, account->id, now, 0,
"external account is missing transport credentials");
return -1;
}
secretResult = CollectorAccountsSecretGet(database, account->inbound_secret_id,
secret, sizeof(secret));
if (secretResult != 1) {
CollectorAccountsMarkResult(database, account->id, now, 0,
"external account secret not found or too long");
return -1;
}
scheme = strcmp(account->inbound_protocol, "imap") == 0 ? "imap" : "pop3";
if (snprintf(url, sizeof(url), "%s%s://%s:%d/%s", scheme,
strcmp(account->inbound_tls, "implicit") == 0 ? "s" : "",
account->inbound_host, account->inbound_port,
account->destination_folder[0] != '\0' ? account->destination_folder : "INBOX") >= (int) sizeof(url)) {
CollectorAccountsMarkResult(database, account->id, now, 0, "external account URL too long");
return -1;
}
curl = curl_easy_init();
if (curl == NULL) return -1;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERNAME, account->inbound_username);
curl_easy_setopt(curl, CURLOPT_PASSWORD, secret);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DiscardCurlData);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
code = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (code != CURLE_OK) {
CollectorAccountsMarkResult(database, account->id, now, 0,
error[0] != '\0' ? error : curl_easy_strerror(code));
return -1;
}
return CollectorAccountsMarkResult(database, account->id, now, 1, NULL);
}
static void
CollectorLoop(void *ignored)
{
@@ -61,6 +119,10 @@ CollectorLoop(void *ignored)
Log(LOG_ERROR, "Unable to query due external mail accounts");
} else if (due > 0) {
Log(LOG_DEBUG, "%d external mail account(s) are due for collection", due);
CollectorExternalAccount account;
if (CollectorAccountsNextDue(accounts, (long) now, &account) == 1) {
ProbeExternalAccount(accounts, &account, (long) now);
}
}
}
if (lastCalendarCollection == 0 || now - lastCalendarCollection >= 6 * 60 * 60) {
+5 -4
View File
@@ -82,7 +82,7 @@ CollectorAccountsNextDue(sqlite3 *database, long now,
sqlite3_stmt *statement = NULL;
const char query[] =
"SELECT id, owner, email_address, inbound_protocol, inbound_host, "
"inbound_port, inbound_tls, inbound_username, destination_folder, "
"inbound_port, inbound_tls, inbound_username, inbound_secret_id, destination_folder, "
"delete_policy, COALESCE(delete_after_days, 0) "
"FROM external_accounts WHERE enabled = 1 AND inbound_protocol != 'none' "
"AND (last_checked_at IS NULL OR last_checked_at + poll_interval <= ?) "
@@ -116,9 +116,10 @@ CollectorAccountsNextDue(sqlite3 *database, long now,
account->inbound_port = sqlite3_column_int(statement, 5);
COPY_ACCOUNT_FIELD(6, inbound_tls);
COPY_ACCOUNT_FIELD(7, inbound_username);
COPY_ACCOUNT_FIELD(8, destination_folder);
COPY_ACCOUNT_FIELD(9, delete_policy);
account->delete_after_days = sqlite3_column_int(statement, 10);
COPY_ACCOUNT_FIELD(8, inbound_secret_id);
COPY_ACCOUNT_FIELD(9, destination_folder);
COPY_ACCOUNT_FIELD(10, delete_policy);
account->delete_after_days = sqlite3_column_int(statement, 11);
#undef COPY_ACCOUNT_FIELD
sqlite3_finalize(statement);
return 1;
+1
View File
@@ -14,6 +14,7 @@ typedef struct {
int inbound_port;
char inbound_tls[16];
char inbound_username[256];
char inbound_secret_id[128];
char destination_folder[256];
char delete_policy[16];
int delete_after_days;