allow history to work in webkit browsers
[gae-samples.git] / secret_valentine / secret-valentine.py
blobff8f7ecc30a0185b9fb0c51b9729cecbbc42fce5
1 #!/usr/bin/env python
3 # Copyright 2008 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 __author__ = 'Rafe Kaplan'
19 from google.appengine.api import mail
20 from google.appengine.api import users
21 from google.appengine.ext import webapp
22 from google.appengine.ext.webapp import template
23 from google.appengine.ext.webapp.util import run_wsgi_app
24 import cgi
25 import logging
26 import os
27 import sys
29 _DEBUG = True
31 # Change this value to an admin of your application
32 SECRET_VALENTINE_SENDER = 'secret.valentine.demo@gmail.com'
35 class SecretValentine(webapp.RequestHandler):
36 """Index page handler.
38 Generates form used to fill in information for secret valentine.
39 """
41 def get(self):
42 """Get index page.
44 The index page is generated by injecting a while bunch of HTML in to the
45 index template. This is a very simple form that does not attempt to
46 remember any additional state about the application, such as previous
47 selections.
48 """
49 # Resolve path to template.
50 directory = os.path.dirname(__file__)
51 path = os.path.join(directory, 'welcome.html')
53 # Values used in template. Each value for the form is an HTML input
54 # form corresponding to the fields of the secret valentine.
55 values = {
56 'error_message': self.request.get('error_message'),
58 # These HTML lines are in this file rather than a template because
59 # the template for the sending email is the same as the template
60 # for the input form. See message_body.html. Normally, it is
61 # desirable to be more clever than this, but this is clear enough
62 # for demonstration purposes.
64 'salutation':
65 '<select name="salutation">'
66 '<option>Beloved</option>'
67 '<option>My dearest</option>'
68 '<option>Dear</option>'
69 '<option>Hello</option>'
70 '</select>',
72 'receiver_name':
73 '<input type="text" size="14" name="receiver_name">',
75 'feeling_type':
76 '<select name="feeling_type">'
77 '<option>loving</option>'
78 '<option>fond</option>'
79 '<option>warm</option>'
80 '<option>angry</option>'
81 '<option>terrified</option>'
82 '<option>loathing</option>'
83 '</select>',
85 'thinking_activity':
86 '<select name="thinking_activity">'
87 '<option>swoon</option>'
88 '<option>lose my breath</option>'
89 '<option>smile</option>'
90 '<option>cry</option>'
91 '<option>scream</option>'
92 '<option>run</option>'
93 '</select>',
95 'will_be':
96 '<select name="will_be">'
97 '<option>admirer</option>'
98 '<option>best friend</option>'
99 '<option>friend</option>'
100 '</select>',
102 'good_bye':
103 '<select name="good_bye">'
104 '<option>, just yours</option>'
105 '<option>lovingly</option>'
106 '<option>truly</option>'
107 '<option>sincerely</option>'
108 '</select>',
110 'secret_name': '&lt;your secret name&gt;'
113 self.response.out.write(template.render(path, values, _DEBUG))
115 class PostMail(webapp.RequestHandler):
116 """Handles posting mail to recipient.
118 Main form handler. Merely receives fields and passes them to the
119 EmailMessage class.
122 def handle_error(self, message):
123 """Handle user error in input form.
125 Places the error message in to the request and redirects the
126 user back to the index page.
128 Args:
129 message: Message to display to the user upon error.
131 self.redirect('/compose?error_message=%s' % message)
133 def get(self):
134 """PostMail handler get method.
136 The email is generated in potentially two forms, text and HTML.
137 Each form of the mail has its own template each of which takes
138 the same parameters. The main function of this method is to
139 pass the form parameters to one or both of the templates and
140 pass the generated text to the email API.
143 directory = os.path.dirname(__file__)
145 # Copy a subset of the form to the mail templates parameter
146 # dict.
147 values = dict((k, cgi.escape(self.request.get(k))) for k in (
148 'salutation',
149 'receiver_name',
150 'feeling_type',
151 'thinking_activity',
152 'will_be',
153 'good_bye',
154 'secret_name'))
156 if not values['secret_name'].strip():
157 self.handle_error('What is your secret name?')
158 return
160 if not values['receiver_name'].strip():
161 self.handle_error('Who are you sending this too?')
162 return
164 #############################
166 # MAIN MAIL SENDING SECTION.
168 #############################
170 # Generate an EmailMessage object without a body.
171 try:
172 message = mail.EmailMessage(sender=SECRET_VALENTINE_SENDER,
173 to=self.request.get('email'),
174 subject='A Secret Valentine!')
176 # Report who really sent the email.
177 user = users.get_current_user()
178 values['nickname'] = user.nickname()
179 values['user_email'] = user.email()
180 message.reply_to = user.email()
182 # Generate the body depending on format selection.
183 # For each option, the templating engine is called to render
184 # the mail body.
185 format = self.request.get('format')
186 if format == 'text' or format == 'both':
187 template_file = os.path.join(directory, 'message.txt')
188 message.body = template.render(template_file, values, _DEBUG)
190 if format == 'html' or format == 'both':
191 template_file = os.path.join(directory, 'message.html')
192 message.html = template.render(template_file, values, _DEBUG)
194 message.check_initialized()
196 except mail.InvalidEmailError:
197 self.handle_error('Invalid email recipient.')
198 return
199 except mail.MissingRecipientsError:
200 self.handle_error('You must provide a recipient.')
201 return
202 except mail.MissingBodyError:
203 self.handle_error('You must provide a mail format.')
204 return
206 # That's all there is to it!
207 message.send()
208 values['mime_message'] = cgi.escape(str(message.ToMIMEMessage()))
210 # Render the sent page.
211 path = os.path.join(directory, 'sent.html')
212 self.response.out.write(template.render(path, values, _DEBUG))
214 _URLS = (
215 ('/', SecretValentine),
216 ('/compose', SecretValentine),
217 ('/send', PostMail))
220 def main(argv):
221 application = webapp.WSGIApplication(_URLS)
222 run_wsgi_app(application)
225 if __name__ == '__main__':
226 main(sys.argv)