Domains
Domains are how Mailman interacts with email host names and web host names.
# The test framework starts out with an example domain, so let's delete
# that first.
>>> from mailman.interfaces.domain import IDomainManager
>>> from zope.component import getUtility
>>> domain_manager = getUtility(IDomainManager)
>>> domain_manager.remove('example.com')
<Domain example.com...>
>>> from mailman.config import config
>>> transaction = config.db
>>> transaction.commit()
The REST API can be queried for the set of known domains, of which there are initially none.
>>> from mailman.testing.documentation import dump_json
>>> dump_json('http://localhost:9001/3.0/domains')
http_etag: "..."
start: 0
total_size: 0
Once a domain is added, it is accessible through the API.
>>> domain_manager.add('example.com', 'An example domain')
<Domain example.com, An example domain>
>>> transaction.commit()
>>> dump_json('http://localhost:9001/3.0/domains')
entry 0:
alias_domain: None
base_url: None
description: An example domain
http_etag: "..."
mail_host: example.com
self_link: http://localhost:9001/3.0/domains/example.com
http_etag: "..."
start: 0
total_size: 1
At the top level, all domains are returned as separate entries.
>>> domain_manager.add('example.org',)
<Domain example.org>
>>> domain_manager.add(
... 'lists.example.net',
... 'Porkmasters')
<Domain lists.example.net, Porkmasters>
>>> # A list with an alias domain.
>>> domain_manager.add(
... 'mm.example.net',
... 'Porkmasters2',
... alias_domain='mmx.example.net')
<Domain mm.example.net, Porkmasters2, alias: mmx.example.net>
>>> transaction.commit()
>>> dump_json('http://localhost:9001/3.0/domains')
entry 0:
alias_domain: None
base_url: None
description: An example domain
http_etag: "..."
mail_host: example.com
self_link: http://localhost:9001/3.0/domains/example.com
entry 1:
alias_domain: None
base_url: None
description: None
http_etag: "..."
mail_host: example.org
self_link: http://localhost:9001/3.0/domains/example.org
entry 2:
alias_domain: None
base_url: None
description: Porkmasters
http_etag: "..."
mail_host: lists.example.net
self_link: http://localhost:9001/3.0/domains/lists.example.net
entry 3:
alias_domain: mmx.example.net
base_url: None
description: Porkmasters2
http_etag: "..."
mail_host: mm.example.net
self_link: http://localhost:9001/3.0/domains/mm.example.net
http_etag: "..."
start: 0
total_size: 4
Individual domains
The information for a single domain is available by following one of the
self_links
from the above collection.
>>> dump_json('http://localhost:9001/3.0/domains/lists.example.net')
alias_domain: None
base_url: None
description: Porkmasters
http_etag: "..."
mail_host: lists.example.net
self_link: http://localhost:9001/3.0/domains/lists.example.net
You can also list all the mailing lists for a given domain. At first, the example.com domain does not contain any mailing lists.
>>> dump_json('http://localhost:9001/3.0/domains/example.com/lists')
http_etag: "..."
start: 0
total_size: 0
>>> dump_json('http://localhost:9001/3.0/lists', {
... 'fqdn_listname': 'test-domains@example.com',
... })
content-length: 0
content-type: application/json
date: ...
location: http://localhost:9001/3.0/lists/test-domains.example.com
...
>>> dump_json('http://localhost:9001/3.0/domains/example.com/lists')
entry 0:
advertised: True
description:
display_name: Test-domains
fqdn_listname: test-domains@example.com
http_etag: "..."
...
member_count: 0
self_link: http://localhost:9001/3.0/lists/test-domains.example.com
volume: 1
http_etag: "..."
start: 0
total_size: 1
Other domains continue to contain no mailing lists.
>>> dump_json('http://localhost:9001/3.0/domains/lists.example.net/lists')
http_etag: "..."
start: 0
total_size: 0
Creating new domains
New domains can be created by posting to the domains
url.
>>> dump_json('http://localhost:9001/3.0/domains', {
... 'mail_host': 'lists.example.com',
... })
content-length: 0
content-type: application/json
date: ...
location: http://localhost:9001/3.0/domains/lists.example.com
...
Now the web service knows about our new domain.
>>> dump_json('http://localhost:9001/3.0/domains/lists.example.com')
alias_domain: None
base_url: None
description: None
http_etag: "..."
mail_host: lists.example.com
self_link: http://localhost:9001/3.0/domains/lists.example.com
And the new domain is in our database.
>>> domain_manager['lists.example.com']
<Domain lists.example.com>
# Unlock the database.
>>> transaction.abort()
You can also create a new domain with a description and a contact address.
>>> dump_json('http://localhost:9001/3.0/domains', {
... 'mail_host': 'my.example.com',
... 'description': 'My new domain',
... })
content-length: 0
content-type: application/json
date: ...
location: http://localhost:9001/3.0/domains/my.example.com
...
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com')
alias_domain: None
base_url: None
description: My new domain
http_etag: "..."
mail_host: my.example.com
self_link: http://localhost:9001/3.0/domains/my.example.com
>>> domain_manager['my.example.com']
<Domain my.example.com, My new domain>
# Unlock the database.
>>> transaction.abort()
Domain URLs
Domain have a base_url
property which allows Mailman to generate URLs
for Mailman’s Web Inteface. URL patterns are configured under [urlpatterns]
configuration.
Initially, the domain doesn’t have base_url
:
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com')
alias_domain: None
base_url: None
description: My new domain
http_etag: "..."
mail_host: my.example.com
self_link: http://localhost:9001/3.0/domains/my.example.com
Set the URL to the base_url
of the web interface. If you are using
Postorius it will look something like https://lists.example.com/mailman3
or https://lists.example.com/postorius
:
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com', {
... 'base_url': 'https://lists.example.com/mailman3',
... }, method='PATCH')
date: ...
server: gunicorn
status: 204
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com')
alias_domain: None
base_url: https://lists.example.com/mailman3
description: My new domain
http_etag: "..."
mail_host: my.example.com
self_link: http://localhost:9001/3.0/domains/my.example.com
Deleting domains
Domains can also be deleted via the API.
>>> dump_json('http://localhost:9001/3.0/domains/lists.example.com',
... method='DELETE')
date: ...
server: ...
status: 204
Domain owners
Domains can have owners. By posting some addresses to the owners resource, you can add some domain owners. Currently our domain has no owners:
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com/owners')
http_etag: ...
start: 0
total_size: 0
Anne and Bart volunteer to be a domain owners.
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com/owners', (
... ('owner', 'anne@example.com'), ('owner', 'bart@example.com')
... ))
date: ...
server: ...
status: 204
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com/owners',
... sort_entries='user_id')
entry 0:
created_on: 2005-08-01T07:49:23
http_etag: ...
is_server_owner: False
self_link: http://localhost:9001/3.0/users/1
user_id: 1
entry 1:
created_on: 2005-08-01T07:49:23
http_etag: ...
is_server_owner: False
self_link: http://localhost:9001/3.0/users/2
user_id: 2
http_etag: ...
start: 0
total_size: 2
We can delete all the domain owners.
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com/owners',
... method='DELETE')
date: ...
server: ...
status: 204
Now there are no owners.
>>> dump_json('http://localhost:9001/3.0/domains/my.example.com/owners')
http_etag: ...
start: 0
total_size: 0
New domains can be created with owners.
>>> dump_json('http://localhost:9001/3.0/domains', (
... ('mail_host', 'your.example.com'),
... ('owner', 'anne@example.com'),
... ('owner', 'bart@example.com'),
... ))
content-length: 0
content-type: application/json
date: ...
location: http://localhost:9001/3.0/domains/your.example.com
server: ...
status: 201
The new domain has the expected owners.
>>> dump_json('http://localhost:9001/3.0/domains/your.example.com/owners',
... sort_entries='user_id')
entry 0:
created_on: 2005-08-01T07:49:23
http_etag: ...
is_server_owner: False
self_link: http://localhost:9001/3.0/users/1
user_id: 1
entry 1:
created_on: 2005-08-01T07:49:23
http_etag: ...
is_server_owner: False
self_link: http://localhost:9001/3.0/users/2
user_id: 2
http_etag: ...
start: 0
total_size: 2