1
# -*- test-case-name: twisted.mail.test.test_options -*-
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
# See LICENSE for details.
6
"""I am the support module for creating mail servers with twistd
12
from twisted.mail import mail
13
from twisted.mail import maildir
14
from twisted.mail import relay
15
from twisted.mail import relaymanager
16
from twisted.mail import alias
18
from twisted.python import usage
20
from twisted.cred import checkers
21
from twisted.application import internet
24
class Options(usage.Options):
25
synopsis = "[options]"
28
["pop3", "p", 8110, "Port to start the POP3 server on (0 to disable).", usage.portCoerce],
29
["pop3s", "S", 0, "Port to start the POP3-over-SSL server on (0 to disable).", usage.portCoerce],
30
["smtp", "s", 8025, "Port to start the SMTP server on (0 to disable).", usage.portCoerce],
31
["certificate", "c", None, "Certificate file to use for SSL connections"],
33
"Relay messages according to their envelope 'To', using the given"
34
"path as a queue directory."],
35
["hostname", "H", None, "The hostname by which to identify this server."],
39
["esmtp", "E", "Use RFC 1425/1869 SMTP extensions"],
40
["disable-anonymous", None, "Disallow non-authenticated SMTP connections"],
42
zsh_actions = {"hostname" : "_hosts"}
44
longdesc = "This creates a mail.tap file that can be used by twistd."
47
usage.Options.__init__(self)
48
self.service = mail.MailService()
49
self.last_domain = None
51
def opt_passwordfile(self, filename):
52
"""Specify a file containing username:password login info for authenticated ESMTP connections."""
53
ch = checkers.OnDiskUsernamePasswordDatabase(filename)
54
self.service.smtpPortal.registerChecker(ch)
55
opt_P = opt_passwordfile
57
def opt_default(self):
58
"""Make the most recently specified domain the default domain."""
60
self.service.addDomain('', self.last_domain)
62
raise usage.UsageError("Specify a domain before specifying using --default")
65
def opt_maildirdbmdomain(self, domain):
66
"""generate an SMTP/POP3 virtual domain which saves to \"path\"
69
name, path = domain.split('=')
71
raise usage.UsageError("Argument to --maildirdbmdomain must be of the form 'name=path'")
73
self.last_domain = maildir.MaildirDirdbmDomain(self.service, os.path.abspath(path))
74
self.service.addDomain(name, self.last_domain)
75
opt_d = opt_maildirdbmdomain
77
def opt_user(self, user_pass):
78
"""add a user/password to the last specified domains
81
user, password = user_pass.split('=', 1)
83
raise usage.UsageError("Argument to --user must be of the form 'user=password'")
85
self.last_domain.addUser(user, password)
87
raise usage.UsageError("Specify a domain before specifying users")
90
def opt_bounce_to_postmaster(self):
91
"""undelivered mails are sent to the postmaster
93
self.last_domain.postmaster = 1
94
opt_b = opt_bounce_to_postmaster
96
def opt_aliases(self, filename):
97
"""Specify an aliases(5) file to use for this domain"""
98
if self.last_domain is not None:
99
if mail.IAliasableDomain.providedBy(self.last_domain):
100
aliases = alias.loadAliasFile(self.service.domains, filename)
101
self.last_domain.setAliasGroup(aliases)
102
self.service.monitor.monitorFile(
104
AliasUpdater(self.service.domains, self.last_domain)
107
raise usage.UsageError(
108
"%s does not support alias files" % (
109
self.last_domain.__class__.__name__,
113
raise usage.UsageError("Specify a domain before specifying aliases")
116
def postOptions(self):
118
if not self['certificate']:
119
raise usage.UsageError("Cannot specify --pop3s without "
121
elif not os.path.exists(self['certificate']):
122
raise usage.UsageError("Certificate file %r does not exist."
123
% self['certificate'])
125
if not self['disable-anonymous']:
126
self.service.smtpPortal.registerChecker(checkers.AllowAnonymousAccess())
128
if not (self['pop3'] or self['smtp'] or self['pop3s']):
129
raise usage.UsageError("You cannot disable all protocols")
132
def __init__(self, domains, domain):
133
self.domains = domains
135
def __call__(self, new):
136
self.domain.setAliasGroup(alias.loadAliasFile(self.domains, new))
138
def makeService(config):
140
rmType = relaymanager.SmartHostESMTPRelayingManager
141
smtpFactory = config.service.getESMTPFactory
143
rmType = relaymanager.SmartHostSMTPRelayingManager
144
smtpFactory = config.service.getSMTPFactory
147
dir = config['relay']
148
if not os.path.isdir(dir):
151
config.service.setQueue(relaymanager.Queue(dir))
152
default = relay.DomainQueuer(config.service)
154
manager = rmType(config.service.queue)
156
manager.fArgs += (None, None)
157
manager.fArgs += (config['hostname'],)
159
helper = relaymanager.RelayStateHelper(manager, 1)
160
helper.setServiceParent(config.service)
161
config.service.domains.setDefaultDomain(default)
164
if config['certificate']:
165
from twisted.mail.protocols import SSLContextFactory
166
ctx = SSLContextFactory(config['certificate'])
169
s = internet.TCPServer(config['pop3'], config.service.getPOP3Factory())
170
s.setServiceParent(config.service)
172
s = internet.SSLServer(config['pop3s'],
173
config.service.getPOP3Factory(), ctx)
174
s.setServiceParent(config.service)
178
if config['hostname']:
179
f.domain = config['hostname']
180
f.fArgs = (f.domain,)
182
f.fArgs = (None, None) + f.fArgs
183
s = internet.TCPServer(config['smtp'], f)
184
s.setServiceParent(config.service)
185
return config.service