comparison src/plugins/plugin_misc_smtp.py @ 594:e629371a28d3

Fix pep8 support in src/plugins.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:35 +0100
parents beaf6bec2fcd
children 6fd1095b2b7b
comparison
equal deleted inserted replaced
593:70bae685d05c 594:e629371a28d3
19 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """ 20 """
21 21
22 from logging import debug, info, error 22 from logging import debug, info, error
23 import warnings 23 import warnings
24 from twisted.internet import protocol,defer 24 from twisted.internet import protocol, defer
25 from twisted.words.protocols.jabber import error as jab_error 25 from twisted.words.protocols.jabber import error as jab_error
26 from twisted.cred import portal,checkers,credentials 26 from twisted.cred import portal, checkers, credentials
27 from twisted.cred import error as cred_error 27 from twisted.cred import error as cred_error
28 from twisted.mail import smtp 28 from twisted.mail import smtp
29 from twisted.python import failure 29 from twisted.python import failure
30 from email.parser import Parser 30 from email.parser import Parser
31 from email.utils import parseaddr 31 from email.utils import parseaddr
32 from twisted.mail.imap4 import LOGINCredentials, PLAINCredentials 32 from twisted.mail.imap4 import LOGINCredentials, PLAINCredentials
33 import os,os.path 33 import os
34 from twisted.internet import reactor 34 from twisted.internet import reactor
35 import sys 35 import sys
36 36
37
38 from zope.interface import implements 37 from zope.interface import implements
39 38
40
41 PLUGIN_INFO = { 39 PLUGIN_INFO = {
42 "name": "SMTP server Plugin", 40 "name": "SMTP server Plugin",
43 "import_name": "SMTP", 41 "import_name": "SMTP",
44 "type": "Misc", 42 "type": "Misc",
45 "protocols": [], 43 "protocols": [],
46 "dependencies": ["Maildir"], 44 "dependencies": ["Maildir"],
47 "main": "SMTP_server", 45 "main": "SMTP_server",
48 "handler": "no", 46 "handler": "no",
49 "description": _("""Create a SMTP server that you can use to send your "normal" type messages""") 47 "description": _("""Create a SMTP server that you can use to send your "normal" type messages""")
50 } 48 }
49
51 50
52 class SMTP_server(object): 51 class SMTP_server(object):
53 52
54 params = """ 53 params = """
55 <params> 54 <params>
72 info(_("Launching SMTP server on port %d"), port) 71 info(_("Launching SMTP server on port %d"), port)
73 72
74 self.server_factory = SmtpServerFactory(self.host) 73 self.server_factory = SmtpServerFactory(self.host)
75 reactor.listenTCP(port, self.server_factory) 74 reactor.listenTCP(port, self.server_factory)
76 75
76
77 class SatSmtpMessage(object): 77 class SatSmtpMessage(object):
78 implements(smtp.IMessage) 78 implements(smtp.IMessage)
79 79
80 def __init__(self, host, profile): 80 def __init__(self, host, profile):
81 self.host=host 81 self.host = host
82 self.profile=profile 82 self.profile = profile
83 self.message=[] 83 self.message = []
84 84
85 def lineReceived(self, line): 85 def lineReceived(self, line):
86 """handle another line""" 86 """handle another line"""
87 self.message.append(line) 87 self.message.append(line)
88 88
89 def eomReceived(self): 89 def eomReceived(self):
90 """handle end of message""" 90 """handle end of message"""
91 mail = Parser().parsestr("\n".join(self.message)) 91 mail = Parser().parsestr("\n".join(self.message))
92 try: 92 try:
93 self.host.sendMessage(parseaddr(mail['to'].decode('utf-8','replace'))[1], mail.get_payload().decode('utf-8','replace'), #TODO: manage other charsets 93 self.host.sendMessage(parseaddr(mail['to'].decode('utf-8', 'replace'))[1], mail.get_payload().decode('utf-8', 'replace'), # TODO: manage other charsets
94 subject=mail['subject'].decode('utf-8','replace'), mess_type='normal', profile_key=self.profile) 94 subject=mail['subject'].decode('utf-8', 'replace'), mess_type='normal', profile_key=self.profile)
95 except: 95 except:
96 exc_type, exc_value, exc_traceback = sys.exc_info() 96 exc_type, exc_value, exc_traceback = sys.exc_info()
97 error(_("Can't send message: %s") % exc_value) #The email is invalid or incorreclty parsed 97 error(_("Can't send message: %s") % exc_value) # The email is invalid or incorreclty parsed
98 return defer.fail() 98 return defer.fail()
99 self.message=None 99 self.message = None
100 return defer.succeed(None) 100 return defer.succeed(None)
101 101
102 def connectionLost(self): 102 def connectionLost(self):
103 """handle message truncated""" 103 """handle message truncated"""
104 raise smtp.SMTPError 104 raise smtp.SMTPError
105 105
106
106 class SatSmtpDelivery(object): 107 class SatSmtpDelivery(object):
107 implements(smtp.IMessageDelivery) 108 implements(smtp.IMessageDelivery)
108 109
109 def __init__(self, host, profile): 110 def __init__(self, host, profile):
110 self.host=host 111 self.host = host
111 self.profile=profile 112 self.profile = profile
112 113
113 def receivedHeader(self, helo, origin, recipients): 114 def receivedHeader(self, helo, origin, recipients):
114 """ 115 """
115 Generate the Received header for a message 116 Generate the Received header for a message
116 @param helo: The argument to the HELO command and the client's IP 117 @param helo: The argument to the HELO command and the client's IP
142 @return: origin or a Deferred whose callback will be 143 @return: origin or a Deferred whose callback will be
143 passed origin. 144 passed origin.
144 """ 145 """
145 return origin 146 return origin
146 147
148
147 class SmtpRealm(object): 149 class SmtpRealm(object):
148 implements(portal.IRealm) 150 implements(portal.IRealm)
149 151
150 def __init__(self,host): 152 def __init__(self, host):
151 self.host = host 153 self.host = host
152 154
153 def requestAvatar(self, avatarID, mind, *interfaces): 155 def requestAvatar(self, avatarID, mind, *interfaces):
154 debug('requestAvatar') 156 debug('requestAvatar')
155 profile=avatarID.decode('utf-8') 157 profile = avatarID.decode('utf-8')
156 if smtp.IMessageDelivery not in interfaces: 158 if smtp.IMessageDelivery not in interfaces:
157 raise NotImplementedError 159 raise NotImplementedError
158 return smtp.IMessageDelivery, SatSmtpDelivery(self.host,profile), lambda:None 160 return smtp.IMessageDelivery, SatSmtpDelivery(self.host, profile), lambda: None
161
159 162
160 class SatProfileCredentialChecker(object): 163 class SatProfileCredentialChecker(object):
161 """ 164 """
162 This credential checker check against SàT's profile and associated jabber's password 165 This credential checker check against SàT's profile and associated jabber's password
163 Check if the profile exists, and if the password is OK 166 Check if the profile exists, and if the password is OK
165 """ 168 """
166 implements(checkers.ICredentialsChecker) 169 implements(checkers.ICredentialsChecker)
167 credentialInterfaces = (credentials.IUsernamePassword, 170 credentialInterfaces = (credentials.IUsernamePassword,
168 credentials.IUsernameHashedPassword) 171 credentials.IUsernameHashedPassword)
169 172
170
171 def __init__(self, host): 173 def __init__(self, host):
172 self.host = host 174 self.host = host
173 175
174 def _cbPasswordMatch(self, matched, profile): 176 def _cbPasswordMatch(self, matched, profile):
175 if matched: 177 if matched:
180 def requestAvatarId(self, credentials): 182 def requestAvatarId(self, credentials):
181 profiles = self.host.memory.getProfilesList() 183 profiles = self.host.memory.getProfilesList()
182 if not credentials.username in profiles: 184 if not credentials.username in profiles:
183 return defer.fail(cred_error.UnauthorizedLogin()) 185 return defer.fail(cred_error.UnauthorizedLogin())
184 password = self.host.memory.getParamA("Password", "Connection", profile_key=credentials.username) 186 password = self.host.memory.getParamA("Password", "Connection", profile_key=credentials.username)
185 return defer.maybeDeferred( 187 return defer.maybeDeferred(credentials.checkPassword,
186 credentials.checkPassword, 188 password).addCallback(self._cbPasswordMatch,
187 password).addCallback( 189 credentials.username)
188 self._cbPasswordMatch, credentials.username) 190
189 191
190 class SmtpServerFactory(smtp.SMTPFactory): 192 class SmtpServerFactory(smtp.SMTPFactory):
191 193
192 def __init__(self, host): 194 def __init__(self, host):
193 self.protocol = smtp.ESMTP 195 self.protocol = smtp.ESMTP
194 self.host=host 196 self.host = host
195 _portal = portal.Portal(SmtpRealm(self.host)) 197 _portal = portal.Portal(SmtpRealm(self.host))
196 _portal.registerChecker(SatProfileCredentialChecker(self.host)) 198 _portal.registerChecker(SatProfileCredentialChecker(self.host))
197 smtp.SMTPFactory.__init__(self, _portal) 199 smtp.SMTPFactory.__init__(self, _portal)
198 200
199 def startedConnecting(self, connector): 201 def startedConnecting(self, connector):
200 debug (_("SMTP server connection started")) 202 debug(_("SMTP server connection started"))
201 smtp.SMTPFactory.startedConnecting(self, connector) 203 smtp.SMTPFactory.startedConnecting(self, connector)
202 204
203 def clientConnectionLost(self, connector, reason): 205 def clientConnectionLost(self, connector, reason):
204 debug (_("SMTP server connection lost (reason: %s)"), reason) 206 debug(_("SMTP server connection lost (reason: %s)"), reason)
205 smtp.SMTPFactory.clientConnectionLost(self, connector, reason) 207 smtp.SMTPFactory.clientConnectionLost(self, connector, reason)
206 208
207 def buildProtocol(self, addr): 209 def buildProtocol(self, addr):
208 p = smtp.SMTPFactory.buildProtocol(self, addr) 210 p = smtp.SMTPFactory.buildProtocol(self, addr)
209 # add the challengers from imap4, more secure and complicated challengers are available 211 # add the challengers from imap4, more secure and complicated challengers are available
210 p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials} 212 p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials}
211 return p 213 return p
212