OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.mail.test.test_options -*- | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 | |
6 """I am the support module for creating mail servers with 'mktap' | |
7 """ | |
8 | |
9 import os | |
10 import sys | |
11 | |
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 | |
17 | |
18 from twisted.python import usage | |
19 | |
20 from twisted.cred import checkers | |
21 from twisted.application import internet | |
22 | |
23 | |
24 class Options(usage.Options): | |
25 synopsis = "Usage: mktap mail [options]" | |
26 | |
27 optParameters = [ | |
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 disab
le).", 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"
], | |
32 ["relay", "R", None, | |
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."
], | |
36 ] | |
37 | |
38 optFlags = [ | |
39 ["esmtp", "E", "Use RFC 1425/1869 SMTP extensions"], | |
40 ["disable-anonymous", None, "Disallow non-authenticated SMTP connections
"], | |
41 ] | |
42 zsh_actions = {"hostname" : "_hosts"} | |
43 | |
44 longdesc = "This creates a mail.tap file that can be used by twistd." | |
45 | |
46 def __init__(self): | |
47 usage.Options.__init__(self) | |
48 self.service = mail.MailService() | |
49 self.last_domain = None | |
50 | |
51 def opt_passwordfile(self, filename): | |
52 """Specify a file containing username:password login info for authentica
ted ESMTP connections.""" | |
53 ch = checkers.OnDiskUsernamePasswordDatabase(filename) | |
54 self.service.smtpPortal.registerChecker(ch) | |
55 opt_P = opt_passwordfile | |
56 | |
57 def opt_default(self): | |
58 """Make the most recently specified domain the default domain.""" | |
59 if self.last_domain: | |
60 self.service.addDomain('', self.last_domain) | |
61 else: | |
62 raise usage.UsageError("Specify a domain before specifying using --d
efault") | |
63 opt_D = opt_default | |
64 | |
65 def opt_maildirdbmdomain(self, domain): | |
66 """generate an SMTP/POP3 virtual domain which saves to \"path\" | |
67 """ | |
68 try: | |
69 name, path = domain.split('=') | |
70 except ValueError: | |
71 raise usage.UsageError("Argument to --maildirdbmdomain must be of th
e form 'name=path'") | |
72 | |
73 self.last_domain = maildir.MaildirDirdbmDomain(self.service, os.path.abs
path(path)) | |
74 self.service.addDomain(name, self.last_domain) | |
75 opt_d = opt_maildirdbmdomain | |
76 | |
77 def opt_user(self, user_pass): | |
78 """add a user/password to the last specified domains | |
79 """ | |
80 try: | |
81 user, password = user_pass.split('=', 1) | |
82 except ValueError: | |
83 raise usage.UsageError("Argument to --user must be of the form 'user
=password'") | |
84 if self.last_domain: | |
85 self.last_domain.addUser(user, password) | |
86 else: | |
87 raise usage.UsageError("Specify a domain before specifying users") | |
88 opt_u = opt_user | |
89 | |
90 def opt_bounce_to_postmaster(self): | |
91 """undelivered mails are sent to the postmaster | |
92 """ | |
93 self.last_domain.postmaster = 1 | |
94 opt_b = opt_bounce_to_postmaster | |
95 | |
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( | |
103 filename, | |
104 AliasUpdater(self.service.domains, self.last_domain) | |
105 ) | |
106 else: | |
107 raise usage.UsageError( | |
108 "%s does not support alias files" % ( | |
109 self.last_domain.__class__.__name__, | |
110 ) | |
111 ) | |
112 else: | |
113 raise usage.UsageError("Specify a domain before specifying aliases") | |
114 opt_A = opt_aliases | |
115 | |
116 def postOptions(self): | |
117 if self['pop3s']: | |
118 if not self['certificate']: | |
119 raise usage.UsageError("Cannot specify --pop3s without " | |
120 "--certificate") | |
121 elif not os.path.exists(self['certificate']): | |
122 raise usage.UsageError("Certificate file %r does not exist." | |
123 % self['certificate']) | |
124 | |
125 if not self['disable-anonymous']: | |
126 self.service.smtpPortal.registerChecker(checkers.AllowAnonymousAcces
s()) | |
127 | |
128 if not (self['pop3'] or self['smtp'] or self['pop3s']): | |
129 raise usage.UsageError("You cannot disable all protocols") | |
130 | |
131 class AliasUpdater: | |
132 def __init__(self, domains, domain): | |
133 self.domains = domains | |
134 self.domain = domain | |
135 def __call__(self, new): | |
136 self.domain.setAliasGroup(alias.loadAliasFile(self.domains, new)) | |
137 | |
138 def makeService(config): | |
139 if config['esmtp']: | |
140 rmType = relaymanager.SmartHostESMTPRelayingManager | |
141 smtpFactory = config.service.getESMTPFactory | |
142 else: | |
143 rmType = relaymanager.SmartHostSMTPRelayingManager | |
144 smtpFactory = config.service.getSMTPFactory | |
145 | |
146 if config['relay']: | |
147 dir = config['relay'] | |
148 if not os.path.isdir(dir): | |
149 os.mkdir(dir) | |
150 | |
151 config.service.setQueue(relaymanager.Queue(dir)) | |
152 default = relay.DomainQueuer(config.service) | |
153 | |
154 manager = rmType(config.service.queue) | |
155 if config['esmtp']: | |
156 manager.fArgs += (None, None) | |
157 manager.fArgs += (config['hostname'],) | |
158 | |
159 helper = relaymanager.RelayStateHelper(manager, 1) | |
160 helper.setServiceParent(config.service) | |
161 config.service.domains.setDefaultDomain(default) | |
162 | |
163 ctx = None | |
164 if config['certificate']: | |
165 from twisted.mail.protocols import SSLContextFactory | |
166 ctx = SSLContextFactory(config['certificate']) | |
167 | |
168 if config['pop3']: | |
169 s = internet.TCPServer(config['pop3'], config.service.getPOP3Factory()) | |
170 s.setServiceParent(config.service) | |
171 if config['pop3s']: | |
172 s = internet.SSLServer(config['pop3s'], | |
173 config.service.getPOP3Factory(), ctx) | |
174 s.setServiceParent(config.service) | |
175 if config['smtp']: | |
176 f = smtpFactory() | |
177 f.context = ctx | |
178 if config['hostname']: | |
179 f.domain = config['hostname'] | |
180 f.fArgs = (f.domain,) | |
181 if config['esmtp']: | |
182 f.fArgs = (None, None) + f.fArgs | |
183 s = internet.TCPServer(config['smtp'], f) | |
184 s.setServiceParent(config.service) | |
185 return config.service | |
OLD | NEW |