Reputation: 2406
App Engine allows one to listen to incoming emails. I'd like to then read attachments and write them to a GCS bucket. google.cloud.storage
is not available in the standard environment, and cloudstorage
, which is available, doesn't allow writing in any other bucket but the default one.
I tried also in flexible env, but InboundMailHandler is not available in that case: "The App Engine Mail service is not available outside the standard environment" https://cloud.google.com/appengine/docs/flexible/python/migrating
Is there any way to write these files to a designated bucket, in a standard environment?
import logging
import webapp2
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
class LogSenderHandler(InboundMailHandler):
def receive(self, mail_message):
logging.info("Received a message from: " + mail_message.sender)
plaintext_bodies = mail_message.bodies('text/plain')
html_bodies = mail_message.bodies('text/html')
if hasattr(mail_message, 'attachments'):
for filename, filecontent in mail_message.attachments:
# write filecontent to a bucket
app = webapp2.WSGIApplication([LogSenderHandler.mapping()], debug=True)
Upvotes: 2
Views: 3464
Reputation: 939
Based on the accepted answer, for a flask app, this is how you would do it:
In requirements.txt
add google-cloud-storage
Flask==2.1.2
appengine-python-standard>=1.0.0
google-cloud-storage
In your main.py
:
from flask import Flask, request
from google.appengine.api import mail
from google.appengine.api import wrap_wsgi_app
from google.cloud import storage
from datetime import date
app = Flask(__name__)
# Enable access to bundled services
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
@app.route("/_ah/mail/<path>", methods=["POST"])
def receive_mail(path):
message = mail.InboundEmailMessage(request.get_data())
print(f"Received greeting for {message.to} at {message.date} from {message.sender}")
for content_type, payload in message.bodies("text/plain"):
print(f"Text/plain body: {payload.decode()}")
for filename, filecontent in message.attachments:
print("Received attachment: ", filename)
storage_client = storage.Client()
bucket = storage_client.bucket("BUCKET NAME")
blob = bucket.blob(f'{date.today():%Y-%d-%m}/{filename}')
with blob.open("wb") as f:
f.write(filecontent.decode())
return "OK", 200
This is what my app.yaml
looks like:
runtime: python39
app_engine_apis: true
service: email-service
inbound_services:
- mail
- mail_bounce
Upvotes: 0
Reputation: 2344
You can specify the bucket while writing in cloud storage
.
from google.appengine.api import app_identity
bucket_name = os.environ.get('BUCKET_NAME',app_identity.get_default_gcs_bucket_name())
You can fetch the particular bucket by the above code. Then you can use this bucket to write in your cloud storage
.
Keep in mind while writing file specify your filename as below:
file_name = '/' + 'BUCKET_NAME' + '/' + 'FILE_NAME'
For more detailed code regarding reading and writing, you can refer
Cloud Read/Write Documentation.
Detailed Read/Write Code: Github Google Cloud
Hope this answers your question!!
Upvotes: 4