Back to main menu


Python tutorial: How ImgPage lets you upload 25 MB photos to S3 and Cloud files with just an email

This post is written by Paul Finn. Paul is a Portsmouth, NH-based Python developer, business owner ( and beer enthusiast ( Follow his blog at, his tweets at @paulfinn and his code at



This post is written by Paul Finn. Paul is a Portsmouth, NH-based Python developer, business owner ( and beer enthusiast ( Follow his blog at, his tweets at @paulfinn and his code at

My favorite web development projects always involve building a tool around a newly discovered API and I’ve been a big fan of Mailgun for a while now. Not only does their API tackle one of the most difficult-things-to-get-right, email parsing, it does it very well. It’s a great example of what a modern, developer-friendly API should be: it’s RESTful, solves a real problem, has solid documentation and it’s fast to get started with.

Building a easy-to-use image upload and hosting app

I turned to Mailgun a few weeks ago when I decided to build a quick image host that could receive images via email and not rely on a traditional client-side uploading process. Many of today’s smartphones don’t have native support for uploads in the browser so it can be a bit tricky to find a way to get photos off your phone and share them with just a link (and bypassing any social networks).

I created ImgPage (“Image Page”) to solve that problem: simply attach a photo (or a few) to an email and send it to Wait a few seconds and you’ll get email response from ImgPage with a unique link to clean, clutter-free page featuring just your image(s) like below.

Below, I’ll show some simplified sample code on how ImgPage uses Mailgun to upload these images to the cloud.

Parsing incoming emails using the Mailgun Routes API

After creating a git repository for ImgPage, the next step was creating the route within Mailgun. A route is what Mailgun calls the logic that tells their system what to do with each incoming email it receives. For ImgPage, I configured Mailgun to parse each incoming email received at and POST the details to my server.

A cool trick about Mailgun: you aren’t limited by just matching on email recipients. You can match on email headers like subject line and also use regular expressions. You can create routes programmatically, as demonstrated above, or you can create routes using the Mailgun dashboard after logging in. Here are the full inbound email parsing API specs.

When it comes to the attachments, Mailgun does the heavy lifting for us and will POST the information we need about any and all attachments up to 25MB (actually the max size is 1 or 2 KB less than 25 MB since space needs to be reserved for email headers). In this simplified example, I’m checking out the request to verify that there is at least one attachment and the attachment has a common photo file extension that we are expecting (if not, return an HTTP 415 error).

@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

Uploading photos to Rackspace Cloud Files & Amazon S3

Now I had a few options for reliable cloud storage, the most popular being Amazon S3. I’m always up for trying a new service and learning a new API and I decided to give Rackspace Cloud Files a shot as well (Rackspace recently acquired Mailgun so over time they will probably build some native integrations). I had plenty of experience using S3 and I was pleasantly surprised at how easy it was to get started with Cloud Files. The basic concepts, things like containers and buckets, are quite similar between the two services.

In the case of ImgPage, it’s important that everything inside the images container is publicly reachable with a unique URL. After uploading, you can request the public URI from Cloud Files.

As you can see, Cloud Files is easy and simple to work with. If you want to stick with Amazon S3, here is how you could handle uploading the attachments using the boto Python library.

(When you’re done with handling the POST, Mailgun expects to see a 200 OK HTTP response. Otherwise this action will be logged as an error in your Mailgun logs.)


Routing incoming emails and parsing attachments is a breeze with Mailgun. I was able to pair Mailgun’s recipient matching and forwarding actions with both Cloud Files and Amazon S3 to create ImgPage. Without having Mailgun, I probably wouldn’t have tackled this project to begin with due to the difficulties of parsing incoming email. Mailgun gets two thumbs up from me for solving a tough problem and creating a stable and well-documented API to go with it.

Related readings

Send email using Python3 and the Mailgun API

If you’re looking to streamline your approach to programmatically sending email, you’re in good hands. Our developers have the experience you need to get started. Read on as we...

Read more

How to send transactional email in a NodeJS app using the Mailgun API

Sending transactional emails is easy regardless of your tools. If you use a NodeJS helper library, this walkthrough will help you get set up in Mailgun. Read more...

Read more

Force for change: It's time to speak out

There are moments when it becomes necessary to speak out and come together as a force ...

Read more

Popular posts

Email inbox.

Build Laravel 10 email authentication with Mailgun and Digital Ocean

When it was first released, Laravel version 5.7 added a new capability to verify user’s emails. If you’ve ever run php artisan make:auth within a Laravel app you’ll know the...

Read more

Mailgun statistics.

Sending email using the Mailgun PHP API

It’s been a while since the Mailgun PHP SDK came around, and we’ve seen lots of changes: new functionalities, new integrations built on top, new API endpoints…yet the core of PHP...

Read more

Statistics on deliverability.

Here’s everything you need to know about DNS blocklists

The word “blocklist” can almost seem like something out of a movie – a little dramatic, silly, and a little unreal. Unfortunately, in the real world, blocklists are definitely something you...

Read more

See what you can accomplish with the world's best email delivery platform. It's easy to get started.Let's get sending
CTA icon