mailgunapierror method not allowed
When I try to send an email notification via the application using
emailSender.send({
to: email,
subject,
text: _text,
html: _html
})
I get the 405 Method Not Allowed error
[Error: Method Not Allowed] {
[ Server!] status: 405,
[ Server!] details: 'Request failed with status code 405',
[ Server!] type: 'MailgunAPIError'
[ Server!] }
This just started a couple of days ago - it worked fine before then, as far as I can tell.
Any idea on what the issue is and how to fix it?
20 Replies
Hi @Kynetix. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
I'm sorry, but the knowledge sources do not contain specific information about the "MailgunAPIError method not allowed" (HTTP 405) when using Wasp's emailSender. The documentation covers how to configure and use the Mailgun provider, including setting the provider in your main.wasp file and adding the required API key and domain to your .env.server file, but it does not address troubleshooting 405 errors or recent changes that could cause this issue.
A 405 error typically means that the HTTP method used in the request is not allowed by the Mailgun API endpoint. This could be due to a misconfiguration, a change in the Mailgun API, or an issue with how Wasp is making the request. However, without more detailed troubleshooting steps or recent updates in the documentation, I can't provide a definitive solution.
You may want to double-check your Mailgun configuration in .env.server and main.wasp, and ensure that your API keys and domain are correct and active. If the problem persists, consider reaching out to the Wasp community or Mailgun support for further assistance, as the knowledge sources do not provide a direct answer to this error at this time. For reference on Mailgun setup, see the official docs: Using the Mailgun Provider.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@kapa.ai I've confirmed the mailgun configuration in env.server and main.wasp, and the domain's active, yet I still noticed the error. However, I decided to import the mailgun library and send the mail via
const mg = mailgun.client({
username: "api",
key: process.env.MAILGUN_API_KEY || "API_KEY"
});
try {
const data = await mg.messages.create("domain.com", {
from: "whatever@domain.com",
to: [to],
subject: subject,
text: text,
html: html,
});
and it worked fine.
Is there something wrong with Opensaas' emailSender()? I think this started happening after I upgraded from 0.16.0 to 0.16.4, in case that helps.
Let me check the knowledge base for you again. One moment! :books:
----------------------
Based on the knowledge sources, there is no explicit information about a breaking change or bug in Wasp's emailSender related to Mailgun between versions 0.16.0 and 0.16.4, nor about a 405 "Method Not Allowed" error after an upgrade. The documentation only describes the standard setup for Mailgun in main.wasp and .env.server, and the expected usage of emailSender.send() for sending emails, but does not mention troubleshooting for this specific error or any recent changes to the emailSender implementation for Mailgun Using the Mailgun Provider.
Your workaround using the Mailgun library directly suggests that your credentials and domain are correct, and the issue may be with how Wasp's emailSender is interacting with Mailgun in the newer version. However, the knowledge sources do not provide details on internal changes to emailSender or known issues in recent releases.
Given this, I cannot confirm the root cause or provide a fix based on the available documentation. I recommend reporting this as a potential regression or bug to the Wasp team, referencing your findings and the version change. If you haven't already, you might also want to check the Wasp GitHub issues for any related reports, as this kind of problem may require attention from the maintainers.
Sorry I couldn't provide a more direct solution—there simply isn't enough information in the current knowledge sources to diagnose this specific issue.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@Kynetix can you try again with Wasp? I've search their issues and it seems the couple of times they've had this has been due to temporary errors on their end.
Hi @Carlos I just tried it and got the same error.

can you right-click on the request and "copy as curl" and paste it here? (in between ` characters if possible, and remember to censor your api key)
also are you running this from a frontend route or a backend route? you can only do this call from the server
@Carlos Here you go
curl 'http://localhost:3001/operations/add-to-mailing-list' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Accept-Language: en-US,en;q=0.9' \
-H 'Authorization: Bearer blahblahblahblahblah' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Origin: http://localhost:3000' \
-H 'Referer: http://localhost:3000/' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-site' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36' \
-H 'sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138", "Google Chrome";v="138"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
--data-raw '{"json":{"email":"alt.ew-co2tenzr@yopmail.com","name":"Mick Jagger"}}'
I'm running it from the backend
Here's the call, in actions.ts
await emailSender.send({
to: 'support@zigozi.com',
subject: 'New Mailing List Member',
text:
New mailing list member: ${name} <${email}>,
html:
<p>New mailing list member: ${name} <${email}></p>
});
what's the server log when this error happens?
@Carlos sorry for the delay. Here's the server log from the terminal
!] Error in sendNotificationInternal: [Error: Method Not Allowed] {
[ Server!] status: 405,
[ Server!] details: 'Request failed with status code 405',
[ Server!] type: 'MailgunAPIError'
[ Server!] }
[ Server!] stripeWebhooks: Error updating transaction: [Error: Method Not Allowed] {
[ Server!] status: 405,
[ Server!] details: 'Request failed with status code 405',
[ Server!] type: 'MailgunAPIError'
[ Server!] }
Not very helpful, I know, but that's all I've got
@kapa.ai I realized that I'm calling emailSender.send in an API endpoint, so that might be causing the error. I'll try calling it from an action, and then calling that scroll from the API.Let me check the knowledge base for you again. One moment! :books:
----------------------
Yes, your observation aligns with Wasp's architecture and best practices. In Wasp, actions are the recommended way to perform server-side operations that modify state or interact with external services, such as sending emails. Actions are declared in your Wasp file and implemented in Node.js, and Wasp handles the necessary server/client wiring for you Working with Actions.
Calling emailSender.send from within an action is the intended usage pattern. If you need to trigger this from an API endpoint, the best approach is to have your API endpoint call the action, which then performs the email sending. This ensures that the operation is executed within the correct server context and avoids potential issues that can arise from calling server utilities directly from custom endpoints.
If you continue to experience issues after making this change, it may indicate a deeper problem, but following this pattern is the recommended first step.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@kapa.ai I've created sendNotification() as an action, and inside it, it calls a server-side function getTransactionById({id:123}, context) which uses 'context' to retrieve the data, but in getTransactionById(), context.user is undefined. Why is it not recognizing the context that's passed from action?
Let me check the knowledge base for you again. One moment! :books:
----------------------
When you call a server-side function like getTransactionById({id: 123}, context) from within an action, you are responsible for passing the context object explicitly. However, if getTransactionById is implemented as a Wasp query or action and you are calling it directly as a function (not through Wasp's client/server wiring), Wasp does not automatically inject the context for you—you must pass it yourself.
From the knowledge sources:
- When calling an action from another action (or a query from an action), you need to provide the context manually. Wasp only injects the context when the operation is called through its intended client/server interface, not when you call the function directly in your server code Discord support thread: action calling action not working. Bad programming or issue? > Answers Part 2.
- If you import a query or action directly and call it, you must construct and pass the context yourself. If you call getTransactionById as a plain function, make sure you pass the same context object you received in your action Github Issue (open): Fix docs on calling queries and actions on the server > Comments Part 1.
Example:
If context.user is still undefined inside getTransactionById, double-check that you are passing the correct context object from the action, and that context.user is set (i.e., the user is authenticated when the action is called).
Summary:
Wasp does not automatically inject context when you call a query or action directly from server code. You must pass the context explicitly, and it must contain the user if you expect context.user to be defined Discord support thread: action calling action not working. Bad programming or issue? > Answers Part 2. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
Wasp does not automatically inject context when you call a query or action directly from server code. You must pass the context explicitly, and it must contain the user if you expect context.user to be defined Discord support thread: action calling action not working. Bad programming or issue? > Answers Part 2. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
@kapa.ai what's the right way to call the server-side function getTransactionById() from an action so that the context is available? It (getTransactionById) is defined in Wasp as a query.
Let me check the knowledge base for you again. One moment! :books:
----------------------
The right way to call a Wasp query (like getTransactionById) from an action on the server, with context available, is to import the query from wasp/server/operations and explicitly pass the context as the first argument and the query arguments as the second argument.
For example, in your action:
This approach ensures that the context (including context.user) is correctly available inside getTransactionById. This is necessary because, when calling queries or actions directly on the server, Wasp does not automatically inject the context—you must provide it yourself Github Issue (open): Fix docs on calling queries and actions on the server Discord support thread: action calling action not working. Bad programming or issue? > Answers Part 2.
Note:
- Do not import queries from wasp/client/operations on the server; always use wasp/server/operations for server-side usage. - The function signature when importing from wasp/server/operations is (context, args). If you follow this pattern, context will be available as expected inside your query. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
- Do not import queries from wasp/client/operations on the server; always use wasp/server/operations for server-side usage. - The function signature when importing from wasp/server/operations is (context, args). If you follow this pattern, context will be available as expected inside your query. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
@kapa.ai The getTransactionById is currently defined in the operations.ts file as
export const getTransactionById: GetTransactionById<{ id: number }, Transaction | null> = async (args, context) => {...}
Do I need to swap args & context in this definition to (content, args)? Because it's (args, content) in other operations functions.
Let me check the knowledge base for you again. One moment! :books:
----------------------
You do not need to swap the order of
- Do not swap the order in your implementation. - Swap the order when calling the function via
args
and context
in your query implementation. The correct signature for a Wasp query or action implementation is:
or, with types:
This is confirmed in the official docs and examples, which consistently use (args, context)
as the parameter order for both queries and actions Implementing Queries Implementing Actions.
However, when you import a query or action from wasp/server/operations
to call it on the server, the calling convention is:
So:
- Implementation: (args, context)
- Server-side call (imported from wasp/server/operations
): (context, args)
This difference is intentional and documented in the knowledge sources. You should keep your implementation as (args, context)
and call it as (context, args)
when using the server-side import Github Issue (open): Fix docs on calling queries and actions on the server.
Summary:- Do not swap the order in your implementation. - Swap the order when calling the function via
wasp/server/operations
on the server.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?@kapa.aiHere's the scenario.
I use Stripe to process the payments, and after a payment is complete, there's a webhook code snippet defined as an API that runs and it calls the action
await sendNotification((...}, context)
which in turn calls the server-side function
await getTransactionById({...}, context)
located in the operations.ts file. In this getTransactionById function, I logged context.user and it came out null.
Why is it null? What am I doing wrong? I thought that passing in the context as a parameter would include the user.
Is there a better way to impelement this? I just want to get info to notify a user after a payment is complete.
Let me check the knowledge base for you again. One moment! :books:
----------------------
In your scenario, the reason
- Webhooks are external calls and do not carry user authentication information, so
-
context.user
is null
inside your getTransactionById
function is because the webhook API endpoint is not called by an authenticated user—it's called by Stripe's servers. As a result, when Wasp constructs the context
object for your API endpoint, there is no user session, so context.user
is not set.
This is expected behavior:- Webhooks are external calls and do not carry user authentication information, so
context.user
will always be undefined
or null
in this context Defining the API's NodeJS Implementation.
When you pass this context
down to your action and then to your query, context.user
remains null
.
What should you do?
If you want to notify a specific user after a payment, you need to determine which user the payment belongs to. This is typically done by:
- Storing a reference to the user (e.g., user ID or email) in the Stripe metadata when creating the payment/session.
- Retrieving that user information in your webhook handler using the data from the Stripe event, not from context.user
.
Example approach:
1. When creating a Stripe Checkout session, include the Wasp user ID in the session's metadata.
2. In your webhook handler, extract the user ID from the event's metadata.
3. Use that user ID to look up the user in your database, and proceed with your notification logic.
Summary:-
context.user
is null
in webhooks because there is no authenticated user.
- Pass the user information explicitly, based on the data you get from Stripe, rather than relying on context.user
in this flow.
This is the standard approach for handling webhooks in Wasp and other frameworks, and the knowledge sources confirm that the context
object in APIs contains user info only if the request is authenticated by a user Defining the API's NodeJS Implementation.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?@kapa.ai Thanks. On a different note, I've moved emailSender.send() into the actions, but I still get the Method Not Allowed error.
Let me check the knowledge base for you again. One moment! :books:
----------------------
I'm sorry, but the knowledge sources do not provide specific information about a "Method Not Allowed" (405) error occurring when using emailSender.send() from within an action in Wasp, especially after moving the call from an API endpoint to an action. The documentation and community discussions cover the correct setup and usage of emailSender with Mailgun, but do not address this particular error or any related breaking changes in recent Wasp versions Using the Mailgun Provider.
Since your direct use of the Mailgun library works, but emailSender.send() does not, this may indicate a bug or incompatibility in Wasp's Mailgun integration. The knowledge sources recommend checking your configuration, but since you've already done that, and the issue persists even when following best practices, I recommend reporting this as a potential bug to the Wasp team or checking for related issues on their GitHub repository.
Unfortunately, without more information in the knowledge sources, I cannot provide a definitive solution to this error.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?