Commit ae35908e7857aa925ed3ff7343855a39c1eedaf1

Authored by Antonio Terceiro
1 parent 756dc057

mailman setup (mail setup part)

Pending: web interface
config/roles/integration_server.rb
1 1 name "integration_server"
2   -description "Application that manages user authentication, visual integration and gamification"
  2 +description "Server that runs COLAB (user authentication, visual integration and gamification), mailman (mailing lists), and Gitlab (git repositories)"
3 3  
4 4 # TODO colab and mailman-api should be able to run in separate hosts at some
5 5 # point in the future
6   -run_list 'recipe[mailman-api]', 'recipe[colab]', 'recipe[basics::nginx]', 'recipe[colab::nginx]'
  6 +run_list 'recipe[mailman-api]', 'recipe[mailman]', 'recipe[colab]', 'recipe[basics::nginx]', 'recipe[colab::nginx]'
... ...
cookbooks/mailman/files/centos/postfix-to-mailman-centos.py 0 → 100755
... ... @@ -0,0 +1,133 @@
  1 +#! /usr/bin/env python
  2 +
  3 +# Configuration variables - Change these for your site if necessary.
  4 +MailmanHome = "/var/lib/mailman"; # Mailman home directory.
  5 +MailmanOwner = "postmaster@example.com"; # Postmaster and abuse mail recipient.
  6 +MailmanScripts = "/usr/lib/mailman"; # Where mailman scripts reside
  7 +
  8 +# End of configuration variables.
  9 +
  10 +# postfix-to-mailman-2.1.py (to be installed as postfix-to-mailman.py)
  11 +#
  12 +# Interface mailman to a postfix with a mailman transport. Does not require
  13 +# the creation of _any_ aliases to connect lists to your mail system.
  14 +#
  15 +# Dax Kelson, dkelson@gurulabs.com, Sept 2002.
  16 +# coverted from qmail to postfix interface
  17 +# Jan 2003: Fixes for Mailman 2.1
  18 +# Thanks to Simen E. Sandberg <senilix@gallerbyen.net>
  19 +# Feb 2003: Change the suggested postfix transport to support VERP
  20 +# Thanks to Henrique de Moraes Holschuh <henrique.holschuh@ima.sp.gov.br>
  21 +#
  22 +# This script was originally qmail-to-mailman.py by:
  23 +# Bruce Perens, bruce@perens.com, March 1999.
  24 +# This is free software under the GNU General Public License.
  25 +#
  26 +# This script is meant to be called from ~mailman/postfix-to-mailman.py.
  27 +# It catches all mail to a virtual domain, eg "lists.example.com".
  28 +# It looks at the recipient for each mail message and decides if the mail is
  29 +# addressed to a valid list or not, and bounces the message with a helpful
  30 +# suggestion if it's not addressed to a list. It decides if it is a posting,
  31 +# a list command, or mail to the list administrator, by checking for the
  32 +# -admin, -owner, and -request addresses. It will recognize a list as soon
  33 +# as the list is created, there is no need to add _any_ aliases for any list.
  34 +# It recognizes mail to postmaster, mailman-owner, abuse, mailer-daemon, root,
  35 +# and owner, and routes those mails to MailmanOwner as defined in the
  36 +# configuration variables, above.
  37 +#
  38 +# INSTALLATION:
  39 +#
  40 +# Install this file as ~mailman/postfix-to-mailman.py
  41 +#
  42 +# To configure a virtual domain to connect to mailman, edit Postfix thusly:
  43 +#
  44 +# /etc/postfix/main.cf:
  45 +# relay_domains = ... lists.example.com
  46 +# transport_maps = hash:/etc/postfix/transport
  47 +# mailman_destination_recipient_limit = 1
  48 +#
  49 +# /etc/postfix/transport:
  50 +# lists.example.com mailman:
  51 +#
  52 +# /etc/postfix/master.cf
  53 +# mailman unix - n n - - pipe
  54 +# flags=FR user=mailman:mailman
  55 +# argv=/var/mailman/postfix-to-mailman.py ${nexthop} ${user}
  56 +#
  57 +#
  58 +# Replace list.example.com above with the name of the domain to be connected
  59 +# to Mailman. Note that _all_ mail to that domain will go to Mailman, so you
  60 +# don't want to put the name of your main domain here. Typically a virtual
  61 +# domain lists.domain.com is used for Mailman, and domain.com for regular
  62 +# email.
  63 +#
  64 +
  65 +import sys, os, re, string
  66 +
  67 +def main():
  68 + os.nice(5) # Handle mailing lists at non-interactive priority.
  69 + # delete this if you wish
  70 +
  71 + os.chdir(MailmanHome + "/lists")
  72 +
  73 + try:
  74 + local = sys.argv[2]
  75 + except:
  76 + # This might happen if we're not using Postfix
  77 + sys.stderr.write("LOCAL not set?\n")
  78 + sys.exit(1)
  79 +
  80 + local = string.lower(local)
  81 + local = re.sub("^mailman-","",local)
  82 +
  83 + names = ("root", "postmaster", "mailer-daemon", "mailman-owner", "owner",
  84 + "abuse")
  85 + for i in names:
  86 + if i == local:
  87 + os.execv("/usr/sbin/sendmail",
  88 + ("/usr/sbin/sendmail", MailmanOwner))
  89 + sys.exit(0)
  90 +
  91 + type = "post"
  92 + types = (("-admin$", "admin"),
  93 + ("-owner$", "owner"),
  94 + ("-request$", "request"),
  95 + ("-bounces$", "bounces"),
  96 + ("-confirm$", "confirm"),
  97 + ("-join$", "join"),
  98 + ("-leave$", "leave"),
  99 + ("-subscribe$", "subscribe"),
  100 + ("-unsubscribe$", "unsubscribe"))
  101 +
  102 + for i in types:
  103 + if re.search(i[0],local):
  104 + type = i[1]
  105 + local = re.sub(i[0],"",local)
  106 +
  107 + if os.path.exists(local):
  108 + os.execv(MailmanScripts + "/mail/mailman",
  109 + (MailmanScripts + "/mail/mailman", type, local))
  110 + else:
  111 + bounce()
  112 + sys.exit(75)
  113 +
  114 +def bounce():
  115 + bounce_message = """\
  116 +TO ACCESS THE MAILING LIST SYSTEM: Start your web browser on
  117 +http://%s/
  118 +That web page will help you subscribe or unsubscribe, and will
  119 +give you directions on how to post to each mailing list.\n"""
  120 + sys.stderr.write(bounce_message % (sys.argv[1]))
  121 + sys.exit(1)
  122 +
  123 +try:
  124 + sys.exit(main())
  125 +except SystemExit, argument:
  126 + sys.exit(argument)
  127 +
  128 +except Exception, argument:
  129 + info = sys.exc_info()
  130 + trace = info[2]
  131 + sys.stderr.write("%s %s\n" % (sys.exc_type, argument))
  132 + sys.stderr.write("Line %d\n" % (trace.tb_lineno))
  133 + sys.exit(75) # Soft failure, try again later.
