Commit ae35908e7857aa925ed3ff7343855a39c1eedaf1
1 parent
756dc057
Exists in
r5_design
and in
1 other branch
mailman setup (mail setup part)
Pending: web interface
Showing
10 changed files
with
291 additions
and
136 deletions
Show diff stats
config/roles/integration_server.rb
1 | name "integration_server" | 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 | # TODO colab and mailman-api should be able to run in separate hosts at some | 4 | # TODO colab and mailman-api should be able to run in separate hosts at some |
5 | # point in the future | 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 @@ | @@ -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. |
@@ -0,0 +1,74 @@ | @@ -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 |
@@ -0,0 +1,27 @@ | @@ -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,7 +357,12 @@ Crie/edite ``/etc/postfix/transport`` com o seguinte conteúdo: | ||
357 | 357 | ||
358 | 358 | ||
359 | Faça o download do arquivo :download:`postfix-to-mailman-centos.py` e salve no | 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 | Adicione o seguinte conteúdo no final do arquivo ``/etc/postfix/master.cf``: | 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,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. |
nodes.yaml
@@ -12,6 +12,8 @@ vagrant@integration: | @@ -12,6 +12,8 @@ vagrant@integration: | ||
12 | colab_from_address: '"Portal do Software Publico" <noreply@softwarepublico.dev>' | 12 | colab_from_address: '"Portal do Software Publico" <noreply@softwarepublico.dev>' |
13 | server_email: '"Portal do Software Publico" <noreply@softwarepublico.dev>' | 13 | server_email: '"Portal do Software Publico" <noreply@softwarepublico.dev>' |
14 | email_subject_prefix: '[spb]' | 14 | email_subject_prefix: '[spb]' |
15 | + lists_hostname: listas.softwarepublico.dev | ||
16 | + lists_admin: paulo@softwarelivre.org | ||
15 | peers: &PEERS | 17 | peers: &PEERS |
16 | integration: 10.10.10.2 | 18 | integration: 10.10.10.2 |
17 | email: 10.10.10.3 | 19 | email: 10.10.10.3 |
@@ -0,0 +1,30 @@ | @@ -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,6 +4,22 @@ run_on() { | ||
4 | vagrant ssh "$vm" -- "$@" | 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 | curl=/vagrant/test/bin/curl | 23 | curl=/vagrant/test/bin/curl |
8 | 24 | ||
9 | # make IP addresses avaliable at the environment so we can refer to hosts by | 25 | # make IP addresses avaliable at the environment so we can refer to hosts by |