diff --git a/.gitignore b/.gitignore
index 1451eee257de9b65c50c80c1ee1ac435efcea20d..1859bb4b1ad485cf6dedcc39057e156443a1b9b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 *.swp
 venv
 instance/*
+api.db
diff --git a/api/app.py b/api/app.py
index 1da83ce8e08daa5b674459b00b6ab984c57aca03..a5031847df3b5d83e38729e8ce2ae884aa841083 100644
--- a/api/app.py
+++ b/api/app.py
@@ -1,9 +1,9 @@
 import json
-from flask import Flask, redirect, render_template, url_for
-from decorators import admin
-from models import db
-from strava import Strava
+from flask import Flask, redirect, render_template, request, url_for
 from stravalib import unithelper
+from api.decorators import admin
+from api.models import db, ContactFormSubmission
+from api.strava import Strava
 
 app = Flask(__name__, instance_relative_config=True)
 app.config.from_object('config')
@@ -23,23 +23,32 @@ def strava_auth():
     else:
         return Strava.authorize()
 
-@app.route('/api/<api_name>')
-def api(api_name):
-    if api_name == "strava":
-        s = Strava()
-        return json.dumps([{
-            'name': a.name,
-            'type': a.type,
-            'moving_time': a.moving_time.seconds,
-            'date': str(a.start_date),
-            'distance': unithelper.miles(a.distance).num,
-            'athlete_id': a.athlete.id,
-            'url': 'https://strava.com/activity/{}'.format(a.id)
-            } for a in s.activities])
+@app.route('/api/strava')
+def api_strava():
+    s = Strava()
+    r = app.make_response(json.dumps([{
+        'name': a.name,
+        'type': a.type,
+        'moving_time': a.moving_time.seconds,
+        'date': str(a.start_date),
+        'distance': unithelper.miles(a.distance).num,
+        'athlete_id': a.athlete.id,
+        'url': 'https://strava.com/activity/{}'.format(a.id)
+        } for a in s.activities]))
+    r.mimetype = 'application/json'
+    return r
+
+@app.route('/api/contact', methods=['POST'])
+def api_contact():
+    json = request.json
+    db.session.add(ContactFormSubmission(email=json['email'],
+        name=json['name'], text=json['text']))
+    db.session.commit()
+    return 'ok'
 
 @app.context_processor
 def cp_is_admin():
-    from util import is_admin
+    from api.util import is_admin
     return dict(is_admin=is_admin)
 
 @app.context_processor
diff --git a/api/contact.py b/api/contact.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ad00607c0afc8851cdc1f7c35d56495c8826e49
--- /dev/null
+++ b/api/contact.py
@@ -0,0 +1,21 @@
+from flask import request, redirect, current_app
+from stravalib.client import Client
+from requests.exceptions import HTTPError
+from sqlalchemy.orm.exc import NoResultFound
+from api.models import db, StravaApiToken
+
+class Contact():
+    """Website contact form handler"""
+
+    @classmethod
+    def check_auth(cls, token = None):
+        if not token:
+            try:
+                token = db.session.query(StravaApiToken).one().token
+            except NoResultFound:
+                return False
+        strava = Client(token)
+        try:
+            return strava.get_athlete().email
+        except (HTTPError, AttributeError):
+            return False
diff --git a/api/decorators.py b/api/decorators.py
index 51947d007f2ace9407de39bc9d8c60be403bd710..e0ce6aa8851e51402a6a9d8a23cc2dfaae20adbe 100644
--- a/api/decorators.py
+++ b/api/decorators.py
@@ -1,6 +1,6 @@
 from functools import wraps
 from flask import abort
-from util import is_admin
+from api.util import is_admin
 
 def admin(f):
     @wraps(f)
@@ -8,4 +8,4 @@ def admin(f):
         if is_admin():
             return abort(403)
         return f(*args, **kwargs)
-        
+
diff --git a/api/models.py b/api/models.py
index 2bf2c79ba7b815a20f2586d6cb5892d98c5d846e..7922f806176d69f3e59caf4f02cf7d436a1b558d 100644
--- a/api/models.py
+++ b/api/models.py
@@ -1,4 +1,8 @@
+import datetime
+import smtplib
+from email.mime.text import MIMEText
 from flask_sqlalchemy import SQLAlchemy
+from flask import current_app
 
 db = SQLAlchemy()
 
@@ -7,3 +11,25 @@ class StravaApiToken(db.Model):
     __tablename__ = "strava_api_token"
     id = db.Column(db.Integer, primary_key=True)
     token = db.Column(db.String)
+
+class ContactFormSubmission(db.Model):
+    """Submission via the contact form"""
+    __tablename__ = "contact_form_submission"
+    id = db.Column(db.Integer, primary_key=True)
+    date = db.Column(db.DateTime)
+    name = db.Column(db.String)
+    email = db.Column(db.String)
+    text = db.Column(db.Text)
+
+
+    def __init__(self, **kwargs):
+        kwargs['date'] = datetime.datetime.now()
+        super(ContactFormSubmission, self).__init__(**kwargs)
+        footer = "\n\nSubmitted via website contact form."
+        msg = MIMEText("{body}\n\n{footer}".format(body=self.text, footer=footer))
+        msg['Subject'] = 'Website Contact Form Submission'
+        msg['From'] = '{name} <{email}>'.format(name=self.name, email=self.email)
+        msg['To'] = current_app.config.get('ADMIN_EMAIL')
+        s = smtplib.SMTP(current_app.config.get('SMTP_HOST', 'localhost'))
+        s.send_message(msg)
+        s.quit()
diff --git a/api/strava.py b/api/strava.py
index 04b85dfeb2f3684377480788919d9fb8b37a9e15..2fb908d76d69086729245aa2f042ddadca034a3a 100644
--- a/api/strava.py
+++ b/api/strava.py
@@ -2,7 +2,7 @@ from flask import request, redirect, current_app
 from stravalib.client import Client
 from requests.exceptions import HTTPError
 from sqlalchemy.orm.exc import NoResultFound
-from models import db, StravaApiToken
+from api.models import db, StravaApiToken
 
 class Strava(Client):
     """Wrapper for stavalib Client, which is a Strava API client.
diff --git a/api/templates/index.html b/api/templates/index.html
index 276b125ea1d446545b0137a5e32490741826c2e0..58d418feef97db095a5d3844d2f500171fba1c6b 100644
--- a/api/templates/index.html
+++ b/api/templates/index.html
@@ -17,7 +17,7 @@
     </ul>
     </nav>
     {% else %}
-    <header><h1>Hi</h1></header>
-    <p>There is nothing here for you.</p>
+    <header><h1>Oops</h1></header>
+    <p>This is not my website. My website is <a href="https://ant.sr">here</a>.</p>
     {% endif %}
 {% endblock %}
diff --git a/api/util.py b/api/util.py
index bdbbcc47ed43dd0f25ba2b17b595b6e48fcf552e..03fbc8b2cd5b97e7c21a3e45ce94d0a74db48720 100644
--- a/api/util.py
+++ b/api/util.py
@@ -1,8 +1,5 @@
 from flask import request, current_app
 
 def is_admin():
-    try:
-        admin_ip = current_app.config.ADMIN_IP
-    except AttributeError:
-        admin_ip = '127.0.0.1'
+    admin_ip = current_app.config.get('ADMIN_IP', '127.0.0.1')
     return request.remote_addr == admin_ip
diff --git a/config.py b/config.py
index ca7d9db1aeced7e8c99c3ef8cab4f4c2984a15fc..ca590d0f3f90a9b77bee8c1218e4a297f2faa75e 100644
--- a/config.py
+++ b/config.py
@@ -1,6 +1,7 @@
 STRAVA_APP_ID = '12345'
 STRAVA_APP_SECRET = 'your-strava-app-secret'
 ADMIN_IP = '127.0.0.1'
+ADMIN_EMAIL = 'mail@ant.sr'
 SQLALCHEMY_DATABASE_URI = 'sqlite:///api.db'
 SQLALCHEMY_TRACK_MODIFICATIONS = True
 
diff --git a/migrations/versions/f640a1d27e31_.py b/migrations/versions/f640a1d27e31_.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e0698408e8c00e0e9e24876bc45dab39b5b3bef
--- /dev/null
+++ b/migrations/versions/f640a1d27e31_.py
@@ -0,0 +1,33 @@
+"""empty message
+
+Revision ID: f640a1d27e31
+Revises: 28df97a5e20f
+Create Date: 2016-10-13 00:51:38.915838
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'f640a1d27e31'
+down_revision = '28df97a5e20f'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('contact_form_submission',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('date', sa.DateTime(), nullable=True),
+    sa.Column('name', sa.String(), nullable=True),
+    sa.Column('email', sa.String(), nullable=True),
+    sa.Column('text', sa.Text(), nullable=True),
+    sa.PrimaryKeyConstraint('id')
+    )
+    ### end Alembic commands ###
+
+
+def downgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.drop_table('contact_form_submission')
+    ### end Alembic commands ###
diff --git a/requirements.txt b/requirements.txt
index aa10f9bdb7f5f7a96c2ef199a5eff972c2a0ead8..3af8b966316254a14ce9d9102002a0bb0a836dc4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,4 +3,4 @@ Flask-Migrate==1.8.1
 Flask-SQLAlchemy==2.1
 psycopg2==2.6.2
 SQLAlchemy==1.0.14
-stravalib==0.5.0
+stravalib==0.6.3