Code Monkey home page Code Monkey logo

flask-mailgun's Introduction

Flask-MailGun

Latest Version Build Status Coverage Status Code Climate Python Versions License Downloads

Flask-MailGun Flask extension to use the MailGun email parsing service for sending and receiving emails.

What it does

Flask-MailGun allows you to configure your connection into the MailGun api so that you can

  • Send emails
  • Set up routes
  • Handle incoming emails
  • flask-mailgun3 >= 0.1.4 should work with flask_security as a drop in replacement for flask_mail

Usage

from flask_mailgun import MailGun

mailgun = MailGun()

# .. later
mailgun.init_app(app)

# ..some other time
@mailgun.on_attachment
def save_attachment(email, attachment):
    data = attachment.read()
    with open(attachment.filename, "w") as f:
        f.write(data)

# .. even later register the upload endpoint
mailgun.route('/uploads')

# send an email like flask_mail
message = Message()
message.subject = "Hello World"
message.sender = "[email protected]"
message.add_recipient("[email protected]")
message.add_recipient("[email protected]")
message.body = "Testing some Mailgun awesomness!"

mailgun.send(message)

Long Requests

A mechanisom has been put in place to simplify handeling long requests. Basically if your callback function blocks the processing of an email for toolong it will cause the post from the mailgun services to timeout. At the moment this is done by setting the mailgun.callback_handeler to mailgun.async_pool but you would have to do this before registering the callbacks (you could reregister on init as well).

# at config
app.config['MAILGUN_BG_PROCESSES'] = flask_mailgun.processing.async_pool(NO_PROCS)
app.config['MAILGUN_CALLBACK_HANDELER'] = app.config['MAILGUN_BG_PROCESSES']
# or later
mailgun.callback_handeler = mailgun.async_pool

# but you may still have to :(
mailgun._on_attachment = [mailgun.async_pool(func) for func in mailgun._on_attachment]

Async will save the attachment to disk and offload your callback to a process pool, handling all the file opperations and file cleanup for you.

This however is probably not an ideal system (threadding dosnt go to well with flask and the process pool implimentation is not simple), and for something more robust we need to move to a celary based system. Setting up celary server and taksks however are beyond the scope of this extension, (we will provide an example though). In addition it may be beniffichial to move to a notify fetch pattern instead of mailgun posting the email to us, however the implimentation details will remain internal to flask_mailgun and the api for process_attachment shouldn't change.

flask-mailgun's People

Contributors

aerickson avatar kvdb avatar pbaiz-amey avatar richard-mathie avatar xuru avatar yunxiamey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

flask-mailgun's Issues

sending with attachments not working

I get an error when attempting to send attachments when running from 7bb76b3 (head of the develop branch).

Sending with attachments does work at dd15a0a.

I'm running Python 3.6.4. Here's the error I'm getting:

(my code is above this point in the stack)
...
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/src/flask-mailgun3/flask_mailgun/core.py", line 51, in send
08:45:44 web.1  |     return self.mailgun_api.send(message)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/src/flask-mailgun3/flask_mailgun/api.py", line 80, in send
08:45:44 web.1  |     files=files)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/api.py", line 112, in post
08:45:44 web.1  |     return request('post', url, data=data, json=json, **kwargs)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/api.py", line 58, in request
08:45:44 web.1  |     return session.request(method=method, url=url, **kwargs)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/sessions.py", line 494, in request
08:45:44 web.1  |     prep = self.prepare_request(req)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/sessions.py", line 437, in prepare_request
08:45:44 web.1  |     hooks=merge_hooks(request.hooks, self.hooks),
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/models.py", line 308, in prepare
08:45:44 web.1  |     self.prepare_body(data, files, json)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/models.py", line 496, in prepare_body
08:45:44 web.1  |     (body, content_type) = self._encode_files(files, data)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/requests/models.py", line 162, in _encode_files
08:45:44 web.1  |     rf.make_multipart(content_type=ft)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/urllib3/fields.py", line 174, in make_multipart
08:45:44 web.1  |     (('name', self._name), ('filename', self._filename))
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/urllib3/fields.py", line 134, in _render_parts
08:45:44 web.1  |     parts.append(self._render_part(name, value))
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/urllib3/fields.py", line 114, in _render_part
08:45:44 web.1  |     return format_header_param(name, value)
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/urllib3/fields.py", line 35, in format_header_param
08:45:44 web.1  |     if not any(ch in value for ch in '"\\\r\n'):
08:45:44 web.1  |   File "/Users/aje/git/inqqqq/venv/lib/python3.6/site-packages/urllib3/fields.py", line 35, in <genexpr>
08:45:44 web.1  |     if not any(ch in value for ch in '"\\\r\n'):
08:45:44 web.1  | TypeError: a bytes-like object is required, not 'str'