... ...
cookbooks/mailman/recipes/default.rb 0 → 100644
... ... @@ -0,0 +1,74 @@
  1 +package 'mailman'
  2 +
  3 +template '/etc/mailman/mm_cfg.py' do
  4 + owner 'root'
  5 + group 'mailman'
  6 + mode 0644
  7 + notifies :restart, 'service[mailman]'
  8 +end
  9 +
  10 +execute 'create-meta-list' do
  11 + admin = node['config']['lists_admin']
  12 + password = SecureRandom.random_number.to_s
  13 +
  14 + command "sudo -u mailman /usr/lib/mailman/bin/newlist --quiet mailman #{admin} $(openssl rand -hex 6)"
  15 +
  16 + not_if { File.exists?('/var/lib/mailman/lists/mailman') }
  17 + notifies :restart, 'service[mailman]'
  18 +end
  19 +
  20 +service 'mailman' do
  21 + action :enable
  22 + supports :restart => true
  23 +end
  24 +
  25 +package 'postfix'
  26 +package 'mailx' # for testing, etc
  27 +
  28 +execute 'postfix-config' do
  29 + command [
  30 + "postconf relay_domains=#{node['config']['lists_hostname']}",
  31 + "postconf transport_maps=hash:/etc/postfix/transport",
  32 + ].join(' && ')
  33 + only_if { !system('grep', node['config']['lists_hostname'], '/etc/postfix/main.cf') }
  34 + notifies :restart, 'service[postfix]'
  35 +end
  36 +
  37 +file '/etc/postfix/transport' do
  38 + owner 'root'
  39 + group 'root'
  40 + mode 0644
  41 + content "#{node['config']['lists_hostname']} mailman:\n"
  42 + notifies :run, 'execute[compile-postfix-transport]'
  43 +end
  44 +
  45 +execute 'compile-postfix-transport' do
  46 + command 'postmap /etc/postfix/transport'
  47 + action :nothing
  48 +end
  49 +
  50 +cookbook_file '/etc/postfix/postfix-to-mailman-centos.py' do
  51 + owner 'root'
  52 + group 'root'
  53 + mode 0755
  54 +end
  55 +
  56 +ruby_block 'configure-mailman-transport' do
  57 + block do
  58 + lines = [
  59 + 'mailman unix - n n - - pipe',
  60 + ' flags=FR user=mailman:mailman',
  61 + ' argv=/etc/postfix/postfix-to-mailman-centos.py ${nexthop} ${user}',
  62 + ]
  63 + File.open('/etc/postfix/master.cf', 'a') do |f|
  64 + lines.each do |line|
  65 + f.puts line
  66 + end
  67 + end
  68 + end
  69 + only_if { !system('grep', '^mailman', '/etc/postfix/master.cf')}
  70 +end
  71 +
  72 +service 'postfix' do
  73 + action [:enable, :reload]
  74 +end
