From 436ad4e55fcfc137a600cb29b1c75e9b5542445b Mon Sep 17 00:00:00 2001 From: Jeffrey Rennie Date: Tue, 26 Apr 2016 12:44:50 -0700 Subject: [PATCH 1/3] Add mail samples. For https://cloud.google.com/appengine/docs/python/mail/ --- appengine/__init__.py | 0 appengine/mail/README.md | 7 ++ appengine/mail/app.yaml | 60 +++++++++++ appengine/mail/attachment.py | 48 +++++++++ appengine/mail/attachment_test.py | 25 +++++ appengine/mail/handle_bounced_email.py | 28 +++++ appengine/mail/handle_bounced_email_test.py | 23 ++++ appengine/mail/handle_catchall.py | 16 +++ appengine/mail/handle_incoming_email.py | 41 ++++++++ appengine/mail/handle_incoming_email_test.py | 27 +++++ appengine/mail/handle_owner.py | 16 +++ appengine/mail/handle_support.py | 16 +++ appengine/mail/header.py | 54 ++++++++++ appengine/mail/header_test.py | 25 +++++ appengine/mail/index.html | 29 ++++++ appengine/mail/send_mail.py | 48 +++++++++ appengine/mail/send_mail_test.py | 24 +++++ appengine/mail/send_message.py | 51 +++++++++ appengine/mail/send_message_test.py | 24 +++++ appengine/mail/user_signup.py | 104 +++++++++++++++++++ appengine/mail/user_signup_test.py | 37 +++++++ 21 files changed, 703 insertions(+) create mode 100644 appengine/__init__.py create mode 100644 appengine/mail/README.md create mode 100644 appengine/mail/app.yaml create mode 100644 appengine/mail/attachment.py create mode 100644 appengine/mail/attachment_test.py create mode 100644 appengine/mail/handle_bounced_email.py create mode 100644 appengine/mail/handle_bounced_email_test.py create mode 100644 appengine/mail/handle_catchall.py create mode 100644 appengine/mail/handle_incoming_email.py create mode 100644 appengine/mail/handle_incoming_email_test.py create mode 100644 appengine/mail/handle_owner.py create mode 100644 appengine/mail/handle_support.py create mode 100644 appengine/mail/header.py create mode 100644 appengine/mail/header_test.py create mode 100644 appengine/mail/index.html create mode 100644 appengine/mail/send_mail.py create mode 100644 appengine/mail/send_mail_test.py create mode 100644 appengine/mail/send_message.py create mode 100644 appengine/mail/send_message_test.py create mode 100644 appengine/mail/user_signup.py create mode 100644 appengine/mail/user_signup_test.py diff --git a/appengine/__init__.py b/appengine/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/appengine/mail/README.md b/appengine/mail/README.md new file mode 100644 index 00000000000..5ec82e066f7 --- /dev/null +++ b/appengine/mail/README.md @@ -0,0 +1,7 @@ +## App Engine Email Docs Snippets + +This sample application demonstrates different ways to send and receive email +on App Engine + + + diff --git a/appengine/mail/app.yaml b/appengine/mail/app.yaml new file mode 100644 index 00000000000..5b8e13f50fc --- /dev/null +++ b/appengine/mail/app.yaml @@ -0,0 +1,60 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +runtime: python27 +api_version: 1 +threadsafe: yes + +# [START bounce_service] +# [START mail_service] +inbound_services: +- mail +# [END mail_service] +- mail_bounce +# [END bounce_service] + +handlers: +- url: /user/.+ + script: user_signup.app +- url: /send_mail + script: send_mail.app +- url: /send_message + script: send_message.app +# [START handle_incoming_email] +- url: /_ah/mail/.+ + script: handle_incoming_email.app + login: admin +# [END handle_incoming_email] +# [START handle_all_email] +- url: /_ah/mail/owner@.*your_app_id\.appspotmail\.com + script: handle_owner.app + login: admin +- url: /_ah/mail/support@.*your_app_id\.appspotmail\.com + script: handle_support.app + login: admin +- url: /_ah/mail/.+ + script: handle_catchall.app + login: admin +# [END handle_all_email] +# [START handle_bounced_email] +- url: /_ah/bounce + script: handle_bounced_email.app + login: admin +# [END handle_bounced_email] +- url: /attachment + script: attachment.app +- url: /header + script: header.app +- url: / + static_files: index.html + upload: index.html \ No newline at end of file diff --git a/appengine/mail/attachment.py b/appengine/mail/attachment.py new file mode 100644 index 00000000000..9e3d431f829 --- /dev/null +++ b/appengine/mail/attachment.py @@ -0,0 +1,48 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from google.appengine.api import app_identity +from google.appengine.api import mail +import webapp2 + + +# [START send_attachment] +class AttachmentHandler(webapp2.RequestHandler): + def post(self): + f = self.request.POST['file'] + mail.send_mail(sender=('%s@appspot.gserviceaccount.com' % + app_identity.get_application_id()), + to="Albert Johnson ", + subject="The doc you requested", + body="""Attached is the document file you requested. + +The example.com Team +""", + attachments=[(f.filename, f.file.read())]) +# [END send_attachment] + self.response.content_type = 'text/plain' + self.response.write('Sent %s to Albert.' % f.filename) + + def get(self): + self.response.content_type = 'text/html' + self.response.write(""" +
+ Send a file to Albert:
+

