Python-Tutorial: Mit ImgPage 25 MB große Fotos per E-Mail in S3 und Cloud Files hochladen
Dieser Beitrag stammt von Paul Finn. Paul ist Python-Entwickler, Unternehmer mit Sitz in Portsmouth, NH (http://route3software.com/) und Bierliebhaber (https://hoppypress.com/beer-art). Folgen Sie seinem Blog unter http://www.pfinn.net/, seinen Tweets unter @paulfinn und seinem Code unter https://github.com/pfinn
Meine liebsten Webentwicklungsprojekte beinhalten immer die Erstellung eines Tools rund um eine neu entdeckte API, und ich bin schon seit einiger Zeit ein großer Fan von Mailgun. Ihre API übernimmt nicht nur eine der schwierigsten Aufgaben überhaupt – das Parsing von E-Mails –, sie erledigt dies auch noch hervorragend. Sie ist ein herausragendes Beispiel dafür, wie eine moderne, entwicklerfreundliche API aussehen sollte: Sie ist RESTful, löst ein echtes Problem, verfügt über eine solide Dokumentation und ermöglicht einen schnellen Einstieg.
Erstellung einer benutzerfreundlichen App für den Bilder-Upload und das Hosting
Ich habe mich vor einigen Wochen an Mailgun gewandt, als ich beschloss, einen schnellen Image-Host zu entwickeln, der Bilder per E-Mail empfängt und nicht auf den traditionellen Upload-Prozess auf Client-Seite angewiesen ist. Viele aktuelle Smartphones bieten keinen nativen Support für Uploads im Browser. Daher ist es manchmal etwas knifflig, Fotos vom Smartphone zu übertragen und sie nur mit einem Link (und unter Umgehung von sozialen Netzwerken) zu teilen.
Ich habe ImgPage („Image Page“) entwickelt, um dieses Problem zu lösen: Hängen Sie einfach ein oder mehrere Fotos an eine E-Mail an und senden Sie diese an inbox@imgpage.com. Warten Sie ein paar Sekunden, und Sie erhalten eine E-Mail-Antwort von ImgPage mit einem individuellen Link zu einer sauberen, übersichtlichen Seite, auf der nur Ihre Bilder zu sehen sind (siehe unten).
Nachfolgend zeige ich Ihnen anhand eines vereinfachten Beispiel-Codes, wie ImgPage Mailgun nutzt, um diese Bilder in die Cloud hochzuladen.
Parsing eingehender E-Mails mit der Mailgun Routes API
Nach der Erstellung eines Git-Repositorys für ImgPage bestand der nächste Schritt in der Einrichtung der Adresse inbox@imgpage.com Route innerhalb von Mailgun. Eine Route ist bei Mailgun die Logik, die dem System mitteilt, was mit jeder eingehenden E-Mail geschehen soll. Für ImgPage habe ich Mailgun so konfiguriert, dass jede eingehende E-Mail an inbox@imgpage.com geparst und die Details per POST an meinen Server gesendet werden.
requests.post("https://api.mailgun.net/v2/routes",
auth=("api", os.environ.get("MAILGUN_KEY", "your-api-key"))),
data=MultiDict([("description", "ImgPage Inbox Processing"),
("expression", "match_recipient('inbox@imgpage.com')"),
("action", "forward('http://imgpage.com/mailgun-endpoint/')"),
("action", "stop()")
]))
Ein smarter Trick bei Mailgun: Sie sind nicht nur auf den Abgleich von E-Mail-Empfängern beschränkt. Zudem lassen sich E-Mail-Kopfzeilen wie die Betreffzeile abgleichen und reguläre Ausdrücke nutzen. Routen lassen sich, wie oben gezeigt, programmgesteuert erstellen. Alternativ können Sie diese nach dem Login über das Mailgun-Dashboard einrichten. Hier finden Sie die vollständigen API-Spezifikationen für das Parsing eingehender E-Mails.
Bei den Anhängen nimmt uns Mailgun die meiste Arbeit ab und sendet uns per POST die benötigten Informationen zu allen Anhängen bis zu 25 MB (eigentlich liegt die Maximalgröße 1 oder 2 KB unter 25 MB, da Platz für E-Mail-Kopfzeilen reserviert werden muss). In diesem vereinfachten Beispiel prüfe ich die Anfrage, um sicherzustellen, dass mindestens ein Anhang vorhanden ist und dieser eine gängige Foto-Dateierweiterung aufweist, die wir erwarten (falls nicht, wird ein HTTP 415-Fehler zurückgegeben).
@app.route(‘/mailgun-endpoint’, methods=[‘POST’]) def mailgun_endpoint(): if(len(request.files) > 0): for attachment in request.files.values(): file_name, file_extension = os.path.splitext(attachment.filename) if file_extension.lower() not in [‘.jpg’, ‘.gif’, ‘.png’, ‘.bmp’]: abort(415) #Unsupported Media Type
@app.route('/mailgun-endpoint', methods=['POST'])
def mailgun_endpoint():
if(len(request.files) > 0):
for attachment in request.files.values():
file_name, file_extension = os.path.splitext(attachment.filename)
if file_extension.lower() not in ['.jpg', '.gif', '.png', '.bmp']:
abort(415) #Unsupported Media Type
Upload von Fotos in Rackspace Cloud Files und Amazon S3
Nun hatte ich einige Optionen für zuverlässigen Cloud-Speicher, wobei Amazon S3 die beliebteste ist. Ich probiere immer gerne neue Dienste aus und lerne neue APIs kennen. Daher beschloss ich, auch Rackspace Cloud Files eine Chance zu geben (Rackspace hat kürzlich Mailgun übernommen, sodass im Laufe der Zeit wahrscheinlich einige native Integrationen entwickelt werden). Ich hatte bereits viel Erfahrung mit S3 und war angenehm überrascht, wie einfach der Einstieg in Cloud Files war. Die grundlegenden Konzepte wie Container und Buckets sind sich bei beiden Diensten sehr ähnlich.
image_attachment.public_uri()
'http://c1234.cdn.cloudfiles.rackspacecloud.com/6a8f43...ab3cb7.jpg'
Im Fall von ImgPage ist es wichtig, dass alles innerhalb des Bilder-Containers über eine eindeutige URL öffentlich erreichbar ist. Nach dem Upload fordern Sie die öffentliche URI von Cloud Files an.
Wie Sie sehen, ist die Arbeit mit Cloud Files einfach und unkompliziert. Wenn Sie bei Amazon S3 bleiben möchten, können Sie den Upload der Anhänge mithilfe der Python-Bibliothek boto wie folgt abwickeln.
from boto.s3.key import Key
from boto.s3.connection import S3Connection
conn = S3Connection(my-access-key, my-secret-key)
bucket = conn.get_bucket('images')
key = Key(bucket)
key = ('%s%s') % (str(uuid.uuid4()), file_extension)
key.set_contents_from_filename(attachment.filename)
(Wenn Sie die POST-Anfrage verarbeitet haben, erwartet Mailgun eine HTTP-Antwort 200 OK. Andernfalls wird diese Aktion in Ihren Mailgun-Protokollen als Fehler verzeichnet.)
Fazit
Das Routing eingehender E-Mails und das Parsing von Anhängen ist mit Mailgun ein Kinderspiel. Ich konnte Mailguns Aktionen für den Empfänger-Abgleich und die Weiterleitung sowohl mit Cloud Files als auch mit Amazon S3 kombinieren, um ImgPage zu erstellen. Ohne Mailgun hätte ich dieses Projekt aufgrund der Schwierigkeiten beim Parsing eingehender E-Mails wahrscheinlich gar nicht erst in Angriff genommen. Mailgun bekommt von mir beide Daumen nach oben für die Lösung eines schwierigen Problems und die Bereitstellung einer stabilen und gut dokumentierten API.