Contact: fumanchu@aminus.org

Log in as guest/misc to create tickets

root/vmpro_pager.py

Revision 122 (checked in by fumanchu, 2 years ago)

vmpro_pager: Better error handling.

  • Property svn:eol-style set to native
Line 
1 """Email proxy for Avaya's Voicemail Pro (which embeds G-Lock's EasyMail Pro).
2
3 Voicemail Pro has the capability to send email alerts when a voicemail
4 message is left in a given voicemail box. We use this capability at Amor
5 Ministries, for example, to run an "emergency extension"--if one of our
6 customers has an emergency after hours, they can leave a voicemail message
7 in this box, and various people will be paged to address the issue.
8
9 Unfortunately, the emails that Voicemail Pro sends out don't follow
10 RFC 821, which requires "MAIL FROM" before "DATA". This causes Exim,
11 which requires spec compliance, to choke. This module runs as an SMTP
12 proxy, fixing up the email from Voicemail Pro and forwarding it on to
13 a designated recipient. It only runs on localhost for security reasons.
14 """
15
16 def log_error():
17     import traceback
18     f = open(r"C:\diefile.txt", "wb")
19     traceback.print_exc(file=f)
20     f.close()
21
22
23 try:
24     import asyncore
25     import smtpd
26     import threading
27
28     import win32serviceutil
29     import win32service
30     import win32event
31     import servicemanager
32
33
34     class win32log:
35        
36         def write(self, msg):
37             servicemanager.LogInfoMsg('%s (%s): %s'
38                                       % (SMTPProxyService._svc_name_,
39                                          SMTPProxyService._svc_display_name_,
40                                          msg))
41        
42         def flush(self): pass
43     win32log = win32log()
44
45     ##smtpd.DEBUGSTREAM = win32log
46
47
48     class VoicemailProProxy(smtpd.PureProxy):
49         def process_message(self, peer, mailfrom, rcpttos, data):
50             # Fixup the mailfrom;
51             # Exim requires that it contain a domain, but it's coming through as "Voicemail2".
52             refused = self._deliver("vemergency@amor.org", rcpttos, data)
53            
54             # TBD: what to do with refused addresses?
55             win32log.write("Delivery results: %s" % repr(refused))
56             return refused
57
58
59     class SMTPProxyService(win32serviceutil.ServiceFramework):
60        
61         _svc_name_ = "vmpropager3"
62         _svc_display_name_ = "Voicemail Pro Email Fixup 3"
63        
64         def __init__(self, args, *a, **kw):
65             try:
66                 servicemanager.LogInfoMsg("entering init")
67                 win32serviceutil.ServiceFramework.__init__(self, args)
68                 servicemanager.LogInfoMsg("framework inited")
69                 # create an event that SvcDoRun can wait on and SvcStop can set.
70                 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
71                 servicemanager.LogInfoMsg("event created")
72                 # create our proxy instance
73                 self.proxy = VoicemailProProxy(("localhost", 25), ("192.168.0.6", 25))
74                 servicemanager.LogInfoMsg("proxy created")
75             except:
76                 log_error()
77                 raise
78        
79         def SvcDoRun(self):
80             # log a service started message
81             servicemanager.LogMsg(
82                 servicemanager.EVENTLOG_INFORMATION_TYPE,
83                 servicemanager.PYS_SERVICE_STARTED,
84                 (self._svc_name_, ' (%s)' % self._svc_display_name_))
85            
86             # Start the SMTP proxy listener loop in a separate thread
87             t = threading.Thread(None, asyncore.loop)
88             t.start()
89            
90             # Wait for a service stop request.
91             win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
92            
93             # signal stop and wait for the SMTP thread to stop
94             self.proxy.close()
95             t.join()
96            
97             # log a service stopped message
98             servicemanager.LogMsg(
99                 servicemanager.EVENTLOG_INFORMATION_TYPE,
100                 servicemanager.PYS_SERVICE_STOPPED,
101                 (self._svc_name_, ' (%s) ' % self._svc_display_name_))
102        
103         def SvcStop(self):
104             self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
105             win32event.SetEvent(self.hWaitStop)
106         SvcShutdown = SvcStop
107
108
109     if __name__ == '__main__':
110         import sys
111         if sys.argv[1:] == ['test']:
112             p = VoicemailProProxy(("localhost", 25), ("192.168.0.6", 25))
113             try:
114                 asyncore.loop()
115             except KeyboardInterrupt:
116                 p.close()
117         else:
118             print "handling command line"
119             win32serviceutil.HandleCommandLine(SMTPProxyService)
120     else:
121         # Don't use sys.stdout
122         import win32traceutil
123 except:
124     log_error()
125     raise
Note: See TracBrowser for help on using the browser.