- Events
Meet Our Amazing Pathwire Mavericks!
This post is written by Paul Finn. Paul is a Portsmouth, NH-based Python developer, business owner (http://route3software.com/) and beer enthusiast (https://hoppypress.com/beer-art). Follow his blog at http://www.pfinn.net/, his tweets at @paulfinn and his code at https://github.com/pfinn
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.
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 inbox@imgpage.com. 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.
After creating a git repository for ImgPage, the next step was creating the inbox@imgpage.com 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 inbox@imgpage.com and POST the details to my server.
1 requests.post("https://api.mailgun.net/v2/routes", 2 auth=("api", os.environ.get("MAILGUN_KEY", "your-api-key"))), 3 data=MultiDict([("description", "ImgPage Inbox Processing"), 4 ("expression", "match_recipient('inbox@imgpage.com')"), 5 ("action", "forward('http://imgpage.com/mailgun-endpoint/')"), 6 ("action", "stop()")7 ]))
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
1 @app.route('/mailgun-endpoint', methods=['POST'])2 def mailgun_endpoint(): 3 if(len(request.files) > 0): 4 for attachment in request.files.values(): 5 file_name, file_extension = os.path.splitext(attachment.filename) 6 if file_extension.lower() not in ['.jpg', '.gif', '.png', '.bmp']: 7 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.
1image_attachment.public_uri() 2 'http://c1234.cdn.cloudfiles.rackspacecloud.com/6a8f43...ab3cb7.jpg'
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.
1from boto.s3.key import Key 2from boto.s3.connection import S3Connection 34conn = S3Connection(my-access-key, my-secret-key) 5bucket = conn.get_bucket('images') 6key = Key(bucket) 7key = ('%s%s') % (str(uuid.uuid4()), file_extension) 8key.set_contents_from_filename(attachment.filename)
(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.)
Conclusion 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.
Last updated on August 28, 2020
Meet Our Amazing Pathwire Mavericks!
International Women’s Day: How Pathwire’s Female Leaders Choose To Challenge
Mailpets: For The Love Of Animals
The Mailgun Maverick Program Is Here!
Force for Change: It's Time to Speak Out
How To Use Parallel Programming
HTTP Crash Course
How we built a Lucene-inspired parser in Go
Intelligent Email Forwarding With Mailgun
Gubernator: Cloud-native distributed rate limiting for microservices
InboxReady x Salesforce: The Key to a Stronger Email Deliverability
Become an Email Pro With Our Templates API
Google Postmaster Tools: Understanding Sender Reputation
Navigating Your Career as a Woman in Tech
Implementing Dmarc – A Step-by-Step Guide
Email Bounces: What To Do About Them
Announcing InboxReady: The deliverability suite you need to hit the inbox
Black History Month in Tech: 7 Visionaries Who Shaped The Future
How To Create a Successful Triggered Email Program
Designing HTML Email Templates For Transactional Emails
InboxReady x Salesforce: The Key to a Stronger Email Deliverability
Implementing Dmarc – A Step-by-Step Guide
Announcing InboxReady: The deliverability suite you need to hit the inbox
Designing HTML Email Templates For Transactional Emails
Email Security Best Practices: How To Keep Your Email Program Safe
Mailgun’s Active Defense Against Log4j
Email Blasts: The Dos And Many Don’ts Of Mass Email Sending
Email's Best of 2021
5 Ideas For Better Developer-Designer Collaboration
Mailgun Joins Sinch: The Future of Customer Communications Is Here
Always be in the know and grab free email resources!
By sending this form, I agree that Mailgun may contact me and process my data in accordance with its Privacy Policy.