... ...
cookbooks/mailman/templates/centos/mm_cfg.py.erb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +###############################################################
  2 +# copied from default mailman config file
  3 +###############################################################
  4 +from Defaults import *
  5 +import pwd, grp
  6 +MAILMAN_UID = pwd.getpwnam('mailman')[2]
  7 +MAILMAN_GID = grp.getgrnam('mailman')[2]
  8 +from socket import *
  9 +try:
  10 + fqdn = getfqdn()
  11 +except:
  12 + fqdn = 'mm_cfg_has_unknown_host_domains'
  13 +
  14 +
  15 +###############################################################
  16 +# site-specific items
  17 +###############################################################
  18 +
  19 +DEFAULT_URL_HOST = '<%= node['config']['external_hostname'] %>'
  20 +DEFAULT_EMAIL_HOST = '<%= node['config']['lists_hostname'] %>'
  21 +MTA = None
  22 +POSTFIX_STYLE_VIRTUAL_DOMAINS = ['<%= node['config']['lists_hostname']%>']
  23 +
  24 +###############################################################
  25 +# copied from default mailman config file
  26 +###############################################################
  27 +add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
... ...
docs/install.rst
... ... @@ -357,7 +357,12 @@ Crie/edite ``/etc/postfix/transport`` com o seguinte conteúdo:
357 357  
358 358  
359 359 Faça o download do arquivo :download:`postfix-to-mailman-centos.py` e salve no
360   -diretório ``/etc/postfix``.
  360 +diretório ``/etc/postfix``, e altere as permissões para tornar o arquivo
  361 +executável:
  362 +
  363 +.. code-block:: sh
  364 +
  365 + $ sudo chmod +x /etc/postfix/postfix-to-mailman-centos.py
