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
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.
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
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.
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.
65 '<select name="salutation">'
66 '<option>Beloved</option>'
67 '<option>My dearest</option>'
68 '<option>Dear</option>'
69 '<option>Hello</option>'
73 '<input type="text" size="14" name="receiver_name">',
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>'
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>'
96 '<select name="will_be">'
97 '<option>admirer</option>'
98 '<option>best friend</option>'
99 '<option>friend</option>'
103 '<select name="good_bye">'
104 '<option>, just yours</option>'
105 '<option>lovingly</option>'
106 '<option>truly</option>'
107 '<option>sincerely</option>'
110 'secret_name': '<your secret name>'
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
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.
129 message: Message to display to the user upon error.
131 self
.redirect('/compose?error_message=%s' % message
)
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
147 values
= dict((k
, cgi
.escape(self
.request
.get(k
))) for k
in (
156 if not values
['secret_name'].strip():
157 self
.handle_error('What is your secret name?')
160 if not values
['receiver_name'].strip():
161 self
.handle_error('Who are you sending this too?')
164 #############################
166 # MAIN MAIL SENDING SECTION.
168 #############################
170 # Generate an EmailMessage object without a body.
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
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.')
199 except mail
.MissingRecipientsError
:
200 self
.handle_error('You must provide a recipient.')
202 except mail
.MissingBodyError
:
203 self
.handle_error('You must provide a mail format.')
206 # That's all there is to it!
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
))
215 ('/', SecretValentine
),
216 ('/compose', SecretValentine
),
221 application
= webapp
.WSGIApplication(_URLS
)
222 run_wsgi_app(application
)
225 if __name__
== '__main__':