Sending emails with the Graph Java SDK fails with 504, but messages get queued and sent. How to detect it?

Stelios 0 Reputation points
2025-06-25T09:11:33.51+00:00

I am using the Java graph SDK to send emails. Sometimes (about once every two weeks) the call fails with a 504. I sleep for 5 seconds and try again.

After 4 failures the next time I try I get a 429 (indicating that the other four attempts are still active)

I give up and eventually users receive the email 4 times.

It looks to me like I am connecting to Microsoft server A, that schedules work to Microsoft server B, and then A times out, but B performs the action.

  1. Should I treat all 504 errors as successes?
  2. Is there a way to specify an ID so that multiple attempts to send the same email will result to only one email being delivered?
  3. Is there a way to increase the timeout?
  4. Is there a way to submit an email in a non blocking manner, and then poll an endpoint to find out what happened to it?
  5. Would you recommend an alternative way of sending the email, so that I am not affected by this 'characteristic'?

My code for sending the email is:

UserSendMailParameterSet userSendMailParameterSet = UserSendMailParameterSet.newBuilder().withMessage(graphEmail).build();

graphClient.users(fromUserId).sendMail(userSendMailParameterSet).buildRequest().post();
Microsoft Security | Microsoft Graph

1 answer

Sort by: Most helpful
  1. Aashutosh Tiwari - MSFT 435 Reputation points Microsoft External Staff
    2025-06-25T16:26:45.6933333+00:00

    Hi Stelios,

    Thanks for posting question on Forum. Here are possible answers we can provide

    a) Should I treat all 504 errors as successes?

    No, not blindly. A 504 Gateway Timeout means the server didn’t respond in time, but it doesn’t confirm whether the action succeeded or failed. In your case, it seems the backend does eventually send the email, which leads to duplicates on retries. So while the action might succeed, you can’t safely assume that from the 504 alone.

    b) Is there a way to specify an ID to deduplicate retries?

    Unfortunately, Microsoft Graph’s sendMail API does not support idempotency tokens or client-supplied message IDs to prevent duplicate sends. This is a limitation that many developers have flagged.

    c) Can I increase the timeout?

    Yes! You can increase the timeout on the HttpProvider used by the Graph client:

    java

    graphClient.getHttpProvider().setOverallTimeout(Duration.ofSeconds(60));
    

    This might help avoid the 504s if the backend just needs a bit more time

    d) Can I submit the email non-blocking and poll for status?

    Not with sendMail. The Graph API’s sendMail call is fire-and-forget—it doesn’t return a message ID or status URL to poll. If you need delivery tracking, you’d have to:

    Save the message as a draft using POST /me/messages

    Then call POST /me/messages/{id}/send to send it

    Afterward, poll the Sent folder or use webhooks to track delivery

    This adds complexity but gives you more control.

    e) Is there a better way to send email to avoid this issue?

    If reliability and deduplication are critical, consider:

    Microsoft Graph + Draft + Send pattern (as above)

    Azure Communication Services (ACS) for email, which offers better delivery tracking and retry handling

    Third-party transactional email services (like SendGrid or Mailgun) that support idempotency and delivery webhooks

    Workaround ideas:

    Save the internetMessageId of the email and check for it in the Sent folder before retrying.

    • Use a custom header or message property (like a GUID in the subject or body) to detect duplicates on the receiving end.

    If you still have sdk related issues, then you shall raise on https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues

    Hope it helps

    If the answer is helpful, please click Accept Answer and kindly upvote it. If you have any further questions about this answer, please click Comment

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.