diff --git a/defaults/main.yml b/defaults/main.yml
index 97f9790818ad84183bd1cf0f38a80e317f621edc..e3d735de2d2aeb36784bd6b93c3f177a0f9d919f 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -1,4 +1,33 @@
 ---
+# Transport map
+# <pattern> is an email address, domain name, or * to lookup the mail recipient
+# <result> specificies how and where to deliver mail and has the format
+#          <transport>:<nexthop>. Both <transport> and <nexthop> are optional,
+#          but the delimiting ':' is required.
+#
+# EXAMPLES:
+#
+# This configuration will pass mail for the domain 'internal.domain.com' without
+# modifying it, while discard all mail addressed to other recipient domains.
+#
+# postfix__transport_map:
+#   - { pattern: 'internal.domain.com', result: ':' }
+#   - { pattern: '*', result: 'discard:' }
+#
+#
+# This configuration will discard mail sent to localhost and will relay all
+# other mail through Mailgun.
+#
+# postfix__transport_map:
+#   - { pattern: 'localhost', result: 'discard:' }
+#   - { pattern: 'localhost.localdomain', result: 'discard:' }
+#   - { pattern: '*', result: 'relay:[smtp.mailgun.org]:587' }
+#
+#
+# Valid <transport> and <nexthop> values are described in the postfix transport
+# documentation. http://www.postfix.org/transport.5.html
+postfix__transport_map: []
+
 # The name of this mail system, set in '/etc/mailname'
 postfix__mailname: '{{ ansible_fqdn }}'
 
diff --git a/handlers/main.yml b/handlers/main.yml
index 004a153d481cb00c5e141e2eee970ac370fbb08d..d9d57795c8abc9ce195e4f453e5464ad6fc19501 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,4 +1,24 @@
 ---
+- name: make postfix transport.db
+  environment:
+    LC_MESSAGES: 'C'
+  command: make transport.db
+  args:
+    chdir: /etc/postfix
+  register: result
+  notify: ['reload postfix']
+  changed_when: "result.stdout != \"make: 'transport.db' is up to date.\""
+
+- name: make postfix
+  environment:
+    LC_MESSAGES: 'C'
+  command: make
+  args:
+    chdir: /etc/postfix
+  register: result
+  notify: ['reload postfix']
+  changed_when: "result.stdout != \"make: Nothing to be done for 'all'.\""
+
 - name: reload postfix
   command: /usr/sbin/postfix -c /etc/postfix check
   notify: ['reload postfix step 2']
diff --git a/tasks/main.yml b/tasks/main.yml
index 60ca5c76441905988575a113bf74746467700057..d9441e4279c4c90b2fb436438383b4b8914bd500 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -17,5 +17,23 @@
     group: root
     mode: 0644
   notify: ['reload postfix']
+
+- name: Place the Postfix makefile
+  template:
+    src: templates/Makefile.j2
+    dest: /etc/postfix/Makefile
+    owner: root
+    group: root
+    mode: 0644
+  notify: ['make postfix']
+
+- name: Generate Postfix transport map
+  template:
+    src: templates/transport.in.js
+    dest: /etc/postfix/transport.in
+    owner: root
+    group: root
+    mode: 0644
+  notify: ['make postfix transport.db']
 ...
 # vi: set ts=2 sts=2 sw=2 et ft=yaml: 
diff --git a/templates/Makefile.j2 b/templates/Makefile.j2
new file mode 100644
index 0000000000000000000000000000000000000000..deee71e2ce84707bd87e7592d5b072bbd19d1edd
--- /dev/null
+++ b/templates/Makefile.j2
@@ -0,0 +1,16 @@
+# {{ ansible_managed }}
+
+# Manage Postfix DB files idempotently
+
+MAPS = transport.db
+
+all: $(MAPS)
+
+aliases.db: aliases.in
+	postalias "$<" && mv -- "$<.db" "$@"
+
+%.db: %.in
+	postmap "$<" && mv -- "$<.db" "$@"
+
+clean:
+	rm -f *.db
diff --git a/templates/transport.in.js b/templates/transport.in.js
new file mode 100644
index 0000000000000000000000000000000000000000..715d8a2fcaa0aaa01b7464bf195e36c9c345baa7
--- /dev/null
+++ b/templates/transport.in.js
@@ -0,0 +1,5 @@
+# {{ ansible_managed }}
+
+{% for item in postfix__transport_map %}
+{{ item.pattern }} {{ item.result }}
+{% endfor %}