python 3.7 issues

File REDACTED/venv/src/flask-mailgun3/flask_mailgun/processing.py", line 30
    self.async = async_pool(app.config.get('MAILGUN_BG_PROCESSES', 4))
             ^
SyntaxError: invalid syntax

Seems related to python 3.7 changes. See ansible/ansible#32816.

issue with pypi deployment

Writing Flask-MailGun3-0.1.6/setup.cfg
creating dist
Creating tar archive
removing 'Flask-MailGun3-0.1.6' (and everything under it)
/home/travis/virtualenv/pypy2.7-5.10/site-packages/cryptography/hazmat/bindings/openssl/binding.py:163: CryptographyDeprecationWarning: OpenSSL version 1.0.1 is no longer supported by the OpenSSL project, please upgrade. A future version of cryptography will drop support for it.
  utils.CryptographyDeprecationWarning
Uploading distributions to https://upload.pypi.org/legacy/
Uploading Flask-MailGun3-0.1.6.tar.gz
100%|##########| 17.9k/17.9k [00:00<00:00, 69.3kB/s]HTTPError: 403 Client Error: Invalid or non-existent authentication information. for url: https://upload.pypi.org/legacy/
NOTE: Try --verbose to see response content.
Flask_MailGun3.egg-info/PKG-INFO already exists, no checkout
Flask_MailGun3.egg-info/SOURCES.txt already exists, no checkout
Flask_MailGun3.egg-info/dependency_links.txt already exists, no checkout
Flask_MailGun3.egg-info/not-zip-safe already exists, no checkout
Flask_MailGun3.egg-info/requires.txt already exists, no checkout
Flask_MailGun3.egg-info/top_level.txt already exists, no checkout
Could not restore untracked files from stash entry
PyPI upload failed.
failed to deploy

FaradayRF/faradayio#35
travis-ci/travis-ci#10056

Python 3 incompattability

It seems like there are issues around saving attachments in python3 need to investigate

======================================================================
ERROR: test_receive_message (tests.test_receve.ReceiveMessageTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/build/amey-sam/Flask-MailGun/tests/test_receve.py", line 32, in test_receive_message
    response = self.appclient.post('/upload', data=request)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/werkzeug/test.py", line 801, in post
    return self.open(*args, **kw)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/flask/testing.py", line 127, in open
    follow_redirects=follow_redirects)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/werkzeug/test.py", line 754, in open
    environ = args[0].get_environ()
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/werkzeug/test.py", line 552, in get_environ
    stream_encode_multipart(values, charset=self.charset)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/werkzeug/test.py", line 98, in stream_encode_multipart
    write_binary(chunk)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/werkzeug/test.py", line 59, in write_binary
    stream.write(string)
TypeError: a bytes-like object is required, not 'str'
======================================================================
ERROR: test_save_attachments (tests.test_save_attachments.SaveAttachmentTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/build/amey-sam/Flask-MailGun/tests/test_save_attachments.py", line 35, in test_save_attachments
    filenames = save_attachments([self.attachment], testdir)
  File "/home/travis/build/amey-sam/Flask-MailGun/flask_mailgun/attachment.py", line 52, in save_attachments
    attachment.save(filename)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/site-packages/werkzeug/datastructures.py", line 2706, in save
    copyfileobj(self.stream, dst, buffer_size)
  File "/home/travis/virtualenv/python3.5.2/lib/python3.5/shutil.py", line 76, in copyfileobj
    fdst.write(buf)
TypeError: a bytes-like object is required, not 'str'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.