]> code.delx.au - monosys/blob - mail/sendmail.py
Actually listen to the debug level set on the command line
[monosys] / mail / sendmail.py
1 #!/usr/bin/env python
2
3 import decorators
4 import smtplib, email, urllib
5 import subprocess, sys, optparse
6 import logging
7
8 #### USER CONFIG #####
9 def getUserConfig():
10 smtpServers = (
11 SMTPProxy(remoteServer='mail.internode.on.net', domainSuffix='.internode.on.net'),
12 SMTPProxy(remoteServer='smtp.usyd.edu.au', domainSuffix='.usyd.edu.au'),
13 SMTPProxy(remoteServer='mail.iinet.net.au', domainSuffix='.iinet.net.au'),
14 SMTPProxy(remoteServer='mail.netspace.net.au', domainSuffix='.netspace.net.au'),
15 SMTPProxy(remoteServer='mail.optusnet.com.au', domainSuffix='.optusnet.com.au'),
16 SMTPProxySSH(remoteServer='kagami.tsukasa.net.au'), # Fall back to sending the email via ssh if nothing else
17 )
18
19 return smtpServers
20
21 #### REAL CODE STARTS HERE ####
22
23 class SMTPProxyBase(object):
24 def __repr__(self):
25 return '%s(%s)' % (self.__class__.__name__,
26 ', '.join('%s=%r' % (k, getattr(self, k)) for k in self.__slots__)
27 )
28
29 class SMTPProxy(SMTPProxyBase):
30 __slots__ = (
31 'remoteServer',
32 'domainSuffix',
33 'username',
34 'password',
35 'useSSL',
36 )
37 @decorators.logCall
38 def __init__(self, remoteServer, domainSuffix, username=None, password=None, useSSL=False):
39 self.remoteServer = remoteServer
40 self.domainSuffix = domainSuffix
41
42 self.username = username
43 self.password = password
44 self.useSSL = useSSL
45
46 def doesHandle(self, localhostName):
47 '''Determines if this SMTPProxy can be used within this domain'''
48 if localhostName is None:
49 return False
50 else:
51 return localhostName.endswith(self.domainSuffix)
52
53 def sendmail(self, fromAddr, toAddrs, message):
54 '''
55 Actually send the mail.
56
57 Returns true if the mail was successfully send
58 '''
59
60 smtp = smtplib.SMTP(self.remoteServer)
61 if self.useSSL:
62 smtp.starttls()
63 if self.username is not None and self.password is not None:
64 smtp.login(self.username, self.password)
65 smtp.sendmail(fromAddr, toAddrs, message)
66 smtp.quit()
67 return True
68
69 class SMTPProxySSH(SMTPProxyBase):
70 __slots__ = ('remoteServer',)
71 @decorators.logCall
72 def __init__(self, remoteServer):
73 self.remoteServer = remoteServer
74
75 def doesHandle(self, *args, **kwargs):
76 '''
77 Determines if this SMTPProxySSH can be used within this domain.
78 Note: This method returns true for all values.
79 '''
80 return True
81
82 def sendmail(self, fromAddr, toAddrs, message):
83 '''
84 Actually send the mail.
85
86 Returns true if the mail was successfully send
87 '''
88 cmdline = ['ssh', self.remoteServer, '/usr/sbin/sendmail', '--']
89 cmdline.extend(toAddrs)
90 process = subprocess.Popen(cmdline, stdin=subprocess.PIPE)
91 process.communicate(message)
92 return not bool(process.wait())
93
94 def getOptionParser():
95 parser = optparse.OptionParser(usage="%prog [options] toAddress1 [toAddress2] ...")
96 parser.add_option('--debug',
97 action='store_const', dest='debugLevel', const=logging.DEBUG,
98 help='Sets the logging level to debug')
99 parser.add_option('--warn',
100 action='store_const', dest='debugLevel', const=logging.WARNING,
101 help='Sets the logging level to warn')
102 parser.set_default('debugLevel', logging.ERROR)
103
104 return parser
105
106 def main():
107 # Get the to addresses
108 parser = getOptionParser()
109 options, toAddrs = parser.parse_args()
110 logging.basicConfig(level=options.debugLevel)
111 if not toAddrs:
112 parser.error('No to addresses found')
113
114 # Pick a SMTP server
115 try:
116 host = urllib.urlopen("http://suits.ug.it.usyd.edu.au/myip.php").read().strip()
117 except:
118 host = None
119 logging.exception('Failed to grab our external domain name')
120
121 for smtpProxy in getUserConfig():
122 if smtpProxy.doesHandle(host):
123 # Got the correct smtpServer
124 logging.info('Using the Proxy %r to connect from %s', smtpProxy, host)
125 break
126 else:
127 logging.info('Did not find a proxy to conncet from %s', host)
128 return False
129
130 # Get the from address
131 message = sys.stdin.read()
132 fromAddr = email.message_from_string(message)["from"]
133 _, fromAddr = email.utils.parseaddr(fromAddr)
134
135 return smtpProxy.sendmail(fromAddr, toAddrs, message)
136
137 if __name__ == "__main__":
138 # Specify SMTP servers here
139 sys.exit(not main())