361 366  
362 367 Adicione o seguinte conteúdo no final do arquivo ``/etc/postfix/master.cf``:
363 368  
... ...
docs/postfix-to-mailman-centos.py
... ... @@ -1,133 +0,0 @@
1   -#! /usr/bin/env python
2   -
3   -# Configuration variables - Change these for your site if necessary.
4   -MailmanHome = "/var/lib/mailman"; # Mailman home directory.
5   -MailmanOwner = "postmaster@example.com"; # Postmaster and abuse mail recipient.
6   -MailmanScripts = "/usr/lib/mailman"; # Where mailman scripts reside
7   -
8   -# End of configuration variables.
9   -
10   -# postfix-to-mailman-2.1.py (to be installed as postfix-to-mailman.py)
11   -#
12   -# Interface mailman to a postfix with a mailman transport. Does not require
13   -# the creation of _any_ aliases to connect lists to your mail system.
14   -#
15   -# Dax Kelson, dkelson@gurulabs.com, Sept 2002.
16   -# coverted from qmail to postfix interface
17   -# Jan 2003: Fixes for Mailman 2.1
18   -# Thanks to Simen E. Sandberg <senilix@gallerbyen.net>
19   -# Feb 2003: Change the suggested postfix transport to support VERP
20   -# Thanks to Henrique de Moraes Holschuh <henrique.holschuh@ima.sp.gov.br>
21   -#
22   -# This script was originally qmail-to-mailman.py by:
23   -# Bruce Perens, bruce@perens.com, March 1999.
24   -# This is free software under the GNU General Public License.
25   -#
26   -# This script is meant to be called from ~mailman/postfix-to-mailman.py.
27   -# It catches all mail to a virtual domain, eg "lists.example.com".
28   -# It looks at the recipient for each mail message and decides if the mail is
29   -# addressed to a valid list or not, and bounces the message with a helpful
30   -# suggestion if it's not addressed to a list. It decides if it is a posting,
31   -# a list command, or mail to the list administrator, by checking for the
32   -# -admin, -owner, and -request addresses. It will recognize a list as soon
33   -# as the list is created, there is no need to add _any_ aliases for any list.
34   -# It recognizes mail to postmaster, mailman-owner, abuse, mailer-daemon, root,
35   -# and owner, and routes those mails to MailmanOwner as defined in the
36   -# configuration variables, above.
37   -#
38   -# INSTALLATION:
39   -#
40   -# Install this file as ~mailman/postfix-to-mailman.py
41   -#
42   -# To configure a virtual domain to connect to mailman, edit Postfix thusly:
43   -#
44   -# /etc/postfix/main.cf:
45   -# relay_domains = ... lists.example.com
46   -# transport_maps = hash:/etc/postfix/transport
47   -# mailman_destination_recipient_limit = 1
48   -#
49   -# /etc/postfix/transport:
50   -# lists.example.com mailman:
51   -#
52   -# /etc/postfix/master.cf
53   -# mailman unix - n n - - pipe
54   -# flags=FR user=mailman:mailman
55   -# argv=/var/mailman/postfix-to-mailman.py ${nexthop} ${user}
56   -#
57   -#
58   -# Replace list.example.com above with the name of the domain to be connected
59   -# to Mailman. Note that _all_ mail to that domain will go to Mailman, so you
60   -# don't want to put the name of your main domain here. Typically a virtual
61   -# domain lists.domain.com is used for Mailman, and domain.com for regular
62   -# email.
63   -#
64   -
65   -import sys, os, re, string
66   -
67   -def main():
68   - os.nice(5) # Handle mailing lists at non-interactive priority.
69   - # delete this if you wish
70   -
71   - os.chdir(MailmanHome + "/lists")
72   -
73   - try:
74   - local = sys.argv[2]
75   - except:
76   - # This might happen if we're not using Postfix
77   - sys.stderr.write("LOCAL not set?\n")
78   - sys.exit(1)
79   -
80   - local = string.lower(local)
81   - local = re.sub("^mailman-","",local)
82   -
83   - names = ("root", "postmaster", "mailer-daemon", "mailman-owner", "owner",
84   - "abuse")
85   - for i in names:
86   - if i == local:
87   - os.execv("/usr/sbin/sendmail",
88   - ("/usr/sbin/sendmail", MailmanOwner))
89   - sys.exit(0)
90   -
91   - type = "post"
92   - types = (("-admin$", "admin"),
93   - ("-owner$", "owner"),
94   - ("-request$", "request"),
95   - ("-bounces$", "bounces"),
96   - ("-confirm$", "confirm"),
97   - ("-join$", "join"),
98   - ("-leave$", "leave"),
99   - ("-subscribe$", "subscribe"),
100   - ("-unsubscribe$", "unsubscribe"))
101   -
102   - for i in types:
103   - if re.search(i[0],local):
104   - type = i[1]
105   - local = re.sub(i[0],"",local)
106   -
107   - if os.path.exists(local):
108   - os.execv(MailmanScripts + "/mail/mailman",
109   - (MailmanScripts + "/mail/mailman", type, local))
110   - else:
111   - bounce()
112   - sys.exit(75)
113   -
114   -def bounce():
115   - bounce_message = """\
116   -TO ACCESS THE MAILING LIST SYSTEM: Start your web browser on
117   -http://%s/
118   -That web page will help you subscribe or unsubscribe, and will
119   -give you directions on how to post to each mailing list.\n"""
120   - sys.stderr.write(bounce_message % (sys.argv[1]))
121   - sys.exit(1)
122   -
123   -try:
124   - sys.exit(main())
125   -except SystemExit, argument:
126   - sys.exit(argument)
127   -
128   -except Exception, argument:
129   - info = sys.exc_info()
130   - trace = info[2]
131   - sys.stderr.write("%s %s\n" % (sys.exc_type, argument))
132   - sys.stderr.write("Line %d\n" % (trace.tb_lineno))
133   - sys.exit(75) # Soft failure, try again later.
docs/postfix-to-mailman-centos.py 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../cookbooks/mailman/files/centos/postfix-to-mailman-centos.py
0 2 \ No newline at end of file
... ...
nodes.yaml
... ... @@ -12,6 +12,8 @@ vagrant@integration:
12 12 colab_from_address: '"Portal do Software Publico" <noreply@softwarepublico.dev>'
13 13 server_email: '"Portal do Software Publico" <noreply@softwarepublico.dev>'
14 14 email_subject_prefix: '[spb]'
  15 + lists_hostname: listas.softwarepublico.dev
  16 + lists_admin: paulo@softwarelivre.org
