Bits of Freedom
Bits of Freedom

Tinkerer and thinker on everything free and open. Exploring possibilities and engaging with new opportunities to instigate change.

Jonas Öberg
Author

Jonas is a dad, husband, tinkerer, thinker and traveler. He's passionate about the future and bringing people together, from all fields of free and open.

Share


My Newsletters


If you're interested in what Commons Machinery, Elog.io, or myself are up to, I'd love for you to be part of my notification lists. It's pretty low volume, a few messages per month, depending on which notifications you sign up for. Thanks for taking an interest!

Read more & subscribe
Bits of Freedom

Introducing: forms

Jonas ÖbergJonas Öberg

In this post, I will introduce you to the FSFE's forms API, a way to send emails and manage sign-ups on web pages used in the FSFE community.

For our Public Money, Public Code campaign, as well as for two of our other initiatives which launched not too long ago (Save Code Share and REUSE), we needed a way to process form submissions from static web sites in a way which allowed for some templating and customisation for each web site.

This is not a new problem by any means, and there are existing solutions like formspree and Google Forms which allows you to submit a form to another website and get a generated email or similar with the results. Some of these are proprietary, others not.

We decided to expand upon the idea of formspree and create a utility which not only turns form submissions into emails, but also allows for storing submissions in json format (to allow us to easily process them afterwards), and allows for customising the mails sent. So we built forms.

The idea of this is easy: on a static website, put a <form> which has as an action to submit the form to forms.fsfe.org. Our forms system then processes the request, acts according to the configuration for that particular website, and then redirects the user back to the static website again.

Some of the use cases where this can be employed is:

Each of these can be made to happen with or without confirmation of an email address. We typically require confirmed e-mail addresses though, and this is the recommended practice. It means the person submitting a form will get an email asking to click a link to confirm their submission. Only when they click that email will any action be taken.

Here's how a form on a webpage could look like:

<form method="POST" action="https://forms.fsfe.org/email">  
  <input type="hidden" name="appid" value="totick2">
  Your name: <input type="text" name="name">
  Your e-mail: <input type="email" name="from" />
  Your message: <input type="text" name="msg" />
</form>  

You will notice that aside from the text and email fields, which the visitor can fill in, there's also a hidden field called appid. This is the identifier used in the forms API to be able to separate different forms, and to know how to behave in each case, and what templates to use.

The configuration, if you want to have a look at it, is in https://git.fsfe.org/FSFE/forms/src/master/src/configuration/applications.json. For a simple contact form, it can look like this:

  "contact": {
    "to": [
      "contact@fsfe.org"
    ],
    "include_vars": true,
    "redirect": "https://fsfe.org/contact/contact-thankyou",
    "template": "contact-form"
  },

This does not have any confirmation of the senders email, and simply says that upon submission, an email should be sent to contact@fsfe.org using the template contact-form, including the extra variables (like name, email, etc) which was included in the form. The submitter should then be redirected to https://fsfe.org/contact/contact-thankyou where there would supposedly be some thank you note.

The templates are a bit magical, and they are defined using a two step process. First you give the identifier of the template in the applications.json. Then in templates.json in the same directory you define the actual template:

  "contact-form": {
    "plain": {
      "content": "{{ msg }}. Best regards, {{ name }}"
    },
    "required_vars": [
      "msg", "name"
    ]
  },

This simply says that we need the content and name variables from the form, and we include them in the content of the email which is sent on submit. You can also specify a html fragment, which would then complement the plain part, and instead of content you can specify filename so the template isn't included in the JSON but loaded from an external filename.

Now, back to our web form. The form we created contained from, name and msg input fields. The latter two were created by us for this particular form, but from is part of a set of form values which control the behaviour of the forms API.

In this case, from is understood by the forms API to be the value of the From: field of the email it is supposed to send. This variable can be set either in the <form> as an input variable, hidden field, or similar, or it can be set in the application config.

If it appears in the application config, this takes precedence and anything submitted in the form with the same name will be ignored. These are the variables which can be included either in the <form> or in the application config:

Each of them do pretty much what it says; it defines the headers of the email sent, or defines the template or content to be used for the email.

The application config in itself can define a number of additional options, which control how the forms API function. The most frequently used ones are given below (you can see the whole list and some examples in the README.

Let's look at a more complete example. We can use the form which at one point was used to sign people up for a mailing list about our REUSE initiative.

<form method="post" action="https://forms.fsfe.org/email">  
  <input type="hidden" name="appid" value="reuse-signup" />
  <input type="email" name="confirm" size="45" id="from" placeholder="Your email address" /><br />
  <input type="checkbox" name="optin" value="yes"> I agree to the <a href="/privacy">privacy</a> policy.
  <input type="submit" value="Send" /><br />
</form>  

You can see here we use the trick of naming the email field confirm to use the confirmation feature. Else, we mostly include a checkbox called optin for the user to confirm they've agreed to the privacy policies.

The application config for this is:

  "reuse-signup": {
    "from": "no-reply@fsfe.org",
    "to": [ "jonas@fsfe.org" ],
    "subject": "New signup to REUSE",
    "confirm": true,
    "include_vars": true,
    "redirect": "https://reuse.software/sign-confirm",
    "redirect-confirmed": "https://reuse.software/sign-success",
    "template": "reuse-signup",
    "store": "/store/reuse/signups.json",
    "confirmation-template": "reuse-signup-confirm",
    "confirmation-subject": "Just one step left! Confirm your email for REUSE!"
  }

What this says is that upon submission, we want to confirm the email address (confirm == TRUE). So when someone submits this form, instead of acting on it right away, the system will redirect the user to a webpage (redirect) and send an email to the address entered into the webform. That email will have the subject Just one step left! Confirm your email for REUSE! (confirmation-subject) and the following content (which is defined in the templates):

Thank you for your interest in our work on making copyrights and licenses computer readable!

There's just one step left: you need to confirm we have the right email for you, so we know where to reach you to stay in touch about our work on this.

Click the link below and we'll be on our way!

  {{ confirmation_url }}


Thank you,

Jonas Öberg  
Executive Director

FSFE e.V. - keeping the power of technology in your hands.  
Your support enables our work, please join us today http://fsfe.org/join  

The confirmation_url will be replaced with the URL the submitter has to click.

When the submitter gets this mail and clicks on the link given, they will be redirected to another website redirect-confirmed, and en email will be sent according to the specifications:

The content of this mail will be

{{ confirm }};{{ optin }}

For instance:

jonas@example.com;yes  

Since it's an email to myself, I didn't bother to make it fancy. But we could easily have written a template such as:

Great news! {{ confirm }} just signed up to hear more from your awesome project!  

And that's it. But if you paid attention, you'll have noticed another defined variable which we didn't explain yet:

    "store": "/store/reuse/signups.json",

This isn't terribly useful unless you have access to the server where the API runs, but essentially, this will make sure that not only does it send an email to me upon confirmation, but it also stores away, in a JSON structure, the contents of that email, and all the forms variables, which we can then use to do something more automated with the information.

If you're interested in the code behind this, it's available in Git, where there are also a bunch of issues for improvement we've thought about. In the long term, it would be nice if:

But those are bigger tasks, and at least for now, the forms API does what it needs to do. If you want to use it too, the best way would be to clone the Git repository, update the application and template config and send a pull request. We can help you review your configuration and merge it into master.

Jonas Öberg
Author

Jonas Öberg

Jonas is a dad, husband, tinkerer, thinker and traveler. He's passionate about the future and bringing people together, from all fields of free and open.