vue.js: Send E-Mails client side using Airtable
Tags: vue, email, airtable, javascript
Published: 2021-02-18 14:56:37

Creating cool websites using SPA frameworks like vue.js you probably miss sending e-mails directly from JavaScript.

There are solutions like [EmailJS](https://www.emailjs.com/) wich are focused on this problem. But they are limited in the freemium model.

Using [Airtable](https://airtable.com/) as easy database backend via REST-API (see this nice [article of Carol how to access Airtable by Axios](https://dev.to/codeply/build-a-simple-crud-app-with-airtable-api-vue-vuetify-5565)) I found the Automation Action to send mails on row creation. If a new row is created on a table, a mail could be send.

### Setup Airtable Table

To do this, I have to setup an additional table for these messages. I called it `ContactMessages`:

![Airtable Table: ContactMessage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6xyv9nkcibtz5gwictt.png)

### Create Automation Action

Now you are able to define automation action on this table:

![Airtable Automation Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m019koqckhqmwd5yy58r.png)

Take *When a record is created* for trigger. For the action now we could add *Send an email*. The receiver (To) is important to define. I used a fixed email to hide this from the frontend sources, but it is also possible to pass it by the REST-service and take it form a field of the table.

By the way, do not forget to enable the automation task:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tgmzcao66etqjpg1zcj.png)

### Service in vue

Now we extend the vue project and add a new service `contact.service.js`:

```javascript
import airtableBase from './airtable.service'
const TABLE_NAME = 'ContactMessages'

const contactService = {
  async send (item) {
    const data = {
      fields: item
    }

    // save the record
    const response = await airtableBase.post(`${TABLE_NAME}`, data)
    return {
      id: response.id,
      ...response.fields
    }
  }
}

export default contactService
```

Using Airtable for the complete project, there is a wrapper for base connection to Airtable (token, base) `airtable.service.js`:

```javascript
import axios from 'axios'

const airtableBase = axios.create({
  baseURL: `https://api.airtable.com/v0/${process.env.VUE_APP_AIRTABLE_BASE}/`,
  headers: {
    Authorization: 'Bearer ' + process.env.VUE_APP_AIRTABLE_API_KEY,
    'Content-Type': 'application/json'
  }
})

export default airtableBase

```

For details how using Airtable via API I would like to refer again to [Carols post](https://dev.to/codeply/build-a-simple-crud-app-with-airtable-api-vue-vuetify-5565).

Now we create a vue component to send contact messages:

```javascript
<template>
  <div class="create-form">
    <b-form
      v-if="showForm"
      @submit="onSubmit"
    >
      <b-form-group
        label="Name"
      >
        <b-form-input
          v-model="contact.Name"
          type="text"
          placeholder="Name"
          required
        />
      </b-form-group>
      <b-form-group
        label="E-Mail"
      >
        <b-form-input
          v-model="contact.Email"
          type="email"
          placeholder="E-Mail"
          required
        />
      </b-form-group>
      <b-form-group label="Message">
        <b-form-textarea
          v-model="contact.Notes"
          rows="6"
          max-rows="24"
        />
      </b-form-group>

      <b-button
        type="submit"
        variant="primary"
        class="my-5"
      >
        Send
      </b-button>
    </b-form>
    <b-alert
      v-if="success"
      variant="success"
      class="my-5"
      show
    >
      Message was send sucessfully. Thanks for contacting us.
    </b-alert>
  </div>
</template>

<script>
import contactService from '@/services/contact.service'
export default {
  name: 'CreateForm',
  data () {
    return {
      contact: {},
      showForm: true,
      success: false
    }
  },
  methods: {
    onSubmit (event) {
      event.preventDefault()
      this.showForm = false
      contactService.send(this.contact).then(() => {
        this.success = true
      })
    }
  }
}
</script>
```

I used [BootstrapVue](https://bootstrap-vue.org/) for the form. This could be replaced by any other form code.

### Resume

Using this solution you could create many different templates and receivers for mails send directly by vue apps. Some contact forms are created in minutes for free.

One thing is currently missing in this solution: SPAM protection. 

What do you think about this solution? 
Do you have a suggestion how to protect against bots? Sure there is Googles ReCaptcha, but I would prefer a free open source solution.