Newsletter with Buttondown and Netlify forms

Netlify site:# brave-wright-72a364
Hi Support,
I have been following a tutorial I found about Netifly and button-down, to send newsletters.
My Site forms are working perfectly and I can see the emails arriving in my forms tab, active forms section.
The failing part is when the functions I have added to have the emails sent to button-down API for the newsletter.
I am getting an error during the transmission, that it cannot find my Dotenv dependency, although it is in my package.json file,
I have added my API key here in the corresponding environmental section as needed, also in my repo, I have added the ‘netlify.toml’ with the required:
[build]
base = “.”
functions = “./functions”
The tutorial I followed was the following is below and it is the one that got me to know of Netlify:

Any tips, On what I am doing wrong?
Please note, I am not a professional developer and I am learning full-stack web development, in a Bootcamp, (halfway through! :))
Thanks in advance!

Hi Johnny and welcome to our community!

Not sure how you package up your functions exactly - could you let me know which of these 3 methods you’re using to deploy them?

Hi fool,
Thank you for your time,
I have gone through the link you sent and I I think I have not used any of these 3.
As mentioned, in my initial message, I was following that tutorial, in which it seems not to work for me, and since I haven’t touched lambda functions, I am not sure how to proceed.

I have created a functions folder and added the following 2 files to it:
index.js and submissions-created.js

The code for submissions-created.js:

require('dotenv').config()
import fetch from 'node-fetch'
const { EMAIL_TOKEN } = process.env
export async function handler(event) {
  const email = JSON.parse(event.body).payload.email
  console.log(`Recieved a submission: ${email}`)
  return fetch('https://api.buttondown.email/v1/subscribers', {
    method: 'POST',
    headers: {
      Authorization: `Token ${EMAIL_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email }),
  })
    .then(response => response.json())
    .then(data => {
      console.log(`Submitted to Buttondown:\n ${data}`)
    })
    .catch(error => ({ statusCode: 422, body: String(error) }))
}

And the code for the index.js:

// function to submit the form without a redirect.
const processForm = form => {
  const data = new FormData(form)
  data.append('form-name', 'newsletter');
  fetch('/', {
    method: 'POST',
    body: data,
  })
  .then(() => {
    form.innerHTML = `<div class="form--success">Almost there! Check your inbox for a confirmation e-mail.</div>`;
  })
  .catch(error => {
    form.innerHTML = `<div class="form--error">Error: ${error}</div>`;
  })
}
// Whenever a user clicks the “submit” button on the form:
const emailForm = document.querySelector('.email-form')
if (emailForm) {
  emailForm.addEventListener('submit', e => {
    e.preventDefault();
    processForm(emailForm);
  })
}

Hey @JohnnyBoySydney,
Could you please try removing base from your netlify.toml, so that it’s:

[build]
functions = “functions/”

Let us know if that fixes things for you. You shouldn’t have to have a separate package.json file inside your functions/ directory, but that will be our next step if the above change doesn’t work.

Hi Jen,
I removed base from the netlify.toml, but I am still getting the following error:

  >  3:23:24 PM: 2020-06-20T05:23:24.158Z	undefined	ERROR	Uncaught Exception 	{"errorType":"Runtime.UserCodeSyntaxError","errorMessage":"SyntaxError: Cannot use import statement outside a module","stack":["Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module","    at _loadUserApp (/var/runtime/UserFunction.js:98:13)","    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)","    at Object.<anonymous> (/var/runtime/index.js:43:30)","    at Module._compile (internal/modules/cjs/loader.js:1138:30)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)","    at Module.load (internal/modules/cjs/loader.js:986:32)","    at Function.Module._load (internal/modules/cjs/loader.js:879:14)","    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)","    at internal/main/run_main_module.js:17:47"]}
> 3:23:24 PM: 2020-06-20T05:23:24.806Z	undefined	ERROR	Uncaught Exception 	{"errorType":"Runtime.UserCodeSyntaxError","errorMessage":"SyntaxError: Cannot use import statement outside a module","stack":["Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module","    at _loadUserApp (/var/runtime/UserFunction.js:98:13)","    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)","    at Object.<anonymous> (/var/runtime/index.js:43:30)","    at Module._compile (internal/modules/cjs/loader.js:1138:30)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)","    at Module.load (internal/modules/cjs/loader.js:986:32)","    at Function.Module._load (internal/modules/cjs/loader.js:879:14)","    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)","    at internal/main/run_main_module.js:17:47"]}
> 3:23:24 PM: Duration: 195.40 ms	Memory Usage: 15 MB	
> 3:23:24 PM: Unknown application error occurredRuntime.UserCodeSyntaxError

I have checked also the functions folder and in the repo and I do not see any other package.json file in any other location.
I also modified inside netlify.toml file, the functions = “functions/” as I had it as functions = “./functions”

Under the forms tab, I can see the email, so the emails are submitted are sent to Netlify, and is working, it’s just the functions are not.

New error == progress! That one about import statement outside a module looks like it’s about this line in your submissions-created.js file: import fetch from 'node-fetch'

Can you try replacing that with const fetch = require('node-fetch') and see if that works?

Hi Jen,

Thank you for your time to assist me,
And I agree that no error is always a good sign, :slight_smile:
Continuing the troubleshooting, I have modified as requested and I have tried again, and as mentioned earlier, the forms work and I can see my email used, but the function returns the same error.
Thank you in advance for your assistance.

Ah, I thought it was a new error, but sounds like I was mistaken! Sorry about that. At any rate, I think my colleague @perry caught an important step here (from our docs):

Your site must have a build command. If your site doesn’t require a build step, you can set the build command to # .

A year later I had the same need, and found a solution.
I published a post explaining how to get it done:

This is such a great blog post, @Roneo.org! Thanks for taking the time to come back and share this with us-- I am sure it will help future members who encounter something similar. :netliconfetti:

1 Like

Hello, a bit late to the party with this one. But I’ve been following your blog post, @Roneo.org, and it is super clear. As a result, I’ve almost got everything set up. But not quite…

So I have a nice form set up, everything builds well. But after submitting something on the sign-up form, when I go to the functions log, I can see that the form submission has been received, and has been passed on to Buttondown…

But from that point onward, something is not happening. And no error messages that I can see in the functions log. This is what the log looks like:

Dec 27, 04:35:21 PM: d168a164 INFO   Recieved a submission: wb**********@gmail.com
Dec 27, 04:35:21 PM: d168a164 INFO   Submitted to Buttondown:
 [object Object]
Dec 27, 04:35:21 PM: d168a164 Duration: 58.46 ms	Memory Usage: 67 MB	Init Duration: 220.08 ms	

However, there’s no sign of any confirmation email sent to the test email account, nor of anything showing up in Buttondown subscriber list as unverified. And I’m not getting any logs in Buttondown for API requests.

Any ideas? I’m way out of my depth here, but it’s kind of interesting. :slight_smile:

1 Like

Hi :wave:t6: @WaywardPhilosopher welcome to the forums! :netliconfetti:

Can you give this support guide a read and see if it helps?

Also please share your site name/slug and the project repository please. :smiling_face_with_three_hearts:

1 Like

Thanks so much, Sam. I’ve had a look through all the documentation, and it is useful. :smiley: But so far, no joy.

The form is here: https://www.lookingforwisdom.com/buttondown/
The form name is signup

The form submits fine, and redirects to an “almost there” page, telling the user to check their email and confirm sign-up. So that’s as it all should be.

Checking in Netlify, the data appears in the forms section with the form name signup as a verified submission. So that data is there in Netlify, which is pleasing and all as it should be.

When I head to the functions tab, it seems that the function is running (https://www.lookingforwisdom.com/.netlify/functions/submission-created), and the data submitted by the form is acknowledged as received:

Dec 29, 04:47:30 PM: 9eb8e1d5 INFO   Recieved a submission: wb*******@gmail.com
Dec 29, 04:51:32 PM: 0c76b806 INFO   Submitted to Buttondown:
Dec 29, 04:51:32 PM: 0c76b806 INFO    [object Object]
Dec 29, 04:51:33 PM: 0c76b806 Duration: 32.94 ms	Memory Usage: 70 MB

But from there onwards, something isn’t happening in terms of the function sending the form to Buttondown. This makes me think that the form itself is trouble-free, but the function isn’t working as expected.

The repository is here:

Any ideas would be very gratefully received! Thanks! :grinning:

Okay! I’ve got it working, and it’s looking beautiful. I referred to this: javascript - Nerlify: lambda response was undefined. check your function code again Response with status 500 in 583 ms - Stack Overflow

Then I tweaked the submission-created.js file as below.

require('dotenv').config()
const fetch = require('node-fetch')
const { BUTTONDOWN_API_KEY } = process.env

exports.handler = async event => {
const payload = JSON.parse(event.body).payload
console.log(`Received a submission: ${payload.email}`)

const response = await fetch(
  'https://api.buttondown.email/v1/subscribers',
  {
    method: 'POST',
    headers: {
      Authorization: `Token ${BUTTONDOWN_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email: payload.email }),
  }
);

let responseText = await response.text();
console.log('response:', responseText);
return {
  statusCode: response.status,
  body: responseText,
};
}

Now everything works as expected. The signup form works, it passes the data to Buttondown, Buttondown gives a nice response report in the functions tab, and everything is grand!

:partying_face:

Hi @WaywardPhilosopher :wave:t6: welcome back! Thank you for coming back and letting us know what worked. This will help other users resolve their similar issues.

1 Like

Hi @WaywardPhilosopher, thanks for your nice words and glad you found a solution.

I wanted to update the post with your findings, but I realized that I’m getting this error (in Netlify function logs) when I’m using the function you kindly shared:

response: {“code”: “forbidden”, “detail”: “Please upgrade your account”

Update: the Buttondown logs show the request as “Ignored” with a 403 status code:

“detail”: “Please upgrade your account to use the API.”

Question: Are you successfully using this function with the free tier from Buttondown, or did you upgrade to a paid plan?

All the best,
Yann

Yes. I’m on the basic plan at $9 a month. According to the pricing page (Pricing · Buttondown) Buttondown free doesn’t give access to the API.

Thanks again for the write-up, which was hugely useful.

1 Like