mailgun / mailgun-java

Java SDK for integrating with Mailgun
Apache License 2.0
16 stars 11 forks source link

401 when sending mail issue. #29

Closed ValentijnSiW closed 11 months ago

ValentijnSiW commented 11 months ago

Using this mailgun-java library on our project we faced an issue that we weren't allowed to send a message, and were prompted with this error:

2023-10-02T14:28:36.945+02:00  INFO 32684 --- [nio-8123-exec-4] com.mailgun.util.ConsoleLogger           : [MailgunMessagesApi#sendMessage] <--- HTTP/1.1 401 Unauthorized (580ms)
feign.FeignException$Unauthorized: [401 Unauthorized] during [POST] to [https://api.mailgun.net/v3/sandbox8ae918bee67c4ff39a3790fdd3e028f1.mailgun.org/messages] [MailgunMessagesApi#sendMessage(String,Message)]: []
        at feign.FeignException.clientErrorStatus(FeignException.java:224)
        at feign.FeignException.errorStatus(FeignException.java:203)
        at feign.FeignException.errorStatus(FeignException.java:194)
        at feign.FeignException.errorStatus(FeignException.java:171)
        at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92)
        at feign.ResponseHandler.decodeError(ResponseHandler.java:136)
        at feign.ResponseHandler.handleResponse(ResponseHandler.java:70)
        at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114)
        at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70)
        at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:96)
        at jdk.proxy2/jdk.proxy2.$Proxy101.sendMessage(Unknown Source)
        at nl.siw.tools.services.EmailService.sendSimpleMessage(EmailService.java:33)
        at nl.siw.user.controllers.AuthenticationController.forgotPassword(AuthenticationController.java:145)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        at java.base/java.lang.reflect.Method.invoke(Method.java:578)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
        at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:925)
        at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:593)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
        at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1740)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Thread.java:1623)}

The API key and domain name are both correct and coresponding with the one in the mailgun portal. In a nutshell we created a project that gets loaded as dependency which contains all kinds of utility and service classes like this mail service class. The method we used to send the email is this one:

private static final String API_KEY = PropertiesReader.getPropertyValue("mailgun.api.key");
    private static final String DOMAIN_NAME = PropertiesReader.getPropertyValue("mailgun.api.domain");
    private static final String SENDER_EMAIL = PropertiesReader.getPropertyValue("mailgun.from");

    public static MessageResponse sendSimpleMessage(String receiver, String subject, String message) {
        try {
            String apiBase = "https://api.mailgun.net"; // Standard API base URL for the American region

            MailgunMessagesApi mailgunMessagesApi = MailgunClient.config(apiBase, API_KEY)
                    .createApi(MailgunMessagesApi.class);

            Message message1 = Message.builder()
                    .from(SENDER_EMAIL)
                    .to(receiver)
                    .subject(subject)
                    .text(message)
                    .build();

            // Capture detailed logs
            System.out.println("Sending Mailgun request: " + message1.toString());

            MessageResponse response = mailgunMessagesApi.sendMessage(DOMAIN_NAME, message1);

            System.out.println("Mailgun response: " + response.toString());

            return response;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

Any help much appreciated.

vitalii-chornobryvyi-swi commented 11 months ago

Hi @ValentijnSiW, can you please send a message from a postman, just copy-paste this cURL and replace it with your data:

curl --location 'https://api.mailgun.net/v3/DOMAIN_NAME/messages' \
--form 'from="SENDER_EMAIL"' \
--form 'to="receiver"' \
--form 'subject="subject"' \
--form 'text="message"'

then on the 'Authorization' tab specify: Username - api Password - your API_KEY

image

For now, I don't see any code issue, If you get again 401 from the postman then maybe you have the wrong domain or API_KEY

ValentijnSiW commented 11 months ago

Hi @vitalii-chornobryvyi-swi ,

I manage to fix the problem, and indeed there were no issues with the code.

The problem was being not carefull reading and inserting the api key id instead of the api key.

vitalii-chornobryvyi-swi commented 11 months ago

thank you for the quick response, nice to hear that everything works well, so I'm closing an issue