forked from thinkst/canarytokens
-
Notifications
You must be signed in to change notification settings - Fork 0
/
smtpd.tac
155 lines (113 loc) · 4.43 KB
/
smtpd.tac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import re
from zope.interface import implements
from twisted.internet import defer
from twisted.mail import smtp
from twisted.cred.portal import IRealm
from twisted.cred.portal import Portal
class CanaryMessageDelivery:
implements(smtp.IMessageDelivery)
def __init__(self):
print 'Created CanaryMessageDelivery()'
def receivedHeader(self, helo, origin, recipients):
return "Received: CanaryMessageDelivery"
def validateFrom(self, helo, origin):
return origin
def validateTo(self, user):
# Only messages directed to the "console" user are accepted.
if user.dest.local == "console":
return lambda: CanaryMessage()
raise smtp.SMTPBadRcpt(user)
class CanaryMessage:
implements(smtp.IMessage)
def __init__(self):
self.headers = []
self.headers_finished = False
self.attachments = []
self.links = []
self.links_re = re.compile('.*(http[s]?://[^\s\'"]+).*', re.I)
self.mime_boundary = None
self.mime_boundary_re = re.compile('.*boundary="([^"]*)"')
self.in_mime_header = True
self.lines = []
self.stored_byte_count = 0
def lineReceived(self, line):
if line == '' and not self.headers_finished:
self.headers_finished = True
if not self.headers_finished:
self.headers.append(line)
m = self.mime_boundary_re.match(line)
if m:
self.mime_boundary = m.group(1)
else:
if self.mime_boundary:
if self.in_mime_header:
if line == '':
self.in_mime_header = False
else:
self.attachments[-1].append(line)
if self.mime_boundary in line:
self.in_mime_header = True
self.attachments.append([])
if self.stored_byte_count < 5*2**20: #5MB limit
self.lines.append(line)
self.stored_byte_count ++ len(line)
def eomReceived(self):
print "New message received:"
print "\n".join(self.headers)
print "\n".join(self.links)
print '\n\n'.join([ '\n'.join(x) for x in self.attachments])
self.lines = None
#return defer.succeed(None)
d = defer.Deferred()
d.callback("Success")
return d
def connectionLost(self):
# There was an error, throw away the stored lines
self.lines = None
class CanaryESMTP(smtp.ESMTP):
def __init__(self, **kwargs):
smtp.ESMTP.__init__(self, **kwargs)
def greeting(self,):
try:
return self.factory.responses['greeting']
except KeyError:
return smtp.ESMTP.greeting(self)
def receivedHeader(self, helo, origin, recipients):
return "Received: CanaryMessageDelivery"
def validateFrom(self, helo, origin):
return origin
def validateTo(self, user):
# Only messages directed to the "console" user are accepted.
if user.dest.local == "console":
return lambda: CanaryMessage()
raise smtp.SMTPBadRcpt(user)
class CanarySMTPFactory(smtp.SMTPFactory):
protocol = CanaryESMTP
def __init__(self, *a, **kw):
self.responses = kw.pop('responses')
smtp.SMTPFactory.__init__(self, *a, **kw)
# self.delivery = CanaryMessageDelivery()
def buildProtocol(self, addr):
p = smtp.SMTPFactory.buildProtocol(self, addr)
# p.delivery = self.delivery
# p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials}
return p
class SimpleRealm:
implements(IRealm)
def requestAvatar(self, avatarId, mind, *interfaces):
import pdb;pdb.set_trace()
if smtp.IMessageDelivery in interfaces:
return smtp.IMessageDelivery, CanaryMessageDelivery(), lambda: None
raise NotImplementedError()
def main():
from twisted.application import internet
from twisted.application import service
portal = Portal(SimpleRealm())
# checker = InMemoryUsernamePasswordDatabaseDontUse()
# checker.addUser("guest", "password")
# portal.registerChecker(checker)
responses = {'data_success': 'Finished', 'greeting': 'Hello there'}
a = service.Application("Canary SMTP Server")
internet.TCPServer(2500, CanarySMTPFactory(portal, responses=responses)).setServiceParent(a)
return a
application = main()