Motivation

Three years ago I wrote an article about how to build a contact form in jekyll. My previous work on this code lasted quite a while. I’m happy with it but It’s become a bit much to manage in its current state.

Reasons to refactor

  1. The TO field was an environment variable. This necessitated a 1:1 ratio of domains to containers I was running. NOT maintainable…
  2. The vue component was too dumb. It did not understand how to process generic forms. I needed to link hard coded javascript components for each different form type and have manually coded html forms. This was fragile and lead to typos/extra work. Now I include one file and one properly labeled html element that I define.

Solutions

  1. yaml for mailgun proxy config
  2. Form generator for easy scaffolding of embedable forms.
  3. vue3/axios dependency updates.

The Code

Given a custom domain and a properly configured mailgun account; you can be up and running with this project in minutes. You can check it out over at derek-adair/embedded-contact. The README has more detailed instructions but here is a high level overview;

1) The api.

Currently its pretty “dumb” and takes your mailgun key as an environment variable. The most sophisticated piece of this is how it reads proxy.config.yml;

proxy.config.yml

domains:
    # Your mailgun domain
    mg.<yourdomain>.com: 
        to: <your_valid_email>
        uris:
            - https://<yourdomain>.com

2) The Form Generator

This is VueJS app powered by vite. It will give you a central place to edit / style your contact forms. Leveraging this in your own projects will look something like;

  1. Create a form definition, something like CustomContact.vue.
  2. Initialize in main.js
     import CustomContact from "./CustomContact.vue";
    
     createApp(CustomContact).mount("#custom-contact");
    
  3. Build w/ docker-compose run --rm form-generator yarn run build
  4. Include the javascript from ./dist anywhere you have <div id="custom-contact"></div>

Security

The only real security in place is basic CORS and some validation to ensure I dont accidently cross my clients forms.

Know the risk

This code is vulnerable to CSRF attacks. I do have auth planned, but I am not really that concerned as this would really take someone seeking to maliciously attack a specific target – for those reasons I am not sure when I will get around to this.

What’s Next?

  • Releases on pypi / npm
  • Auth
  • Additional mail providers
  • Mailing lists?
  • Probably a SQLite DB??
  • Official docker images
  • You tell me