15 17 peers: &PEERS
16 18 integration: 10.10.10.2
17 19 email: 10.10.10.3
... ...
test/mailman_test.sh 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +. $(dirname $0)/test_helper.sh
  2 +
  3 +test_mailman_running() {
  4 + assertTrue 'mailman running' 'run_on integration pgrep -fa mailmanctl'
  5 +}
  6 +
  7 +test_mailman_delivery() {
  8 + # create list
  9 + run_on integration sudo -u mailman /usr/lib/mailman/bin/newlist --quiet foobar foobar@example.com foobar
  10 + # subscribe us
  11 + echo 'foobar@example.com' | run_on integration sudo -u mailman /usr/lib/mailman/bin/add_members -r - --welcome-msg=n foobar > /dev/null
  12 +
  13 + # send message
  14 + date | run_on integration mail -r foobar@example.com -s test foobar@listas.softwarepublico.dev
  15 +
  16 + # wait for message to arrive at the list mailbox
  17 + mbox=/var/lib/mailman/archives/private/foobar.mbox/foobar.mbox
  18 + if wait_for integration $mbox; then
  19 + messages=$(run_on integration sudo grep -i -c ^Message-ID: $mbox)
  20 + else
  21 + messages=0
  22 + fi
  23 +
  24 + # remove list
  25 + run_on integration sudo -u mailman /usr/lib/mailman/bin/rmlist -a foobar > /dev/null
  26 +
  27 + assertEquals 'Message arrives at mailbox' "1" "$messages"
  28 +}
  29 +
  30 +. shunit2
... ...
test/test_helper.sh
... ... @@ -4,6 +4,22 @@ run_on() {
4 4 vagrant ssh "$vm" -- "$@"
5 5 }
6 6  
  7 +# waits until a file exists
  8 +wait_for() {
  9 + local machine="$1"
  10 + local file="$2"
  11 + local total=0
  12 + while [ "$total" -lt 10 ]; do
  13 + if run_on "$machine" sudo test -f "$file"; then
  14 + return 0
  15 + fi
  16 + sleep 1
  17 + total=$(($total + 1))
  18 + done
  19 + return 1
  20 +}
  21 +
  22 +
7 23 curl=/vagrant/test/bin/curl
8 24  
9 25 # make IP addresses avaliable at the environment so we can refer to hosts by
... ...