+ +
+ Enter an email thread id: + +
""") + + def post(self): + print repr(self.request.POST) + id = self.request.POST['thread_id'] + send_example_mail('%s@appspot.gserviceaccount.com' % + app_identity.get_application_id(), id) + self.response.content_type = 'text/plain' + self.response.write( + 'Sent an email to Albert with Reference header set to %s.' % id) + + +app = webapp2.WSGIApplication([ + ('/header', SendMailHandler), +], debug=True) diff --git a/appengine/mail/header_test.py b/appengine/mail/header_test.py new file mode 100644 index 00000000000..8c7977b4d3d --- /dev/null +++ b/appengine/mail/header_test.py @@ -0,0 +1,25 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import header +import webtest + + +def test_send_mail(testbed): + testbed.init_mail_stub() + testbed.init_app_identity_stub() + app = webtest.TestApp(header.app) + response = app.post('/header', 'thread_id=42') + assert response.status_int == 200 + assert ('Sent an email to Albert with Reference header set to 42.' + in response.body) diff --git a/appengine/mail/index.html b/appengine/mail/index.html new file mode 100644 index 00000000000..aca2802936d --- /dev/null +++ b/appengine/mail/index.html @@ -0,0 +1,29 @@ + + + + + + Google App Engine Mail Samples + + +

Send email.

+

Send email with a message object.

+

Confirm a user's email address.

+

Send email with attachments.

+

Send email with headers.

+ + \ No newline at end of file diff --git a/appengine/mail/send_mail.py b/appengine/mail/send_mail.py new file mode 100644 index 00000000000..a87052d6a25 --- /dev/null +++ b/appengine/mail/send_mail.py @@ -0,0 +1,48 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from google.appengine.api import app_identity +from google.appengine.api import mail +import webapp2 + + +def send_approved_mail(sender_address): + # [BEGIN send_mail] + mail.send_mail(sender=sender_address, + to="Albert Johnson ", + subject="Your account has been approved", + body="""Dear Albert: + +Your example.com account has been approved. You can now visit +http://www.example.com/ and sign in using your Google Account to +access new features. + +Please let us know if you have any questions. + +The example.com Team +""") + # [SEND send_mail] + + +class SendMailHandler(webapp2.RequestHandler): + def get(self): + send_approved_mail('%s@appspot.gserviceaccount.com' % + app_identity.get_application_id()) + self.response.content_type = 'text/plain' + self.response.write('Sent an email to Albert.') + + +app = webapp2.WSGIApplication([ + ('/send_mail', SendMailHandler), +], debug=True) diff --git a/appengine/mail/send_mail_test.py b/appengine/mail/send_mail_test.py new file mode 100644 index 00000000000..9417f828797 --- /dev/null +++ b/appengine/mail/send_mail_test.py @@ -0,0 +1,24 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import send_mail +import webtest + + +def test_send_mail(testbed): + testbed.init_mail_stub() + testbed.init_app_identity_stub() + app = webtest.TestApp(send_mail.app) + response = app.get('/send_mail') + assert response.status_int == 200 + assert 'Sent an email to Albert.' in response.body diff --git a/appengine/mail/send_message.py b/appengine/mail/send_message.py new file mode 100644 index 00000000000..45ffc9e715e --- /dev/null +++ b/appengine/mail/send_message.py @@ -0,0 +1,51 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from google.appengine.api import app_identity +from google.appengine.api import mail +import webapp2 + + +def send_approved_mail(sender_address): + # [BEGIN send_message] + message = mail.EmailMessage( + sender=sender_address, + subject="Your account has been approved") + + message.to = "Albert Johnson " + message.body = """Dear Albert: + +Your example.com account has been approved. You can now visit +http://www.example.com/ and sign in using your Google Account to +access new features. + +Please let us know if you have any questions. + +The example.com Team +""" + message.send() + # [SEND send_message] + + +class SendMessageHandler(webapp2.RequestHandler): + def get(self): + send_approved_mail('%s@appspot.gserviceaccount.com' % + app_identity.get_application_id()) + self.response.content_type = 'text/plain' + self.response.write('Sent an email message to Albert.') + + +app = webapp2.WSGIApplication([ + ('/send_message', SendMessageHandler), +], debug=True) diff --git a/appengine/mail/send_message_test.py b/appengine/mail/send_message_test.py new file mode 100644 index 00000000000..e663cc0bb95 --- /dev/null +++ b/appengine/mail/send_message_test.py @@ -0,0 +1,24 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import send_message +import webtest + + +def test_send_message(testbed): + testbed.init_mail_stub() + testbed.init_app_identity_stub() + app = webtest.TestApp(send_message.app) + response = app.get('/send_message') + assert response.status_int == 200 + assert 'Sent an email message to Albert.' in response.body diff --git a/appengine/mail/user_signup.py b/appengine/mail/user_signup.py new file mode 100644 index 00000000000..56bf95909f5 --- /dev/null +++ b/appengine/mail/user_signup.py @@ -0,0 +1,104 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import datetime +import random +import socket +import string + +from google.appengine.api import app_identity +from google.appengine.api import mail +from google.appengine.ext import ndb +import webapp2 + + +# [START send-confirm-email] +class UserSignupHandler(webapp2.RequestHandler): + """Serves the email address sign up form.""" + + def post(self): + user_address = self.request.get('email_address') + + if not mail.is_email_valid(user_address): + self.get() # Show the form again. + else: + confirmation_url = create_new_user_confirmation(user_address) + sender_address = ( + 'Example.com Support <%s@appspot.gserviceaccount.com>' % + app_identity.get_application_id()) + subject = 'Confirm your registration' + body = """Thank you for creating an account! +Please confirm your email address by clicking on the link below: + +%s +""" % confirmation_url + mail.send_mail(sender_address, user_address, subject, body) +# [END send-confirm-email] + self.response.content_type = 'text/plain' + self.response.write('An email has been sent to %s.' % user_address) + + def get(self): + self.response.content_type = 'text/html' + self.response.write("""
+ Enter your email address: + +
""") + + +class UserConfirmationRecord(ndb.Model): + """Datastore record with email address and confirmation code.""" + user_address = ndb.StringProperty(indexed=False) + confirmed = ndb.BooleanProperty(indexed=False, default=False) + timestamp = ndb.DateTimeProperty(indexed=False, auto_now_add=True) + + +def create_new_user_confirmation(user_address): + """Create a new user confirmation. + + Args: + user_address: string, an email addres + + Returns: The url to click to confirm the email address.""" + id_chars = string.ascii_letters + string.digits + rand = random.SystemRandom() + random_id = ''.join([rand.choice(id_chars) for i in range(42)]) + record = UserConfirmationRecord(user_address=user_address, + id=random_id) + record.put() + return 'https://%s/user/confirm?code=%s' % ( + socket.getfqdn(socket.gethostname()), random_id) + + +class ConfirmUserSignupHandler(webapp2.RequestHandler): + """Invoked when the user clicks on the confirmation link in the email.""" + + def get(self): + code = self.request.get('code') + if code: + record = ndb.Key(UserConfirmationRecord, code).get() + # 2-hour time limit on confirming. + if record and (datetime.datetime.now() - record.timestamp < + datetime.timedelta(hours=2)): + record.confirmed = True + record.put() + self.response.content_type = 'text/plain' + self.response.write('Confirmed %s.' % record.user_address) + return + self.response.status_int = 404 + + +app = webapp2.WSGIApplication([ + ('/user/signup', UserSignupHandler), + ('/user/confirm', ConfirmUserSignupHandler), +], debug=True) diff --git a/appengine/mail/user_signup_test.py b/appengine/mail/user_signup_test.py new file mode 100644 index 00000000000..41f952819ac --- /dev/null +++ b/appengine/mail/user_signup_test.py @@ -0,0 +1,37 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import user_signup +import webtest + + +def test_user_signup(testbed): + testbed.init_mail_stub() + testbed.init_app_identity_stub() + testbed.init_datastore_v3_stub() + app = webtest.TestApp(user_signup.app) + response = app.post('/user/signup', 'email_address=alice@example.com') + assert response.status_int == 200 + assert 'An email has been sent to alice@example.com.' in response.body + + records = user_signup.UserConfirmationRecord.query().fetch(1) + response = app.get('/user/confirm?code=%s' % records[0].key.id()) + assert response.status_int == 200 + assert 'Confirmed alice@example.com.' in response.body + + +def test_bad_code(testbed): + testbed.init_datastore_v3_stub() + app = webtest.TestApp(user_signup.app) + response = app.get('/user/confirm?code=garbage', status=404) + assert response.status_int == 404 From 965794cf80f33ab2aeaf34dc3e119396d54b09c4 Mon Sep 17 00:00:00 2001 From: Jeffrey Rennie Date: Thu, 28 Apr 2016 13:19:57 -0700 Subject: [PATCH 2/3] Drop the copyright from app.yaml. --- appengine/mail/app.yaml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/appengine/mail/app.yaml b/appengine/mail/app.yaml index 5b8e13f50fc..1d254490b55 100644 --- a/appengine/mail/app.yaml +++ b/appengine/mail/app.yaml @@ -1,16 +1,3 @@ -# Copyright 2016 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. runtime: python27 api_version: 1 threadsafe: yes @@ -57,4 +44,4 @@ handlers: script: header.app - url: / static_files: index.html - upload: index.html \ No newline at end of file + upload: index.html From b08b35c79d86f8d796af8ec6be7c4a50425126ee Mon Sep 17 00:00:00 2001 From: Jeffrey Rennie Date: Thu, 28 Apr 2016 13:52:58 -0700 Subject: [PATCH 3/3] Accomodate reviewer's comments. --- appengine/mail/attachment.py | 10 ++++++---- appengine/mail/attachment_test.py | 1 + appengine/mail/handle_bounced_email.py | 1 + appengine/mail/handle_bounced_email_test.py | 1 + appengine/mail/handle_catchall.py | 16 ---------------- appengine/mail/handle_incoming_email_test.py | 1 + appengine/mail/handle_owner.py | 16 ---------------- appengine/mail/handle_support.py | 16 ---------------- appengine/mail/header.py | 7 ++++--- appengine/mail/header_test.py | 1 + appengine/mail/index.html | 2 +- appengine/mail/send_mail.py | 4 ++-- appengine/mail/send_mail_test.py | 1 + appengine/mail/send_message.py | 4 ++-- appengine/mail/send_message_test.py | 1 + appengine/mail/user_signup.py | 16 +++++++++------- appengine/mail/user_signup_test.py | 3 ++- 17 files changed, 33 insertions(+), 68 deletions(-) delete mode 100644 appengine/mail/handle_catchall.py delete mode 100644 appengine/mail/handle_owner.py delete mode 100644 appengine/mail/handle_support.py diff --git a/appengine/mail/attachment.py b/appengine/mail/attachment.py index 9e3d431f829..8717d0b1cb1 100644 --- a/appengine/mail/attachment.py +++ b/appengine/mail/attachment.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + from google.appengine.api import app_identity from google.appengine.api import mail import webapp2 @@ -20,18 +21,19 @@ class AttachmentHandler(webapp2.RequestHandler): def post(self): f = self.request.POST['file'] - mail.send_mail(sender=('%s@appspot.gserviceaccount.com' % - app_identity.get_application_id()), + mail.send_mail(sender='{}@appspot.gserviceaccount.com'.format( + app_identity.get_application_id()), to="Albert Johnson ", subject="The doc you requested", - body="""Attached is the document file you requested. + body=""" +Attached is the document file you requested. The example.com Team """, attachments=[(f.filename, f.file.read())]) # [END send_attachment] self.response.content_type = 'text/plain' - self.response.write('Sent %s to Albert.' % f.filename) + self.response.write('Sent {} to Albert.'.format(f.filename)) def get(self): self.response.content_type = 'text/html' diff --git a/appengine/mail/attachment_test.py b/appengine/mail/attachment_test.py index 10c998a79e0..d94415b1205 100644 --- a/appengine/mail/attachment_test.py +++ b/appengine/mail/attachment_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import attachment import webtest diff --git a/appengine/mail/handle_bounced_email.py b/appengine/mail/handle_bounced_email.py index 212e85efaa7..525ee128864 100644 --- a/appengine/mail/handle_bounced_email.py +++ b/appengine/mail/handle_bounced_email.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import logging from google.appengine.ext.webapp.mail_handlers import BounceNotificationHandler diff --git a/appengine/mail/handle_bounced_email_test.py b/appengine/mail/handle_bounced_email_test.py index 8088f800753..5ac31eca9c7 100644 --- a/appengine/mail/handle_bounced_email_test.py +++ b/appengine/mail/handle_bounced_email_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + from google.appengine.ext.webapp.mail_handlers import BounceNotification import handle_bounced_email diff --git a/appengine/mail/handle_catchall.py b/appengine/mail/handle_catchall.py deleted file mode 100644 index 722c947b0ab..00000000000 --- a/appengine/mail/handle_catchall.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2016 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# app.yaml defines that all email is handled by handle_incoming_email.py, -# so nothing to do here. diff --git a/appengine/mail/handle_incoming_email_test.py b/appengine/mail/handle_incoming_email_test.py index 1f124f785a2..17e0320f4c0 100644 --- a/appengine/mail/handle_incoming_email_test.py +++ b/appengine/mail/handle_incoming_email_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + from google.appengine.api import mail import handle_incoming_email diff --git a/appengine/mail/handle_owner.py b/appengine/mail/handle_owner.py deleted file mode 100644 index 722c947b0ab..00000000000 --- a/appengine/mail/handle_owner.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2016 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# app.yaml defines that all email is handled by handle_incoming_email.py, -# so nothing to do here. diff --git a/appengine/mail/handle_support.py b/appengine/mail/handle_support.py deleted file mode 100644 index 722c947b0ab..00000000000 --- a/appengine/mail/handle_support.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2016 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# app.yaml defines that all email is handled by handle_incoming_email.py, -# so nothing to do here. diff --git a/appengine/mail/header.py b/appengine/mail/header.py index bdd2b74a57e..1b15871519d 100644 --- a/appengine/mail/header.py +++ b/appengine/mail/header.py @@ -42,11 +42,12 @@ def get(self): def post(self): print repr(self.request.POST) id = self.request.POST['thread_id'] - send_example_mail('%s@appspot.gserviceaccount.com' % - app_identity.get_application_id(), id) + send_example_mail('{}@appspot.gserviceaccount.com'.format( + app_identity.get_application_id()), id) self.response.content_type = 'text/plain' self.response.write( - 'Sent an email to Albert with Reference header set to %s.' % id) + 'Sent an email to Albert with Reference header set to {}.' + .format(id)) app = webapp2.WSGIApplication([ diff --git a/appengine/mail/header_test.py b/appengine/mail/header_test.py index 8c7977b4d3d..4935c5999f1 100644 --- a/appengine/mail/header_test.py +++ b/appengine/mail/header_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import header import webtest diff --git a/appengine/mail/index.html b/appengine/mail/index.html index aca2802936d..c0b346c2576 100644 --- a/appengine/mail/index.html +++ b/appengine/mail/index.html @@ -26,4 +26,4 @@

