/*++ /* NAME /* dict_mongodb 3 /* SUMMARY /* dictionary interface to mongodb, compatible with libmongoc-1.0 /* SYNOPSIS /* #include <dict_mongodb.h> /* /* DICT *dict_mongodb_open(name, open_flags, dict_flags) /* const char *name; /* int open_flags; /* int dict_flags; /* DESCRIPTION /* dict_mongodb_open() opens a MongoDB database, providing a /* dictionary interface for Postfix mappings. The result is a /* pointer to the installed dictionary. /* /* Configuration parameters are described in mongodb_table(5). /* /* Arguments: /* .IP name /* Either the path to the MongoDB configuration file (if it /* starts with '/' or '.'), or the prefix which will be used /* to obtain main.cf configuration parameters for this search. /* /* In the first case, configuration parameters are specified /* in the file as \fIname\fR=\fIvalue\fR pairs. /* /* In the second case, the configuration parameters are prefixed /* with the value of \fIname\fR and an underscore, and they /* are specified in main.cf. For example, if this value is /* \fImongodbconf\fR, the parameters would look like /* \fImongodbconf_uri\fR, \fImongodbconf_collection\fR, and /* so on. /* .IP open_flags /* Must be O_RDONLY /* .IP dict_flags /* See dict_open(3). /* SEE ALSO /* dict(3) generic dictionary manager /* HISTORY /* .ad /* .fi /* MongoDB support was added in Postfix 3.9. /* AUTHOR(S) /* Hamid Maadani (hamid@dexo.tech) /* Dextrous Technologies, LLC /* /* Edited by: /* Wietse Venema /* porcupine.org /* /* Based on prior work by: /* Stephan Ferraro /* Aionda GmbH
/*--*/
/* Set an error code, and return null. */ #define DICT_MONGODB_LOOKUP_ERR_RETURN(err) do { \
dict_mongodb->dict.error = (err); \
DICT_MONGODB_LOOKUP_RETURN((char *) 0); \
} while (0);
/* Pass through any error, and return the specified value. */ #define DICT_MONGODB_LOOKUP_RETURN(val) do { \ if (coll) mongoc_collection_destroy(coll); \ if (cursor) mongoc_cursor_destroy(cursor); \ if (query) bson_destroy(query); \ if (options) bson_destroy(options); \ if (projection) bson_destroy(projection); \ return (val); \
} while (0)
coll = mongoc_client_get_collection(dict_mongodb->client,
dict_mongodb->dbname,
dict_mongodb->collection); if (!coll) {
msg_warn("%s:%s: failed to get collection [%s] from [%s]",
dict_mongodb->dict.type, dict_mongodb->dict.name,
dict_mongodb->collection, dict_mongodb->dbname);
DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
}
/* *Usethespecifiedresultprojection,orcraftonefromthe *result_attribute.Excludethe_idfieldfromtheresult.
*/
options = bson_new(); if (dict_mongodb->projection) {
projection = bson_new_from_json((uint8_t *) dict_mongodb->projection,
-1, &error); if (!projection) {
msg_warn("%s:%s: failed to create a projection from '%s': %s",
dict_mongodb->dict.type, dict_mongodb->dict.name,
dict_mongodb->projection, error.message);
DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
} if (!BSON_APPEND_INT32(projection, "_id", 0)
|| !BSON_APPEND_DOCUMENT(options, "projection", projection)) {
msg_warn("%s:%s: failed to append a projection from '%s'",
dict_mongodb->dict.type, dict_mongodb->dict.name,
dict_mongodb->projection);
DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
}
} elseif (dict_mongodb->result_attribute) {
bson_t res_attr;
if (!BSON_APPEND_DOCUMENT_BEGIN(options, "projection", &res_attr)
|| !BSON_APPEND_INT32(&res_attr, "_id", 0)
|| !dict_mongdb_append_result_attribute(&res_attr,
dict_mongodb->result_attribute)
|| !bson_append_document_end(options, &res_attr)) {
msg_warn("%s:%s: failed to append a projection from '%s'",
dict_mongodb->dict.type, dict_mongodb->dict.name,
dict_mongodb->result_attribute);
DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
}
} else { /* Can't happen. The configuration parser should reject this. */
msg_panic("%s:%s: empty 'projection' and 'result_attribute'",
dict_mongodb->dict.type, dict_mongodb->dict.name);
}
/* *Expandfiltertemplate.Thisusesaquotingfunctiontoprevent *metacharacterinjectionwithpartsfromacraftedemailaddress.
*/
INIT_VSTR(queryString, BUFFER_SIZE); if (!db_common_expand(dict_mongodb->ctx, dict_mongodb->query_filter,
name, 0, queryString, dict_mongdb_quote)) /* Suppress the actual lookup if the expansion is empty. */
DICT_MONGODB_LOOKUP_RETURN(0);
/* Create the query from the expanded query template. */
query = bson_new_from_json((uint8_t *) vstring_str(queryString),
-1, &error); if (!query) {
msg_warn("%s:%s: failed to create a query from '%s': %s",
dict_mongodb->dict.type, dict_mongodb->dict.name,
vstring_str(queryString), error.message);
DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
} /* Run the query. */
cursor = mongoc_collection_find_with_opts(coll, query, options, NULL); if (mongoc_cursor_error(cursor, &error)) {
msg_warn("%s:%s: cursor error for '%s': %s",
dict_mongodb->dict.type, dict_mongodb->dict.name,
vstring_str(queryString), error.message);
DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
} /* Convert the lookup result to C string. */
INIT_VSTR(resultString, BUFFER_SIZE); while (mongoc_cursor_next(cursor, &doc)) { if (bson_iter_init(&iter, doc)) {
result = get_result_string(dict_mongodb, resultString, &iter,
name, &expansion, name);
}
}
DICT_MONGODB_LOOKUP_RETURN(result);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.21Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.