1 """
2 A module that provides convenience functions for sending alerts. Currently
3 this includes sending text (SMS) messages or emails.
4
5 This is accomplished through two mechanisms: Google Voice B{or} SMTP.
6
7 Using Google Voice
8 ==================
9 To use Google Voice, this module requires a Google Voice account and depends on
10 pygooglevoice to access your Google Voice account.
11
12 You can sign up for a Google Voice account at
13 U{voice.google.com<http://voice.google.com>}.
14
15 pygooglevoice is in PyPI but unfortunately is not configured properly. You'll
16 have to download the source and run::
17
18 sudo python2 setup.py install
19
20 in the directory containing setup.py. You can download pygooglevoice at
21 U{code.google.com/p/pygooglevoice
22 <http://code.google.com/p/pygooglevoice/downloads/list/>}.
23
24 A quick example of sending an SMS message with Google Voice::
25
26 import nflgame.alert
27 nflgame.alert.google_voice_login('YOUR GMAIL ADDRESS', 'YOUR PASSWORD')
28 nflgame.alert.sms('1112223333', 'This is a text message!')
29
30 If you don't have a Google Voice account or don't want to install a third
31 party library, you can still use this module but the C{google_voice_login}
32 function will not work.
33
34 The disadvantage of using Google Voice is that it limits text messages. Since
35 you'll probably be using this module to send a fair number of alerts, this
36 might be prohibitive.
37
38 Using SMTP
39 ==========
40 SMTP can be used to send SMS messages or emails. For sending SMS messages,
41 the SMTP approach requires that you know the provider of the recipient's
42 cell phone (i.e., Verizon, Sprint, T-Mobile). Although this is a burden,
43 sending SMS messages through email doesn't seem to be as vigorously rate
44 limited as Google Voice is.
45
46 To send an SMS message using your GMail account::
47
48 import nflgame.alert
49 nflgame.alert.gmail_login('YOUR GMAIL ADDRESS', 'YOUR PASSWORD')
50 nflgame.alert.sms('1112223333', 'Test message', provider='Verizon')
51
52 In this case, the C{provider} parameter is required.
53
54 Similarly, you can send email alerts with your GMail account::
55
56 import nflgame.alert
57 nflgame.alert.gmail_login('YOUR GMAIL ADDRESS', 'YOUR PASSWORD')
58 nflgame.alert.email('somewhere@someplace.com', 'Email message')
59
60 Once you login to GMail using C{gmail_login}, you may send both text messages
61 and emails. You may be logged into Google Voice and GMail at the same time.
62
63 Using SMTP without GMail
64 ------------------------
65 You may use SMTP servers that aren't GMail by using C{smtp_login}. In fact,
66 C{gmail_login} is a special case of C{smtp_login}::
67
68 def gmail_login(email, passwd):
69 def connect():
70 gmail = smtplib.SMTP('smtp.gmail.com', port=587)
71 gmail.starttls()
72 return gmail
73
74 smtp_login(email, passwd, connect)
75
76 The connection setup must be provided as a function because it will
77 typically need to be reused in a long running program. (i.e., If you don't
78 send an alert for a while, you'll probably be disconnected from the SMTP
79 server. In which case, the connection setup will be executed again.)
80 """
81 import smtplib
82 import sys
83
84 try:
85 import googlevoice
86 _gv_available = True
87 except ImportError:
88 _gv_available = False
89
90 _voice = None
91 """Store the googlevoice.Voice instance."""
92
93 _smtp = None
94 """Store the smptplib.SMTP session instance."""
95
96 _email_from = None
97 """Stores the login email address for use in the 'from' field."""
98
99 _smtp_connect = None
100 """A function that will (re)connect and login"""
101
102
104 """
105 Logs into your Google Voice account with your full email address
106 (i.e., 'something@gmail.com') and password. This MUST be called before
107 using send without the provider parameter.
108 login only needs to be called once per program execution.
109
110 Note that your Google Voice login information is probably the same as your
111 gmail login information. Please be careful with your login credentials!
112 (It is not a bad idea to setup an entirely separate Google Voice account
113 just for sending SMS.)
114 """
115 global _voice
116
117 if not _gv_available:
118 print >> sys.stderr, "The pygooglevoice Python package is required " \
119 "in order to use Google Voice."
120 return
121
122 _voice = googlevoice.Voice()
123 _voice.login(email, passwd)
124
125
127 """
128 Logs into an SMTP mail server. connectfun should be a function that
129 takes no parameters and returns an smtplib.SMTP instance that is ready
130 to be logged into. (See the source of gmail_login for an example.)
131
132 username and passwd are then used to log into that smtplib.SMTP instance.
133
134 connectfun may be called again automatically if the SMTP connection
135 is broken during program execution.
136 """
137 global _email_from, _smtp, _smtp_connect
138
139 def connect():
140 smtp = connectfun()
141 smtp.login(email, passwd)
142 return smtp
143
144 _email_from = email
145 _smtp_connect = connect
146 _smtp = _smtp_connect()
147
148
150 """
151 Logs into your GMail account with your full email address
152 (i.e., 'something@gmail.com') and password. gmail_login MUST be called
153 before using sms with the provider parameter. It only needs to be called
154 once per program execution.
155 """
156 def connect():
157 gmail = smtplib.SMTP('smtp.gmail.com', port=587)
158 gmail.starttls()
159 return gmail
160
161 smtp_login(email, passwd, connect)
162
163
164 -def email(to_email, msg, from_email=None):
165 """
166 Sends an email to to_email with a message containing msg.
167
168 from_email is an optional parameter that specifies the 'from'
169 email address. If gmail_login was used, this is automatically
170 populated using the login email address. Otherwise it is left empty.
171 """
172 assert _smtp is not None, \
173 "Either gmail_login or smtp_login must be called to setup an " \
174 "smtplib.SMTP instance."
175
176 from_email_ = ''
177 if from_email is not None:
178 from_email_ = from_email
179 elif _email_from is not None:
180 from_email_ = _email_from
181
182 headers = [
183 'To: %s' % to_email,
184 'From: %s' % from_email_,
185 'Subject: nflgame alert',
186 ]
187 full_msg = '%s\r\n\r\n%s' % ('\r\n'.join(headers), msg)
188 _send_email(from_email_, to_email, full_msg)
189
190
191 -def sms(phone_number, msg, provider=None):
192 """
193 Sends an SMS message to phone_number (which should be a string) with
194 a message containing msg.
195
196 If you're using Google Voice to send SMS messages, google_voice_login
197 MUST be called before sms can be called. google_voice_login only needs to
198 be called once per program execution.
199
200 The provider parameter can be used to send SMS messages via email. It
201 is necessary because SMS messages are sent by sending a message to
202 an email like '111222333@vtext.com' or '1112223333@txt.att.net'. Thus,
203 each phone number must be paired with a provider.
204
205 A provider can be specified either as a carrier name (i.e., 'Verizon' or
206 'ATT'), or as simply the domain (i.e., 'vtext.com' or 'txt.att.net').
207 Supported providers are in the module level providers variable. Please
208 feel free to add to it and submit a pull request.
209
210 The provider parameter is not currently used, but is anticipated if this
211 module provides a way to send SMS messages via emails. A provider will be
212 required to look up the email domain. (i.e., for Verizon it's 'vtext.com'.)
213
214 Note that these are SMS messages, and each SMS message is limited to
215 160 characters. If msg is longer than that and you're using Google Voice,
216 it will be broken up into multiple SMS messages (hopefully). Otherwise,
217 if you're sending SMS messages via email, the behavior will vary
218 depending upon your carrier.
219 """
220 if provider is None:
221 assert _voice is not None, \
222 'You must login to Google Voice using google_voice_login before ' \
223 'sending an sms without the provider parameter.'
224 if provider is not None:
225 assert _smtp is not None, \
226 'You must login to an SMTP server using gmail_login or by ' \
227 'passing an smtplib.SMTP instance via the smtp parameter' \
228 'before sending an sms with the provider parameter.'
229
230 if provider is None:
231 _google_voice_sms(phone_number, msg)
232 else:
233 to = '%s@%s' % (phone_number, providers.get(provider, provider))
234 _send_email('', to, 'To: %s\r\n\r\n%s' % (to, msg))
235
236
238 """
239 Sends an SMS message to phone_number (which should be a string) with
240 a message containing msg.
241
242 google_voice_login MUST be called before _google_voice_sms can be called.
243 google_voice_login only needs to be called once per program execution.
244
245 Note that these are SMS messages, and each SMS message is limited to
246 160 characters. If msg is longer than that, it will be broken up into
247 multiple SMS messages.
248 """
249 try:
250 _voice.send_sms(phone_number, msg)
251 except googlevoice.ValidationError:
252
253
254 pass
255
256
258 """
259 Sends an email using nflgame.alert._smtp. It handles a connection that has
260 been disconnected, and reconnects.
261
262 Note that this only works if smtp_login (or gmail_login) was used.
263 """
264 global _smtp
265
266 try:
267 _smtp.sendmail(from_email, to_email, msg)
268 except smtplib.SMTPServerDisconnected:
269 _smtp = _smtp_connect()
270 _smtp.sendmail(from_email, to_email, msg)
271
272
273 providers = {
274 'ATT': 'txt.att.net',
275 'Boost': 'myboostmobile.com',
276 'Cricket': 'sms.mycricket.com',
277 'Sprint': 'messaging.sprintpcs.com',
278 'T-Mobile': 'tmomail.net',
279 'Verizon': 'vtext.com',
280 'Virgin Mobile': 'vmobl.com',
281 }
282 """
283 A dictionary of providers. The keys are English name identifiers of a
284 SMS provider. The values are domain suffixes that come after the
285 '@' symbol in an email address.
286 """
287