]> code.delx.au - monosys/blob - pysendmail
xfce4-genmon-script: use long to parse zfs arc_used
[monosys] / pysendmail
1 #!/usr/bin/env python2
2
3 """
4 sendmailish python program.
5 Usage: sendmail.py toaddress
6
7
8 Sample config file
9 ------------------
10 # vim:ft=python
11
12 smtpServers = [
13 SMTPProxy(remoteServer='mail.internode.on.net', domainSuffix='.internode.on.net'),
14 SMTPProxy(remoteServer='smtp.usyd.edu.au', domainSuffix='.usyd.edu.au'),
15 SMTPProxy(remoteServer='mail.iinet.net.au', domainSuffix='.iinet.net.au'),
16 SMTPProxy(remoteServer='mail.netspace.net.au', domainSuffix='.netspace.net.au'),
17 SMTPProxy(remoteServer='mail.optusnet.com.au', domainSuffix='.optusnet.com.au'),
18 SMTPProxySSH(remoteServer='delx.net.au', remoteSendmail='/usr/sbin/sendmail'),
19 ]
20
21 myIPURL = "http://suits.ug.it.usyd.edu.au/myip.php"
22 """
23
24
25
26 import smtplib, email, urllib
27 import os.path, subprocess, sys, optparse
28 import logging
29
30 try:
31 # Attempt to load this debugging decorator function
32 from decorators import logCall
33 except ImportError:
34 def logCall(f):
35 '''This is a no-op decorator function'''
36 return f
37
38
39 class SMTPProxyBase(object):
40 def __repr__(self):
41 return '%s(%s)' % (
42 self.__class__.__name__,
43 ', '.join('%s=%r' % (k, getattr(self, k)) for k in self.__slots__)
44 )
45
46 class SMTPProxy(SMTPProxyBase):
47 __slots__ = (
48 'remoteServer',
49 'domainSuffix',
50 'username',
51 'password',
52 'useSSL',
53 )
54 @logCall
55 def __init__(self, remoteServer, domainSuffix, username=None, password=None, useSSL=False):
56 self.remoteServer = remoteServer
57 self.domainSuffix = domainSuffix
58
59 self.username = username
60 self.password = password
61 self.useSSL = useSSL
62
63 def doesHandle(self, localhostName):
64 '''Determines if this SMTPProxy can be used within this domain'''
65 if localhostName is None:
66 return False
67 else:
68 return localhostName.endswith(self.domainSuffix)
69
70 def sendmail(self, fromAddr, toAddrs, message):
71 '''
72 Actually send the mail.
73
74 Returns true if the mail was successfully send
75 '''
76
77 smtp = smtplib.SMTP(self.remoteServer)
78 if self.useSSL:
79 smtp.starttls()
80 if self.username is not None and self.password is not None:
81 smtp.login(self.username, self.password)
82 smtp.sendmail(fromAddr, toAddrs, message)
83 smtp.quit()
84 return True
85
86 class SMTPProxySSH(SMTPProxyBase):
87 __slots__ = ('remoteServer',)
88 @logCall
89 def __init__(self, remoteServer, remoteSendmail):
90 self.remoteServer = remoteServer
91 self.remoteSendmail = remoteSendmail
92
93 def doesHandle(self, *args, **kwargs):
94 '''
95 Determines if this SMTPProxySSH can be used within this domain.
96 Note: This method returns true for all values.
97 '''
98 return True
99
100 def sendmail(self, fromAddr, toAddrs, message):
101 '''
102 Actually send the mail.
103
104 Returns true if the mail was successfully send
105 '''
106 cmdline = ['ssh', self.remoteServer, self.remoteSendmail, '--']
107 cmdline.extend(toAddrs)
108 process = subprocess.Popen(cmdline, stdin=subprocess.PIPE)
109 process.communicate(message)
110 return not bool(process.wait())
111
112 def getOptionParser():
113 parser = optparse.OptionParser(usage="%prog [options] toAddress1 [toAddress2] ...")
114 parser.add_option('--debug',
115 action='store_const', dest='debugLevel', const=logging.DEBUG,
116 help='Sets the logging level to debug')
117 parser.add_option('--warn',
118 action='store_const', dest='debugLevel', const=logging.WARNING,
119 help='Sets the logging level to warn')
120 parser.set_default('debugLevel', logging.ERROR)
121
122 return parser
123
124 def main():
125 # Load the config file
126 try:
127 exec(open(os.path.expanduser('~/.sendmailpyrc'), 'r').read())
128 except Exception, e:
129 print >>sys.stderr, 'Error with config file:', e
130 return False
131
132 # Get the to addresses
133 parser = getOptionParser()
134 options, toAddrs = parser.parse_args()
135 logging.basicConfig(level=options.debugLevel)
136 if not toAddrs:
137 parser.error('No to addresses found')
138
139 # Pick a SMTP server
140 try:
141 host = urllib.urlopen(myIPURL).read().strip()
142 except:
143 host = None
144 logging.exception('Failed to grab our external domain name')
145
146 for smtpProxy in smtpServers:
147 if smtpProxy.doesHandle(host):
148 # Got the correct smtpServer
149 logging.info('Using the Proxy %r to connect from %s', smtpProxy, host)
150 break
151 else:
152 logging.error('Did not find a proxy to connect from %s', host)
153 return False
154
155 # Get the from address
156 message = sys.stdin.read()
157 fromAddr = email.message_from_string(message)["from"]
158 _, fromAddr = email.utils.parseaddr(fromAddr)
159
160 return smtpProxy.sendmail(fromAddr, toAddrs, message)
161
162 if __name__ == "__main__":
163 # Specify SMTP servers here
164 sys.exit(not main())
165