| 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 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
class VoicemailProProxy(smtpd.PureProxy): |
|---|
| 49 |
def process_message(self, peer, mailfrom, rcpttos, data): |
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
refused = self._deliver("vemergency@amor.org", rcpttos, data) |
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 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 |
|
|---|
| 70 |
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) |
|---|
| 71 |
servicemanager.LogInfoMsg("event created") |
|---|
| 72 |
|
|---|
| 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 |
|
|---|
| 81 |
servicemanager.LogMsg( |
|---|
| 82 |
servicemanager.EVENTLOG_INFORMATION_TYPE, |
|---|
| 83 |
servicemanager.PYS_SERVICE_STARTED, |
|---|
| 84 |
(self._svc_name_, ' (%s)' % self._svc_display_name_)) |
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
t = threading.Thread(None, asyncore.loop) |
|---|
| 88 |
t.start() |
|---|
| 89 |
|
|---|
| 90 |
|
|---|
| 91 |
win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) |
|---|
| 92 |
|
|---|
| 93 |
|
|---|
| 94 |
self.proxy.close() |
|---|
| 95 |
t.join() |
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 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 |
|
|---|
| 122 |
import win32traceutil |
|---|
| 123 |
except: |
|---|
| 124 |
log_error() |
|---|
| 125 |
raise |
|---|