├── .bowerrc ├── README.md ├── app.py ├── bower.json ├── requirements.txt ├── settings.py ├── templates └── thanks.html └── zappa_settings.json /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "static/" 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mailchimp Signup Utility 2 | Tool that enables you to sign up people to your Mailchimp mailing list through an API or API-Like interface - useful for copying people between lists for example. If the signup is successful, the user will get a thank you notice. If it fails, they'll get an error message. If no email is provided they'll be shown a signup form. 3 | 4 | The app uses Flask for the server, Semantic-UI for the design, and Mailchimp for the mailing list. The experimental version **can be used directly with AWS Lambda** to avoid running a server all the time, using [flask-zappa](https://github.com/Miserlou/flask-zappa). 5 | 6 | ## Setup (traditional) 7 | You'll need to configure the `settings.py` file with your Mailchimp API Key, LIST URL and your POST URL for submitting forms. Then: 8 | ```bash 9 | sudo pip install -r requirements.txt 10 | python app.py 11 | ``` 12 | 13 | ## Setup (AWS Lambda experimental) 14 | You'll need to have `aws` set up on your computer, with `~/.aws/config` and `~/.aws/credentials` in place. You will also need to set up [flask-zappa](https://github.com/Miserlou/flask-zappa) by hand as it is not in pip yet. 15 | 16 | Configure your zappa_settings.json file with your bucket and project name at a minimum. Then: 17 | ```bash 18 | flask-zappa deploy production thf_settings.json 19 | # to update use update instead of deploy 20 | ``` 21 | You'll likely want CORS enabled, for that you have to go into the AWS API Endpoint console, click 'Enable CORS', then 'Deploy', select a stage, 'Deploy'. It's really confusing. -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import json, requests, sys, time, ast 2 | from collections import OrderedDict 3 | from flask import Flask, request, send_from_directory, render_template, jsonify 4 | from flask.ext.cors import CORS 5 | 6 | app = Flask(__name__, static_url_path='/static') 7 | CORS(app) 8 | app.config.from_pyfile('settings.py') 9 | 10 | url = app.config['MAILCHIMP_LIST_URL'] 11 | api_key = app.config['MAILCHIMP_API_KEY'] 12 | 13 | def signup(email, ip): 14 | """Communicates with the Mailchimp API, returns error status""" 15 | error = False 16 | error_detail = "" 17 | if email != None: 18 | print("submitting") 19 | data = {'email_address': str(email), 'status': 'subscribed', 'ip_opt': ip} 20 | headers = {'Content-Type': 'application/json'} 21 | try: 22 | r = requests.post(url, data=json.dumps(data), headers=headers, auth=("apikey", api_key)) 23 | print r.json() 24 | if r.status_code == 200: 25 | error = False 26 | elif r.status_code == 400: 27 | error = True 28 | error_detail = r.json()['detail'] 29 | print(r.text) 30 | else: 31 | error = True 32 | error_detail = "Something broke... try again later" 33 | except: 34 | error = True 35 | error_detail = "Something broke... try again later" 36 | return error, error_detail 37 | 38 | @app.route('/', methods=['POST', 'OPTIONS']) 39 | def signup_api(): 40 | """API endpoint with AWS Lambda-specific stuff""" 41 | if request.method == 'OPTIONS': 42 | # for CORS pre-flight check 43 | print "api options" 44 | return jsonify(request="options") 45 | else: 46 | email = ast.literal_eval(request.data)['email'] 47 | ip = request.headers.get('X-Forwarded-For').split(',')[0] 48 | print "api post", email, ip 49 | error, error_detail = signup(email, ip) 50 | return jsonify(email=email, error=error, error_detail=error_detail) 51 | 52 | 53 | 54 | @app.route('/signup') 55 | def signup_generic(): 56 | """Generic signup method which works on any server""" 57 | email = "" 58 | email = request.args.get('email') 59 | ip = request.remote_addr 60 | error = "" 61 | error_detail = "" 62 | if email != None: 63 | error, error_detail = signup(email, ip) 64 | return render_template('thanks.html', email=email, error=error, error_detail=error_detail, mailchimp_url=app.config['MAILCHIMP_POST_URL']) 65 | 66 | @app.route('/static') 67 | def serve_static(path): 68 | return send_from_directory('/static', path) 69 | 70 | if __name__ == '__main__': 71 | app.run(host="0.0.0.0", port=8005) -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mailchimp-flask", 3 | "authors": [ 4 | "sasha42 " 5 | ], 6 | "dependencies": { 7 | "semantic": "^2.1.8" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | base58==0.2.2 2 | boto3==1.2.5 3 | botocore==1.3.30 4 | click==6.2 5 | docutils==0.12 6 | Flask==0.10.1 7 | Flask-Cors==2.1.2 8 | flask-zappa==0.0.1 9 | futures==3.0.4 10 | itsdangerous==0.24 11 | Jinja2==2.8 12 | jmespath==0.9.0 13 | MarkupSafe==0.23 14 | python-dateutil==2.4.2 15 | requests==2.9.1 16 | six==1.10.0 17 | tqdm==3.7.1 18 | Werkzeug==0.11.4 19 | wheel==0.24.0 20 | wsgi-request-logger==0.4.4 21 | zappa==0.11.2 22 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | APP_MODULE="app" 2 | APP_OBJECT="app" 3 | DEBUG = True 4 | MAILCHIMP_LIST_URL = "https://.api.mailchimp.com/3.0/lists/{listid}/members" 5 | MAILCHIMP_API_KEY = "Your API Key" 6 | MAILCHIMP_POST_URL = "Get this by creating a embeded form for your list and copying the action URL" -------------------------------------------------------------------------------- /templates/thanks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Mailing list signup 8 | 9 | 24 | 25 | 26 |

Mailing list signup

27 |
28 |
29 | {% if email is not none %} 30 | {% if error %} 31 |
32 |

Error

33 |

{{ error_detail }}

34 |
35 | {% else %} 36 |
Thanks for signing up, your email {{ email }} has been added to our list.
37 | {% endif %} 38 | {% else %} 39 |
40 |
41 | 42 | 43 |
44 |
45 |
46 | 47 | 48 |
49 |
50 | 51 | 52 |
53 |
54 | 55 |
56 | {% endif %} 57 |
58 |
59 | -------------------------------------------------------------------------------- /zappa_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "production": { 3 | "s3_bucket": "your-bucket", 4 | "settings_file": "settings.py", 5 | "project_name": "MailchimpUtility" 6 | } 7 | } 8 | --------------------------------------------------------------------------------