Send email with attachments.

Send email with headers.

- \ No newline at end of file + diff --git a/appengine/mail/send_mail.py b/appengine/mail/send_mail.py index a87052d6a25..da90504a96f 100644 --- a/appengine/mail/send_mail.py +++ b/appengine/mail/send_mail.py @@ -37,8 +37,8 @@ def send_approved_mail(sender_address): class SendMailHandler(webapp2.RequestHandler): def get(self): - send_approved_mail('%s@appspot.gserviceaccount.com' % - app_identity.get_application_id()) + send_approved_mail('{}@appspot.gserviceaccount.com'.format( + app_identity.get_application_id())) self.response.content_type = 'text/plain' self.response.write('Sent an email to Albert.') diff --git a/appengine/mail/send_mail_test.py b/appengine/mail/send_mail_test.py index 9417f828797..f068ed64617 100644 --- a/appengine/mail/send_mail_test.py +++ b/appengine/mail/send_mail_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import send_mail import webtest diff --git a/appengine/mail/send_message.py b/appengine/mail/send_message.py index 45ffc9e715e..14465d60c70 100644 --- a/appengine/mail/send_message.py +++ b/appengine/mail/send_message.py @@ -40,8 +40,8 @@ def send_approved_mail(sender_address): class SendMessageHandler(webapp2.RequestHandler): def get(self): - send_approved_mail('%s@appspot.gserviceaccount.com' % - app_identity.get_application_id()) + send_approved_mail('{}@appspot.gserviceaccount.com'.format( + app_identity.get_application_id())) self.response.content_type = 'text/plain' self.response.write('Sent an email message to Albert.') diff --git a/appengine/mail/send_message_test.py b/appengine/mail/send_message_test.py index e663cc0bb95..640dc6efbb3 100644 --- a/appengine/mail/send_message_test.py +++ b/appengine/mail/send_message_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import send_message import webtest diff --git a/appengine/mail/user_signup.py b/appengine/mail/user_signup.py index 56bf95909f5..38b05bd2ca4 100644 --- a/appengine/mail/user_signup.py +++ b/appengine/mail/user_signup.py @@ -35,18 +35,19 @@ def post(self): else: confirmation_url = create_new_user_confirmation(user_address) sender_address = ( - 'Example.com Support <%s@appspot.gserviceaccount.com>' % - app_identity.get_application_id()) + 'Example.com Support <{}@appspot.gserviceaccount.com>'.format( + app_identity.get_application_id())) subject = 'Confirm your registration' body = """Thank you for creating an account! Please confirm your email address by clicking on the link below: -%s -""" % confirmation_url +{} +""".format(confirmation_url) mail.send_mail(sender_address, user_address, subject, body) # [END send-confirm-email] self.response.content_type = 'text/plain' - self.response.write('An email has been sent to %s.' % user_address) + self.response.write('An email has been sent to {}.'.format( + user_address)) def get(self): self.response.content_type = 'text/html' @@ -76,7 +77,7 @@ def create_new_user_confirmation(user_address): record = UserConfirmationRecord(user_address=user_address, id=random_id) record.put() - return 'https://%s/user/confirm?code=%s' % ( + return 'https://{}/user/confirm?code={}'.format( socket.getfqdn(socket.gethostname()), random_id) @@ -93,7 +94,8 @@ def get(self): record.confirmed = True record.put() self.response.content_type = 'text/plain' - self.response.write('Confirmed %s.' % record.user_address) + self.response.write('Confirmed {}.' + .format(record.user_address)) return self.response.status_int = 404 diff --git a/appengine/mail/user_signup_test.py b/appengine/mail/user_signup_test.py index 41f952819ac..d855ce7e140 100644 --- a/appengine/mail/user_signup_test.py +++ b/appengine/mail/user_signup_test.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import user_signup import webtest @@ -25,7 +26,7 @@ def test_user_signup(testbed): assert 'An email has been sent to alice@example.com.' in response.body records = user_signup.UserConfirmationRecord.query().fetch(1) - response = app.get('/user/confirm?code=%s' % records[0].key.id()) + response = app.get('/user/confirm?code={}'.format(records[0].key.id())) assert response.status_int == 200 assert 'Confirmed alice@example.com.' in response.body