Postmark email function works in netlify dev but not on live site

Site name: https://gracious-shockley-06e0b6.netlify.app/

I have a function ( submission-created.js ) which should email me the contents of a form submission from the site. When testing locally on “netlify dev” it works great. When I deploy it to the live site it doesn’t work. It has been found by the build bots, it is run on submission with console.log showing the field submissions. I feel like I must be missing something very simple.

Here is the function : Netlify function to email form submission using Postmark · GitHub

Here is a function log when submitting to the site in production:
3:14:25 PM: 2020-10-29T22:14:25.364Z 04e073b3-55a0-4772-855f-a4471328ff28 INFO submission created error testing
3:14:25 PM: 2020-10-29T22:14:25.365Z 04e073b3-55a0-4772-855f-a4471328ff28 INFO Name: Logan Williams
3:14:25 PM: 2020-10-29T22:14:25.365Z 04e073b3-55a0-4772-855f-a4471328ff28 INFO Email: firefly@loganwilliams.tech
3:14:25 PM: 2020-10-29T22:14:25.365Z 04e073b3-55a0-4772-855f-a4471328ff28 INFO Message: Hello world!
3:14:25 PM: 2020-10-29T22:14:25.365Z 04e073b3-55a0-4772-855f-a4471328ff28 INFO Timeline: Not important thank goodness.
3:14:25 PM: 2020-10-29T22:14:25.365Z 04e073b3-55a0-4772-855f-a4471328ff28 INFO Tell me about your budget: 3
3:14:25 PM: Duration: 40.67 ms Memory Usage: 74 MB Init Duration: 195.77 ms

1 Like

Maybe you can try adding some console.logs inside your try/catch block. This way you can tell if the send email part of your function worked on not. Let me know if that helps.

@firefly I have this exact same issue Logan - were you able to resolve it?

Hi, @barrymcgee. How are you emailing? If you are using SMTP on port 25, this is blocked by default on AWS Lambda (which is what Functions are using - search for “What restrictions apply” at that link for more information).

Hi Luke,

As with the example above, we’re not sending the email directly via the function, we’re just reaching out to the Postmark API… they then do the sending?

Barry

Hi, @barrymcgee. I didn’t notice that the emailing was being done via API. Yes, those would be HTTP requests on port 443 (as I’m assuming SSL is used) so the port 25 block would not impact these API calls at all.

Are you sure the required environment variables are being setup in the deployed Function the same way they are locally (meaning, specifically, any auth tokens required)?

Hi Luke, yes I’m sure - both API keys on dev and prod are identical.

Hi, @barrymcgee. I don’t have any “special” ability to debug the deployed Functions. They are deployed to AWS Lambda so the only way I have to debug them is to rely on the logging of the function itself.

If the function doesn’t log why the failure occurs, I’m just as in the dark as to why as you are.

Using a reduced test case, I’m pretty sure my issue is a symptom of this same issue:
https://answers.netlify.com/t/send-response-before-stopping-function/5016/12

The function which I’m trying to run this code is async.

If I make a reduced test case, sending a simple email using Postmark in a function that is not async, it works.

Question is - why do async functions work as expected using netlify dev but not in production?

1 Like

Hey @barrymcgee :wave:t2:

I haven’t seen any code so just speaking in high-level terms here, but Netlify Dev approximates the AWS Lambda runtime; it’s not necessarily a carbon clone. There will be differences. Some of what you’re seeing may be attributed to Lambda spinning up little instances of each Function - when they return the instance is killed. Immediately. Locally in Netlify Dev, all of the functions run in a single instance that persists as long as you’re running netlify dev - it would make sense that if you another function on the stack and return, that function might still get processed.

Fundamentally, Lambda is not designed to allow you to send back a response then keep processing code… for a number of reasons. Note their docs and in particular:

  • Background processes or callbacks that were initiated by your Lambda function and did not complete when the function ended resume if Lambda reuses the execution environment. Make sure that any background processes or callbacks in your code are complete before the code exits.

This just isn’t the design of Lambda.

HOWEVER, if you do want to accomplish something along these lines, I’d suggest you check out Netlify’s new Background Functions (Announcement and Docs). These would allow you to accomplish what you’re trying to do (generally) in a 2-step process.

  1. Have a non-background Function that does your normal logic, kicks off a background job, then responds to the caller (fast)
  2. The background job receives the call from the first function and does the background (slow) work including your various POST requests.

Be aware though, you need to be strategic around what you’re trying to do since the background jobs don’t give you feedback about their status and whether or not they succeeded (which would be the same if Lambda did continue after return anyway) – so you need to take an architectural strategy to where your background job makes changes somewhere to indicate that your task is complete etc. (Or just make your background jobs immutable and repeatable if needed but that doesn’t always work for something like sending emails)

I hope that gives you some brain fodder or ideas / helps!


Jon


EDIT: The conversation continued a bit over on this thread (same premise) so I thought I’d come back and tag it here for those following in the future:

https://answers.netlify.com/t/send-response-before-stopping-function/5016/13

2 Likes

Thank you for the detailed reply @jonsully - this steer ultimately led to my being able to resolve the issue.

For posterity, my issue was that my function was using async/await to fire off multiple chained requests to various services…

  • Submit order -> Send email confirmation -> Subscribe to newsletter

As outlined above, when the first request returned, the function terminated.

The solution I reached is to split this into three separate functions and chain them on the client.