Skip to content

Commit cbde785

Browse files
1 parent ad7d75f commit cbde785

21 files changed

+703
-0
lines changed

appengine/__init__.py

Whitespace-only changes.

appengine/mail/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## App Engine Email Docs Snippets
2+
3+
This sample application demonstrates different ways to send and receive email
4+
on App Engine
5+
6+
7+
<!-- auto-doc-link --><!-- end-auto-doc-link -->

appengine/mail/app.yaml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
runtime: python27
15+
api_version: 1
16+
threadsafe: yes
17+
18+
# [START bounce_service]
19+
# [START mail_service]
20+
inbound_services:
21+
- mail
22+
# [END mail_service]
23+
- mail_bounce
24+
# [END bounce_service]
25+
26+
handlers:
27+
- url: /user/.+
28+
script: user_signup.app
29+
- url: /send_mail
30+
script: send_mail.app
31+
- url: /send_message
32+
script: send_message.app
33+
# [START handle_incoming_email]
34+
- url: /_ah/mail/.+
35+
script: handle_incoming_email.app
36+
login: admin
37+
# [END handle_incoming_email]
38+
# [START handle_all_email]
39+
- url: /_ah/mail/owner@.*your_app_id\.appspotmail\.com
40+
script: handle_owner.app
41+
login: admin
42+
- url: /_ah/mail/support@.*your_app_id\.appspotmail\.com
43+
script: handle_support.app
44+
login: admin
45+
- url: /_ah/mail/.+
46+
script: handle_catchall.app
47+
login: admin
48+
# [END handle_all_email]
49+
# [START handle_bounced_email]
50+
- url: /_ah/bounce
51+
script: handle_bounced_email.app
52+
login: admin
53+
# [END handle_bounced_email]
54+
- url: /attachment
55+
script: attachment.app
56+
- url: /header
57+
script: header.app
58+
- url: /
59+
static_files: index.html
60+
upload: index.html

appengine/mail/attachment.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from google.appengine.api import app_identity
15+
from google.appengine.api import mail
16+
import webapp2
17+
18+
19+
# [START send_attachment]
20+
class AttachmentHandler(webapp2.RequestHandler):
21+
def post(self):
22+
f = self.request.POST['file']
23+
mail.send_mail(sender=('%[email protected]' %
24+
app_identity.get_application_id()),
25+
to="Albert Johnson <[email protected]>",
26+
subject="The doc you requested",
27+
body="""Attached is the document file you requested.
28+
29+
The example.com Team
30+
""",
31+
attachments=[(f.filename, f.file.read())])
32+
# [END send_attachment]
33+
self.response.content_type = 'text/plain'
34+
self.response.write('Sent %s to Albert.' % f.filename)
35+
36+
def get(self):
37+
self.response.content_type = 'text/html'
38+
self.response.write("""<html><body>
39+
<form method="post" enctype="multipart/form-data">
40+
Send a file to Albert:<br />
41+
<input type="file" name="file"><br /><br />
42+
<input type="submit" name="submit" value="Submit">
43+
</form></body></html""")
44+
45+
46+
app = webapp2.WSGIApplication([
47+
('/attachment', AttachmentHandler),
48+
], debug=True)

appengine/mail/attachment_test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the 'License');
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an 'AS IS' BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import attachment
15+
import webtest
16+
17+
18+
def test_send_mail(testbed):
19+
testbed.init_mail_stub()
20+
testbed.init_app_identity_stub()
21+
app = webtest.TestApp(attachment.app)
22+
response = app.post('/attachment', upload_files=[
23+
('file', 'hello.txt', 'Good day!')])
24+
assert response.status_int == 200
25+
assert 'Sent hello.txt to Albert.' in response.body
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import logging
15+
16+
from google.appengine.ext.webapp.mail_handlers import BounceNotificationHandler
17+
import webapp2
18+
19+
20+
# [START bounce_handler]
21+
class LogBounceHandler(BounceNotificationHandler):
22+
def receive(self, bounce_message):
23+
logging.info('Received bounce post ... [%s]', self.request)
24+
logging.info('Bounce original: %s', bounce_message.original)
25+
logging.info('Bounce notification: %s', bounce_message.notification)
26+
# [END bounce_handler]
27+
28+
app = webapp2.WSGIApplication([LogBounceHandler.mapping()], debug=True)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the 'License');
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an 'AS IS' BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from google.appengine.ext.webapp.mail_handlers import BounceNotification
15+
16+
import handle_bounced_email
17+
18+
19+
def test_handle_bounced_email(testbed):
20+
handler = handle_bounced_email.LogBounceHandler()
21+
handler.request = 'request'
22+
bounced_message = BounceNotification({})
23+
handler.receive(bounced_message)

appengine/mail/handle_catchall.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# app.yaml defines that all email is handled by handle_incoming_email.py,
16+
# so nothing to do here.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START log_sender_handler]
16+
import logging
17+
18+
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
19+
import webapp2
20+
21+
22+
class LogSenderHandler(InboundMailHandler):
23+
def receive(self, mail_message):
24+
logging.info("Received a message from: " + mail_message.sender)
25+
# [END log_sender_handler]
26+
# [START bodies]
27+
plaintext_bodies = mail_message.bodies('text/plain')
28+
html_bodies = mail_message.bodies('text/html')
29+
30+
for content_type, body in html_bodies:
31+
decoded_html = body.decode()
32+
# ...
33+
# [END bodies]
34+
logging.info("Html body of length %d.", len(decoded_html))
35+
for content_type, body in plaintext_bodies:
36+
plaintext = body.decode()
37+
logging.info("Plain text body of length %d.", len(plaintext))
38+
39+
# [START app]
40+
app = webapp2.WSGIApplication([LogSenderHandler.mapping()], debug=True)
41+
# [END app]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the 'License');
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an 'AS IS' BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from google.appengine.api import mail
15+
16+
import handle_incoming_email
17+
18+
19+
def test_handle_bounced_email(testbed):
20+
handler = handle_incoming_email.LogSenderHandler()
21+
handler.request = 'request'
22+
message = mail.EmailMessage(
23+
24+
subject='Your account has been approved')
25+
message.to = 'Albert Johnson <[email protected]>'
26+
message.body = 'Dear Albert.'
27+
handler.receive(message)

0 commit comments

Comments
 (0)