From: Wietse Z Venema Postfix can use MongoDB as a source for any of its lookups:
+aliases(5), virtual(5), canonical(5), etc. This allows you to keep
+information for your mail service in a replicated noSQL database
+with fine-grained access controls. By not storing it locally on the
+mail server, the administrators can maintain it from anywhere, and
+the users can control whatever bits of it you think appropriate.
+You can have multiple mail servers using the same information,
+without the hassle and delay of having to copy it to each. Topics covered in this document: These instructions assume that you build Postfix from source
+code as described in the INSTALL document. Some modification may
+be required if you build Postfix from a vendor-specific source
+package. The Postfix MongoDB client requires the mongo-c-driver library.
+This can be built from source code from the
+mongod-c project, or as a binary package from your OS distribution,
+typically named mongo-c-driver-devel or libmongoc-dev.
+Installing the mongo-c-driver library may also install libbson
+as a dependency. To build Postfix with mongodb map support, add to the CCARGS
+environment variable the options -DHAS_MONGODB and -I for the
+directory containing the mongodb headers, and specify the AUXLIBS_MONGODB
+with the libmongoc and libbson libraries, for example: The 'make tidy' command is needed only if you have previously
+built Postfix without MongoDB support. If your MongoDB shared library is in a directory that the RUN-TIME
+linker does not know about, add a "-Wl,-R,/path/to/directory" option
+after "-lbson-1.0". Then, just run 'make'. In order to use MongoDB lookups, define a MongoDB source as a
+table lookup in main.cf, for example: The file /etc/postfix/mongo-aliases.cf can specify a number of
+parameters. For a complete description, see the mongodb_table(5)
+manual page. Here's a basic example for using MongoDB to look up virtual(5)
+aliases. Assume that in main.cf, you have: and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have: This example assumes mailbox names are stored in a MongoDB backend,
+in a format like: Upon receiving mail for "admin@example.com" that isn't found in the
+/etc/postfix/virtual_aliases database, Postfix will search the
+MongoDB server/cluster listening at port 27017 on some_server. It
+will connect using the provided credentials, and search for any
+entries whose username is, or alias field has "admin@example.com".
+It will return the username attribute of those found, and build a
+list of their email addresses. When it comes to mailing lists, one way of implementing one would
+be as below: using the filter below, will result in a comma separated string
+with all email addresses in this list. Notes: As with projection, the Postfix mongodb client
+automatically removes the top-level '_id' field from a result. The Postfix mongodb client will only parse result fields
+with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
+ignored, with a warning in the logs. This module also supports the use of more complex MongoDB
+projections. There may be some use cases where operations such as
+concatenation are necessary to be performed on the data retrieved
+from the database. Although it is encouraged to keep the database
+design simple enough so this is not necessary, postfix supports the
+use of MongoDB projections to achieve the goal. Consider the example below: virtual_mailbox_maps can be created using below parameters in a
+mongodb:/etc/postfix/mongo-virtual-mailboxes.cf file: This will return 'example.com/user' path built from the database fields. A couple of considerations when using projections: As with result_attribute, the Postfix mongodb client
+automatically removes the top-level '_id' field from a projection
+result. The Postfix mongodb client will only parse fields with data
+types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored,
+with a warning in the logs. It is suggested to exclude any unnecessary
+fields when using a projection. If you have questions, send them to postfix-users@postfix.org.
+Please include relevant information about your Postfix setup:
+MongoDB-related output from postconf, which libraries you built
+with, and such. If your question involves your database contents,
+please include the applicable bits of some database entries.
+ LDAP database LDAP_README Postfix
1.0
+
MongoDB database MONGODB_README Postfix
+3.9
diff --git a/postfix/html/MONGODB_README.html b/postfix/html/MONGODB_README.html
new file mode 100644
index 000000000..278c0c813
--- /dev/null
+++ b/postfix/html/MONGODB_README.html
@@ -0,0 +1,232 @@
+
+
+
+ MySQL database MYSQL_README Postfix
1.0
+
Postfix MongoDB Howto
+
+MongoDB Support in Postfix
+
+
+
+
+Building Postfix with MongoDB support
+
+
+
+
+
+% make tidy
+% make -f Makefile.init makefiles \
+ CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
+ -I/usr/include/libbson-1.0" \
+ AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0"
+
+Configuring MongoDB lookups
+
+
+
+
+
+alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf
+
+Example: virtual(5) alias maps
+
+
+
+
+
+virtual_alias_maps = hash:/etc/postfix/virtual_aliases,
+ proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf
+
+
+
+
+
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+result_attribute = username
+
+
+
+
+
+{ "username": "user@example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+
+Example: Mailing lists
+
+
+
+
+
+{ "name": "dev@example.com", "active": 1, "address":
+ [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
+
+
+
+
+
+query_filter = {"name": "%s", "active": 1}
+result_attribute = address
+
+
+
+
+
+Example: advanced projections
+
+
+
+
+
+{ "username": "user@example.com",
+ "local_part": "user",
+ "domain": "example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+
+
+
+
+
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
+
+
+
+
+Feedback
+
+
+MONGODB_TABLE(5) MONGODB_TABLE(5)
+
+NAME
+ mongodb_table - Postfix MongoDB client configuration
+
+SYNOPSIS
+ postmap -q "string" mongodb:/etc/postfix/filename
+
+ postmap -q - mongodb:/etc/postfix/filename <inputfile
+
+DESCRIPTION
+ The Postfix mail system uses optional tables for address rewriting or
+ mail routing. These tables are usually in dbm or db format.
+
+ Alternatively, lookup tables can be specified as MongoDB databases. In
+ order to use MongoDB lookups, define a MongoDB source as a lookup table
+ in main.cf, for example:
+ alias_maps = mongodb:/etc/postfix/mongodb-aliases.cf
+
+ In this example, the file /etc/postfix/mongodb-aliases.cf has the same
+ format as the Postfix main.cf file, and can specify the parameters
+ described below. It is also possible to have the configuration in
+ main.cf; see "OBSOLETE MAIN.CF PARAMETERS" below.
+
+ It is strongly recommended to use proxy:mongodb, in order to reduce the
+ number of database connections. For example:
+ alias_maps = proxy:mongodb:/etc/postfix/mongodb-aliases.cf
+
+ Note: when using proxy:mongodb:/file, the file must be readable by the
+ unprivileged postfix user (specified with the Postfix mail_owner con-
+ figuration parameter).
+
+MONGODB PARAMETERS
+ uri The URI of mongo server/cluster that Postfix will try to connect
+ to and query from. Please see
+ https://www.mongodb.com/docs/manual/reference/connection-string/
+
+ Example:
+ uri = mongodb+srv://user:pass@loclhost:27017/mail
+
+ dbname Name of the database to read the information from. Example:
+ dbname = mail
+
+ collection
+ Name of the collection (table) to read the information from.
+ Example:
+ collection = mailbox
+
+ query_filter
+ The MongoDB query template used to search the database, where %s
+ is a substitute for the email address that Postfix is trying to
+ resolve. Please see:
+ https://www.mongodb.com/docs/manual/tutorial/query-documents/
+
+ Example:
+ query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1}
+
+ This parameter supports the following '%' expansions:
+
+ %% This is replaced by a literal '%' character.
+
+ %s This is replaced by the input key. The %s must appear in
+ quotes, because all Postfix queries are strings contain-
+ ing (parts from) a domain or email address. Postfix makes
+ no numerical queries.
+
+ %u When the input key is an address of the form user@domain,
+ %u is replaced by the local part of the address. Other-
+ wise, %u is replaced by the entire search string.
+
+ %d When the input key is an address of the form user@domain,
+ %d is replaced by the domain part of the address.
+
+ %[1-9] The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is user@mail.example.com, then
+ %1 is com, %2 is example and %3 is mail.
+
+ In the above substitutions, characters will be quoted as
+ required by RFC 4627. For example, each double quote or back-
+ slash character will be escaped with a backslash characacter.
+
+ projection
+ Advanced MongoDB query projections. Please see:
+ https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/
+
+ o If projection is non-empty, then result_attribute must be
+ empty.
+
+ o This implementation can extract information only from
+ result fields that have type string (UTF8), integer
+ (int32, int64) and array. Other result fields will be
+ ignored with a warning. Please see:
+ https://mongoc.org/libbson/current/bson_type_t.html
+
+ o As with result_attribute, the top-level _id field (type
+ OID) is automatically removed from projection results.
+
+ result_attribute
+ Comma or whitespace separated list with the names of fields to
+ be returned in a lookup result.
+
+ o If result_attribute is non-empty, then projection must be
+ empty.
+
+ o As with projection, the top-level _id field (type OID) is
+ automatically removed from lookup results.
+
+ result_format (default: %s)
+ Format template applied to the result from projection or
+ result_attribute. Most commonly used to append (or prepend) text
+ to the result. This parameter supports the following '%' expan-
+ sions:
+
+ %% This is replaced by a literal '%' character.
+
+ %s This is replaced by the value of the result attribute.
+ When result is empty it is skipped.
+
+ %u When the result attribute value is an address of the form
+ user@domain, %u is replaced by the local part of the
+ address. When the result has an empty localpart it is
+ skipped.
+
+ %d When a result attribute value is an address of the form
+ user@domain, %d is replaced by the domain part of the
+ attribute value. When the result is unqualified it is
+ skipped.
+
+ %[SUD1-9]
+ The upper-case and decimal digit expansions interpolate
+ the parts of the input key rather than the result. Their
+ behavior is identical to that described with query_fil-
+ ter, and in fact because the input key is known in
+ advance, lookups whose key does not contain all the
+ information specified in the result template are sup-
+ pressed and return no results.
+
+ For example, using "result_format = smtp:[%s]" allows one to use
+ a mailHost attribute as the basis of a transport(5) table. After
+ applying the result format, multiple values are concatenated as
+ comma separated strings. The expansion_limit parameter explained
+ below allows one to restrict the number of values in the result,
+ which is especially useful for maps that should return a single
+ value.
+
+ The default value %s specifies that each attribute value should
+ be used as is.
+
+ NOTE: DO NOT put quotes around the result format! The result is
+ not a JSON string.
+
+ domain (default: no domain list)
+ This is a list of domain names, paths to files, or "type:table"
+ databases. When specified, only fully qualified search keys with
+ a *non-empty* localpart and a matching domain are eligible for
+ lookup: 'user' lookups, bare domain lookups and "@domain"
+ lookups are not performed. This can significantly reduce the
+ query load on the backend database. Example:
+ domain = postfix.org, hash:/etc/postfix/searchdomains
+
+ expansion_limit (default: 0)
+ A limit on the total number of result elements returned (as a
+ comma separated list) by a lookup against the map. A setting of
+ zero disables the limit. Lookups fail with a temporary error if
+ the limit is exceeded. Setting the limit to 1 ensures that
+ lookups do not return multiple values.
+
+OBSOLETE MAIN.CF PARAMETERS
+ MongoDB parameters can also be defined in main.cf. Specify as MongoDB
+ source a name that doesn't begin with a slash or a dot. The MongoDB
+ parameters will then be accessible as the name you've given the source
+ in its definition, an underscore, and the name of the parameter. For
+ example, if a map is specified as "mongodb:mongodb_source", the "uri"
+ parameter would be defined in main.cf as "mongodb_source_uri".
+
+ Note: with this form, passwords are written in main.cf, which is nor-
+ mally world-readable, and '$' in a mongodb parameter setting needs to
+ be written as '$$'.
+
+SEE ALSO
+ postmap(1), Postfix lookup table maintenance
+ postconf(5), configuration parameters
+
+README FILES
+ DATABASE_README, Postfix lookup table overview
+ MONGODB_README, Postfix MONGODB client guide
+
+LICENSE
+ The Secure Mailer license must be distributed with this software.
+
+HISTORY
+ MongoDB support was introduced with Postfix version 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
+
+ MONGODB_TABLE(5)
+
diff --git a/postfix/html/postfix-manuals.html b/postfix/html/postfix-manuals.html
index 936ecae8f..84774a52b 100644
--- a/postfix/html/postfix-manuals.html
+++ b/postfix/html/postfix-manuals.html
@@ -164,6 +164,8 @@ the following convention:
Postfix MongoDB HowtoPostfix can use MongoDB as a source for any of its lookups: +aliases(5), virtual(5), canonical(5), etc. This allows you to keep +information for your mail service in a replicated noSQL database +with fine-grained access controls. By not storing it locally on the +mail server, the administrators can maintain it from anywhere, and +the users can control whatever bits of it you think appropriate. +You can have multiple mail servers using the same information, +without the hassle and delay of having to copy it to each.
+ +Topics covered in this document:
+ +These instructions assume that you build Postfix from source +code as described in the INSTALL document. Some modification may +be required if you build Postfix from a vendor-specific source +package.
+ +The Postfix MongoDB client requires the mongo-c-driver library. +This can be built from source code from the +mongod-c project, or as a binary package from your OS distribution, +typically named mongo-c-driver-devel or libmongoc-dev. +Installing the mongo-c-driver library may also install libbson +as a dependency.
+ +To build Postfix with mongodb map support, add to the CCARGS +environment variable the options -DHAS_MONGODB and -I for the +directory containing the mongodb headers, and specify the AUXLIBS_MONGODB +with the libmongoc and libbson libraries, for example:
+ +++ ++% make tidy +% make -f Makefile.init makefiles \ + CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \ + -I/usr/include/libbson-1.0" \ + AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0" ++
The 'make tidy' command is needed only if you have previously +built Postfix without MongoDB support.
+ +If your MongoDB shared library is in a directory that the RUN-TIME +linker does not know about, add a "-Wl,-R,/path/to/directory" option +after "-lbson-1.0". Then, just run 'make'.
+ +In order to use MongoDB lookups, define a MongoDB source as a +table lookup in main.cf, for example:
+ +++ ++alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf ++
The file /etc/postfix/mongo-aliases.cf can specify a number of +parameters. For a complete description, see the mongodb_table(5) +manual page.
+ +Here's a basic example for using MongoDB to look up virtual(5) +aliases. Assume that in main.cf, you have:
+ +++ ++virtual_alias_maps = hash:/etc/postfix/virtual_aliases, + proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf ++
and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have:
+ +
+
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+result_attribute = username
+
+
+
+This example assumes mailbox names are stored in a MongoDB backend, +in a format like:
+ +
+
+{ "username": "user@example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+
+
+
+Upon receiving mail for "admin@example.com" that isn't found in the +/etc/postfix/virtual_aliases database, Postfix will search the +MongoDB server/cluster listening at port 27017 on some_server. It +will connect using the provided credentials, and search for any +entries whose username is, or alias field has "admin@example.com". +It will return the username attribute of those found, and build a +list of their email addresses.
+ +When it comes to mailing lists, one way of implementing one would +be as below:
+ +
+
+{ "name": "dev@example.com", "active": 1, "address":
+ [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
+
+
+
+using the filter below, will result in a comma separated string +with all email addresses in this list.
+ +
+
+query_filter = {"name": "%s", "active": 1}
+result_attribute = address
+
+
+
+Notes:
+ +As with projection, the Postfix mongodb client +automatically removes the top-level '_id' field from a result.
+The Postfix mongodb client will only parse result fields +with data types UTF8, INT32, INT64 and ARRAY. Other fields will be +ignored, with a warning in the logs.
This module also supports the use of more complex MongoDB +projections. There may be some use cases where operations such as +concatenation are necessary to be performed on the data retrieved +from the database. Although it is encouraged to keep the database +design simple enough so this is not necessary, postfix supports the +use of MongoDB projections to achieve the goal.
+ +Consider the example below:
+ +
+
+{ "username": "user@example.com",
+ "local_part": "user",
+ "domain": "example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+
+
+
+virtual_mailbox_maps can be created using below parameters in a +mongodb:/etc/postfix/mongo-virtual-mailboxes.cf file:
+ +
+
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
+
+
+
+This will return 'example.com/user' path built from the database fields.
+ +A couple of considerations when using projections:
+ +As with result_attribute, the Postfix mongodb client +automatically removes the top-level '_id' field from a projection +result.
The Postfix mongodb client will only parse fields with data +types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, +with a warning in the logs. It is suggested to exclude any unnecessary +fields when using a projection.
If you have questions, send them to postfix-users@postfix.org. +Please include relevant information about your Postfix setup: +MongoDB-related output from postconf, which libraries you built +with, and such. If your question involves your database contents, +please include the applicable bits of some database entries.
+ + + + diff --git a/postfix/proto/Makefile.in b/postfix/proto/Makefile.in index 511bd4448..ad7f73e50 100644 --- a/postfix/proto/Makefile.in +++ b/postfix/proto/Makefile.in @@ -30,6 +30,7 @@ HTML = ../html/ADDRESS_CLASS_README.html \ ../html/LMDB_README.html \ ../html/MEMCACHE_README.html \ ../html/MILTER_README.html \ + ../html/MONGODB_README.html \ ../html/MULTI_INSTANCE_README.html \ ../html/MYSQL_README.html ../html/NFS_README.html \ ../html/OVERVIEW.html \ @@ -78,6 +79,7 @@ README = ../README_FILES/ADDRESS_CLASS_README \ ../README_FILES/LMDB_README \ ../README_FILES/MEMCACHE_README \ ../README_FILES/MILTER_README \ + ../README_FILES/MONGODB_README \ ../README_FILES/MULTI_INSTANCE_README \ ../README_FILES/MYSQL_README ../README_FILES/NFS_README \ ../README_FILES/OVERVIEW \ @@ -240,6 +242,9 @@ clobber: ../html/MILTER_README.html: MILTER_README.html $(DETAB) $? | $(POSTLINK) >$@ +../html/MONGODB_README.html: MONGODB_README.html + $(DETAB) $? | $(POSTLINK) >$@ + ../html/MULTI_INSTANCE_README.html: MULTI_INSTANCE_README.html $(DETAB) $? | $(POSTLINK) >$@ @@ -420,6 +425,9 @@ clobber: ../README_FILES/MILTER_README: MILTER_README.html $(DETAB) $? | $(HT2READ) >$@ +../README_FILES/MONGODB_README: MONGODB_README.html + $(DETAB) $? | $(HT2READ) >$@ + ../README_FILES/MULTI_INSTANCE_README: MULTI_INSTANCE_README.html $(DETAB) $? | $(HT2READ) >$@ diff --git a/postfix/proto/mongodb_table b/postfix/proto/mongodb_table new file mode 100644 index 000000000..81dfc8e4d --- /dev/null +++ b/postfix/proto/mongodb_table @@ -0,0 +1,240 @@ +#++ +# NAME +# mongodb_table 5 +# SUMMARY +# Postfix MongoDB client configuration +# SYNOPSIS +# \fBpostmap -q "\fIstring\fB" mongodb:/etc/postfix/\fIfilename\fR +# +# \fBpostmap -q - mongodb:/etc/postfix/\fIfilename\fB <\fIinputfile\fR +# DESCRIPTION +# The Postfix mail system uses optional tables for address +# rewriting or mail routing. These tables are usually in +# \fBdbm\fR or \fBdb\fR format. +# +# Alternatively, lookup tables can be specified as MongoDB +# databases. In order to use MongoDB lookups, define a MongoDB +# source as a lookup table in main.cf, for example: +# .nf +# alias_maps = mongodb:/etc/postfix/mongodb-aliases.cf +# .fi +# +# In this example, the file /etc/postfix/mongodb-aliases.cf +# has the same format as the Postfix main.cf file, and can +# specify the parameters described below. It is also possible +# to have the configuration in main.cf; see "OBSOLETE MAIN.CF +# PARAMETERS" below. +# +# It is strongly recommended to use proxy:mongodb, in order +# to reduce the number of database connections. For example: +# .nf +# alias_maps = proxy:mongodb:/etc/postfix/mongodb-aliases.cf +# .fi +# +# Note: when using proxy:mongodb:/\fIfile\fR, the file must +# be readable by the unprivileged postfix user (specified +# with the Postfix mail_owner configuration parameter). +# MONGODB PARAMETERS +# .ad +# .fi +# .IP "\fBuri\fR" +# The URI of mongo server/cluster that Postfix will try to +# connect to and query from. Please see +# .nf +# https://www.mongodb.com/docs/manual/reference/connection-string/ +# .fi +# +# Example: +# .nf +# uri = mongodb+srv://user:pass@loclhost:27017/mail +# .fi +# .IP "\fBdbname\fR" +# Name of the database to read the information from. +# Example: +# .nf +# dbname = mail +# .fi +# .IP "\fBcollection\fR" +# Name of the collection (table) to read the information from. +# Example: +# .nf +# collection = mailbox +# .fi +# .IP "\fBquery_filter\fR" +# The MongoDB query template used to search the database, +# where \fB%s\fR is a substitute for the email address that +# Postfix is trying to resolve. Please see: +# .nf +# https://www.mongodb.com/docs/manual/tutorial/query-documents/ +# .fi +# +# Example: +# .nf +# query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1} +# .fi +# +# This parameter supports the following '%' expansions: +# .RS +# .IP "\fB%%\fR" +# This is replaced by a literal '%' character. +# .IP "\fB%s\fR" +# This is replaced by the input key. The %s must appear in +# quotes, because all Postfix queries are strings containing +# (parts from) a domain or email address. Postfix makes no +# numerical queries. +# .IP "\fB%u\fR" +# When the input key is an address of the form user@domain, +# \fB%u\fR is replaced by the local part of the address. +# Otherwise, \fB%u\fR is replaced by the entire search string. +# .IP "\fB%d\fR" +# When the input key is an address of the form user@domain, +# \fB%d\fR is replaced by the domain part of the address. +# .IP "\fB%[1-9]\fR" +# The patterns %1, %2, ... %9 are replaced by the corresponding +# most significant component of the input key's domain. If +# the input key is \fIuser@mail.example.com\fR, then %1 is +# \fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR. +# .RE +# .IP +# In the above substitutions, characters will be quoted as +# required by RFC 4627. For example, each double quote or +# backslash character will be escaped with a backslash +# characacter. +# .IP "\fBprojection\fR" +# Advanced MongoDB query projections. Please see: +# .nf +# https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/ +# .fi +# +# .RS +# .IP \(bu +# If \fBprojection\fR is non-empty, then \fBresult_attribute\fR +# must be empty. +# .IP \(bu +# This implementation can extract information only from result +# fields that have type \fBstring\fR (UTF8), \fBinteger\fR +# (int32, int64) and \fBarray\fR. Other result fields will +# be ignored with a warning. Please see: +# .nf +# https://mongoc.org/libbson/current/bson_type_t.html +# .fi +# .IP \(bu +# As with \fBresult_attribute\fR, the top-level _id field +# (type OID) is automatically removed from projection results. +# .RE +# .IP "\fBresult_attribute\fR" +# Comma or whitespace separated list with the names of fields +# to be returned in a lookup result. +# +# .RS +# .IP \(bu +# If \fBresult_attribute\fR is non-empty, then \fBprojection\fR +# must be empty. +# .IP \(bu +# As with \fBprojection\fR, the top-level _id field (type +# OID) is automatically removed from lookup results. +# .RE +# .IP "\fBresult_format (default: \fB%s\fR)\fR" +# Format template applied to the result from \fBprojection\fR +# or \fBresult_attribute\fR. Most commonly used to append (or +# prepend) text to the result. This parameter supports the +# following '%' expansions: +# .RS +# .IP "\fB%%\fR" +# This is replaced by a literal '%' character. +# .IP "\fB%s\fR" +# This is replaced by the value of the result attribute. When +# result is empty it is skipped. +# .IP "\fB%u\fR +# When the result attribute value is an address of the form +# user@domain, \fB%u\fR is replaced by the local part of the +# address. When the result has an empty localpart it is +# skipped. +# .IP "\fB%d\fR" +# When a result attribute value is an address of the form +# user@domain, \fB%d\fR is replaced by the domain part of the +# attribute value. When the result is unqualified it is +# skipped. +# .IP "\fB%[SUD1-9]\fR" +# The upper-case and decimal digit expansions interpolate the +# parts of the input key rather than the result. Their behavior +# is identical to that described with \fBquery_filter\fR, and +# in fact because the input key is known in advance, lookups +# whose key does not contain all the information specified +# in the result template are suppressed and return no results. +# .RE +# .IP +# For example, using "result_format = smtp:[%s]" allows one +# to use a mailHost attribute as the basis of a transport(5) +# table. After applying the result format, multiple values +# are concatenated as comma separated strings. The expansion_limit +# parameter explained below allows one to restrict the number +# of values in the result, which is especially useful for +# maps that should return a single value. +# +# The default value \fB%s\fR specifies that each +# attribute value should be used as is. +# +# NOTE: DO NOT put quotes around the result format! The result +# is not a JSON string. +# .IP "\fBdomain (default: no domain list)\fR" +# This is a list of domain names, paths to files, or "type:table" +# databases. When specified, only fully qualified search keys +# with a *non-empty* localpart and a matching domain are +# eligible for lookup: 'user' lookups, bare domain lookups +# and "@domain" lookups are not performed. This can significantly +# reduce the query load on the backend database. Example: +# .nf +# domain = postfix.org, hash:/etc/postfix/searchdomains +# .fi +# .IP "\fBexpansion_limit (default: 0)\fR" +# A limit on the total number of result elements returned (as +# a comma separated list) by a lookup against the map. A +# setting of zero disables the limit. Lookups fail with a +# temporary error if the limit is exceeded. Setting the limit +# to 1 ensures that lookups do not return multiple values. +# OBSOLETE MAIN.CF PARAMETERS +# .ad +# .fi +# MongoDB parameters can also be defined in main.cf. Specify +# as MongoDB source a name that doesn't begin with a slash +# or a dot. The MongoDB parameters will then be accessible +# as the name you've given the source in its definition, an +# underscore, and the name of the parameter. For example, if +# a map is specified as "mongodb:\fImongodb_source\fR", the +# "uri" parameter would be defined in main.cf as +# "\fImongodb_source\fR_uri". +# +# Note: with this form, passwords are written in main.cf, +# which is normally world-readable, and '$' in a mongodb +# parameter setting needs to be written as '$$'. +# SEE ALSO +# postmap(1), Postfix lookup table maintenance +# postconf(5), configuration parameters +# README FILES +# .ad +# .fi +# Use "\fBpostconf readme_directory\fR" or "\fBpostconf +# html_directory\fR" to locate this information. +# .na +# .nf +# DATABASE_README, Postfix lookup table overview +# MONGODB_README, Postfix MONGODB client guide +# LICENSE +# .ad +# .fi +# The Secure Mailer license must be distributed with this software. +# HISTORY +# MongoDB support was introduced with Postfix version 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 +#-- diff --git a/postfix/proto/stop b/postfix/proto/stop index c9b260241..37436858b 100644 --- a/postfix/proto/stop +++ b/postfix/proto/stop @@ -1595,3 +1595,4 @@ EOD chunking allowlists FWS +mongodb diff --git a/postfix/proto/stop.double-proto-html b/postfix/proto/stop.double-proto-html index e1df531f7..d79c684ee 100644 --- a/postfix/proto/stop.double-proto-html +++ b/postfix/proto/stop.double-proto-html @@ -355,3 +355,5 @@ RFC 2045 Sections 2 7 and 2 8 br br Such clients can be to become a list of comma separated names br br This feature the form of a domain name hostname hostname service hostname service expected to become a list of comma separated names br br This +Postfix Postfix can use MongoDB as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated noSQL database with fine grained access controls By not storing it + CCARGS CCARGS DHAS_MONGODB I usr include libmongoc 1 0 diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc index 9aa64c6e9..41d79beed 100644 --- a/postfix/proto/stop.spell-cc +++ b/postfix/proto/stop.spell-cc @@ -1814,3 +1814,23 @@ inlined stringz Sarvepalli uXXXX +Aionda +Ferraro +GmbH +Hamid +LLC +Maadani +MongoDB +PRId +bson +dexo +hamid +itoa +libmongoc +mongdb +mongo +mongodb +mongodbconf +Dextrous +Mongo +SUD diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history index 16d0e729f..d5e53d3a8 100644 --- a/postfix/proto/stop.spell-history +++ b/postfix/proto/stop.spell-history @@ -70,3 +70,6 @@ dehtml NONPROD LC Philosof +MONGODB +Refactored +Vijay diff --git a/postfix/proto/stop.spell-proto-html b/postfix/proto/stop.spell-proto-html index 6baa193e5..79c1ce533 100644 --- a/postfix/proto/stop.spell-proto-html +++ b/postfix/proto/stop.spell-proto-html @@ -359,3 +359,18 @@ wraptls api MinProtocol spammy +concat +hamid +ina +lbson +libbson +libmobgo +libmongoc +lmongoc +mongo +mongod +noSQL +srv +viktor +MONGODB +MongoDB diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 562290232..c7a1d36af 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -3,7 +3,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ canon_addr.c cfg_parser.c cleanup_strerror.c cleanup_strflags.c \ clnt_stream.c conv_time.c db_common.c debug_peer.c debug_process.c \ defer.c deliver_completed.c deliver_flock.c deliver_pass.c \ - deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c \ + deliver_request.c dict_ldap.c dict_mongodb.c dict_mysql.c dict_pgsql.c \ dict_proxy.c dict_sqlite.c domain_list.c dot_lockfile.c dot_lockfile_as.c \ dsb_scan.c dsn.c dsn_buf.c dsn_mask.c dsn_print.c dsn_util.c \ ehlo_mask.c ext_prop.c file_id.c flush_clnt.c header_opts.c \ @@ -80,13 +80,13 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. -MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o +MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o dict_mongodb.o HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \ conv_time.h db_common.h debug_peer.h debug_process.h defer.h \ deliver_completed.h deliver_flock.h deliver_pass.h deliver_request.h \ - dict_ldap.h dict_mysql.h dict_pgsql.h dict_proxy.h dict_sqlite.h domain_list.h \ + dict_ldap.h dict_mysql.h dict_pgsql.h dict_mongodb.h dict_proxy.h dict_sqlite.h domain_list.h \ dot_lockfile.h dot_lockfile_as.h dsb_scan.h dsn.h dsn_buf.h \ dsn_mask.h dsn_print.h dsn_util.h ehlo_mask.h ext_prop.h \ file_id.h flush_clnt.h header_opts.h header_token.h input_transp.h \ @@ -136,7 +136,7 @@ LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX) LIB_DIR = ../../lib INC_DIR = ../../include PLUGIN_MAP_SO = $(LIB_PREFIX)ldap$(LIB_SUFFIX) $(LIB_PREFIX)mysql$(LIB_SUFFIX) \ - $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) + $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) $(LIB_PREFIX)mongodb$(LIB_SUFFIX) MAKES = .c.o:; $(CC) $(SHLIB_CFLAGS) $(CFLAGS) -c $*.c @@ -173,6 +173,9 @@ $(LIB_PREFIX)pgsql$(LIB_SUFFIX): dict_pgsql.o $(LIB_PREFIX)sqlite$(LIB_SUFFIX): dict_sqlite.o $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_sqlite.o $(AUXLIBS_SQLITE) +$(LIB_PREFIX)mongodb$(LIB_SUFFIX): dict_mongodb.o + $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_mongodb.o $(AUXLIBS_MONGODB) + update: $(LIB_DIR)/$(LIB) $(HDRS) $(PLUGIN_MAP_SO_UPDATE) -for i in $(HDRS); \ do \ @@ -1210,6 +1213,24 @@ dict_memcache.o: dict_memcache.c dict_memcache.o: dict_memcache.h dict_memcache.o: memcache_proto.h dict_memcache.o: string_list.h +dict_mongodb.o: ../../include/argv.h +dict_mongodb.o: ../../include/auto_clnt.h +dict_mongodb.o: ../../include/check_arg.h +dict_mongodb.o: ../../include/dict.h +dict_mongodb.o: ../../include/match_list.h +dict_mongodb.o: ../../include/msg.h +dict_mongodb.o: ../../include/myflock.h +dict_mongodb.o: ../../include/mymalloc.h +dict_mongodb.o: ../../include/stringops.h +dict_mongodb.o: ../../include/sys_defs.h +dict_mongodb.o: ../../include/vbuf.h +dict_mongodb.o: ../../include/vstream.h +dict_mongodb.o: ../../include/vstring.h +dict_mongodb.o: cfg_parser.h +dict_mongodb.o: db_common.h +dict_mongodb.o: dict_mongodb.c +dict_mongodb.o: dict_mongodb.h +dict_mongodb.o: string_list.h dict_mysql.o: ../../include/argv.h dict_mysql.o: ../../include/check_arg.h dict_mysql.o: ../../include/dict.h @@ -1861,6 +1882,7 @@ mail_dict.o: ../../include/vstream.h mail_dict.o: ../../include/vstring.h mail_dict.o: dict_ldap.h mail_dict.o: dict_memcache.h +mail_dict.o: dict_mongodb.h mail_dict.o: dict_mysql.h mail_dict.o: dict_pgsql.h mail_dict.o: dict_proxy.h diff --git a/postfix/src/global/dict_mongodb.c b/postfix/src/global/dict_mongodb.c new file mode 100644 index 000000000..1aa36b3f2 --- /dev/null +++ b/postfix/src/global/dict_mongodb.c @@ -0,0 +1,569 @@ +/*++ +/* NAME +/* dict_mongodb 3 +/* SUMMARY +/* dictionary interface to mongodb, compatible with libmongoc-1.0 +/* SYNOPSIS +/* #include