1<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
2<html>
3<head>
4<title>Postfix MongoDB Howto</title>
5<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6</head>
7<body>
8<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix MongoDB Howto</h1>
9<hr>
10
11<h2>MongoDB Support in Postfix</h2>
12
13<p> Postfix can use MongoDB as a source for any of its lookups:
14aliases(5), virtual(5), canonical(5), etc. This allows you to keep
15information for your mail service in a replicated noSQL database
16with fine-grained access controls. By not storing it locally on the
17mail server, the administrators can maintain it from anywhere, and
18the users can control whatever bits of it you think appropriate.
19You can have multiple mail servers using the same information,
20without the hassle and delay of having to copy it to each. </p>
21
22<p> Topics covered in this document:</p>
23
24<ul>
25<li><a href="#build">Building Postfix with MongoDB support</a>
26<li><a href="#config">Configuring MongoDB lookups</a>
27<li><a href="#example_virtual">Example: virtual alias maps</a>
28<li><a href="#example_mailing_list">Example: Mailing lists</a>
29<li><a href="#example_projections">Example: MongoDB projections</a>
30<li><a href="#feedback">Feedback</a>
31<li><a href="#credits">Credits</a>
32</ul>
33
34<h2><a name="build">Building Postfix with MongoDB support</a></h2>
35
36<p>These instructions assume that you build Postfix from source
37code as described in the INSTALL document. Some modification may
38be required if you build Postfix from a vendor-specific source
39package. </p>
40
41<p>The Postfix MongoDB client requires the <b>mongo-c-driver</b>
42library. This can be built from source code from <a
43href="https://github.com/mongodb/mongo-c-driver/releases">the
44mongod-c project</a>, or this can be installed as a binary package
45from your OS distribution, typically named <b>mongo-c-driver</b>,
46<b>mongo-c-driver-devel</b> or <b>libmongoc-dev</b>.
47Installing the mongo-c-driver library may also install <b>libbson</b>
48as a dependency. </p>
49
50<p> To build Postfix with mongodb map support, add to the CCARGS
51environment variable the options -DHAS_MONGODB and -I for the
52directory containing the mongodb headers, and specify the AUXLIBS_MONGODB
53with the libmongoc and libbson libraries, for example:</p>
54
55<blockquote>
56<pre>
57% make tidy
58% make -f Makefile.init makefiles \
59    CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
60    -I/usr/include/libbson-1.0" \
61    AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0"
62</pre>
63</blockquote>
64
65<p>The 'make tidy' command is needed only if you have previously
66built Postfix without MongoDB support. </p>
67
68<p>If your MongoDB shared library is in a directory that the RUN-TIME
69linker does not know about, add a "-Wl,-R,/path/to/directory" option
70after "-lbson-1.0". Then, just run 'make'.</p>
71
72<h2><a name="config">Configuring MongoDB lookups</a></h2>
73
74<p> In order to use MongoDB lookups, define a MongoDB source as a
75table lookup in main.cf, for example: </p>
76
77<blockquote>
78<pre>
79alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf
80</pre>
81</blockquote>
82
83<p> The file /etc/postfix/mongo-aliases.cf can specify a number of
84parameters. For a complete description, see the mongodb_table(5)
85manual page. </p>
86
87<h2><a name="example_virtual">Example: virtual(5) alias maps</a></h2>
88
89<p> Here's a basic example for using MongoDB to look up virtual(5)
90aliases. Assume that in main.cf, you have: </p>
91
92<blockquote>
93<pre>
94virtual_alias_maps = hash:/etc/postfix/virtual_aliases,
95    proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf
96</pre>
97</blockquote>
98
99<p> and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have: </p>
100
101<blockquote>
102<pre>
103uri = mongodb+srv://user_name:password@some_server
104dbname = mail
105collection = mailbox
106query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
107result_attribute = username
108</pre>
109</blockquote>
110
111<p>This example assumes mailbox names are stored in a MongoDB backend,
112in a format like:</p>
113
114<blockquote>
115<pre>
116{ "username": "user@example.com",
117  "alias": [
118    {"address": "admin@example.com"},
119    {"address": "abuse@example.com"}
120  ],
121  "active": 1
122}
123</pre>
124</blockquote>
125
126<p>Upon receiving mail for "admin@example.com" that isn't found in the
127/etc/postfix/virtual_aliases database, Postfix will search the
128MongoDB server/cluster listening at port 27017 on some_server. It
129will connect using the provided credentials, and search for any
130entries whose username is, or alias field has "admin@example.com".
131It will return the username attribute of those found, and build a
132list of their email addresses. </p>
133
134<p> Notes: </p>
135
136<ul>
137
138<li><p> As with <b>projection</b> (see below), the Postfix mongodb
139client automatically removes the top-level '_id' field from a
140result_attribute result. </p> </li>
141
142<li><p> The Postfix mongodb client will only parse result fields
143with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
144ignored, with a warning in the logs. </p> </li>
145
146</ul>
147
148<h2><a name="example_mailing_list">Example: Mailing lists</a></h2>
149
150<p>When it comes to mailing lists, one way of implementing one would
151be as below:</p>
152
153<blockquote>
154<pre>
155{ "name": "dev@example.com", "active": 1, "address":
156  [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
157</pre>
158</blockquote>
159
160<p>using the filter below, will result in a comma separated string
161with all email addresses in this list. </p>
162
163<blockquote>
164<pre>
165query_filter = {"name": "%s", "active": 1}
166result_attribute = address
167</pre>
168</blockquote>
169
170<p> Notes: </p>
171
172<ul>
173
174<li><p> As with <b>projection</b> (see below), the Postfix mongodb
175client automatically removes the top-level '_id' field from a
176result_attribute result. </p> </li>
177
178<li><p> The Postfix mongodb client will only parse result fields
179with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
180ignored, with a warning in the logs. </p> </li>
181
182</ul>
183
184<h2><a name="example_projections">Example: advanced projections</a></h2>
185
186<p>This module also supports the use of more complex MongoDB
187projections.  There may be some use cases where operations such as
188concatenation are necessary to be performed on the data retrieved
189from the database. Although it is encouraged to keep the database
190design simple enough so this is not necessary, postfix supports the
191use of MongoDB projections to achieve the goal. </p>
192
193<p>Consider the example below:</p>
194
195<blockquote>
196<pre>
197{ "username": "user@example.com",
198  "local_part": "user",
199  "domain": "example.com",
200  "alias": [
201    {"address": "admin@example.com"},
202    {"address": "abuse@example.com"}
203  ],
204  "active": 1
205}
206</pre>
207</blockquote>
208
209<p>virtual_mailbox_maps can be created using below parameters in a
210mongodb:/etc/postfix/mongo-virtual-mailboxes.cf file:</p>
211
212<blockquote>
213<pre>
214uri = mongodb+srv://user_name:password@some_server
215dbname = mail
216collection = mailbox
217query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
218projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
219</pre>
220</blockquote>
221
222<p>This will return 'example.com/user' path built from the database fields. </p>
223
224<p>A couple of considerations when using projections:</p>
225
226<ul>
227
228<li><p>As with <b>result_attribute</b>, the Postfix mongodb client
229automatically removes the top-level '_id' field from a projection
230result. </p></li>
231
232<li><p> The Postfix mongodb client will only parse fields with data
233types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored,
234with a warning in the logs. It is suggested to exclude any unnecessary
235fields when using a projection. </p></li>
236
237</ul>
238
239<h2><a name="feedback">Feedback</a></h2>
240
241<p> If you have questions, send them to postfix-users@postfix.org.
242Please include relevant information about your Postfix setup:
243MongoDB-related output from postconf, which libraries you built
244with, and such. If your question involves your database contents,
245please include the applicable bits of some database entries. </p>
246
247<h2><a name="credits">Credits</a></h2>
248
249<ul>
250
251<li> Stephan Ferraro (Aionda GmbH) implemented an early version of the
252Postfix MongoDB client.
253
254<li> Hamid Maadani (Dextrous Technologies, LLC) added support for
255projections and %<i>letter</i> interpolation, and added documentation.
256
257<li> Wietse Venema adopted and restructured the code and documentation.
258
259</ul>
260
261</body>
262
263</html>
264