Skip to content

ConnectionClosedException: Premature end of Content-Length #259

Description

@maxxedev

Issue Summary

If apiKey is empty and an attachment exists, then sendgrid returns a empty response and non-zero content-length header. That causes following exception to be thrown by http-client:

org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body

Steps to Reproduce

	public static void main(String[] args) throws Exception{
		sendEmail();
	}

	private static void sendEmail() throws IOException{
		Email from = new Email("foo@example.com");
		String subject = "Sending with SendGrid is Fun";
		Email to = new Email("bar@example.com");
		Content content = new Content("text/html", "and easy to do anywhere, even with Java");
		Mail mail = new Mail(from, subject, to, content);

		File file = new File("/path/to/an/image/file.png");
		addAttachment(mail, Files.readAllBytes(file.toPath()));

		SendGrid sg = new SendGrid("");
		Request request = new Request();
		request.setMethod(Method.POST);
		request.setEndpoint("mail/send");
		request.setBody(mail.build());
		Response response = sg.api(request);
		System.out.println("getStatusCode:" + response.getStatusCode());
		System.out.println("getBody:" + response.getBody());
		System.out.println("getHeaders:" + response.getHeaders());
	}

	private static void addAttachment(Mail mail, byte[] bytes){
		Attachments sendGridAttachment = new Attachments();
		sendGridAttachment.setType("image/png");
		sendGridAttachment.setFilename("foo.png");
		sendGridAttachment.setDisposition("attachment");
		sendGridAttachment.setContentId("foobar");
		sendGridAttachment.setContent(Base64.getMimeEncoder().encodeToString(bytes));
		mail.addAttachments(sendGridAttachment);
	}

Technical details:

  • sendgrid-java Version: master (latest commit: [commit number])
  • Java Version: 4.1.0

Activity

  1. thinkingserious commented on Oct 12, 2017

    @thinkingserious
    Contributor

    Hi @maxxedev,

    Would it be acceptable to raise an error when someone tries to create a SendGrid object with an invalid API Key?

    With Best Regards,

    Elmer

  2. maxxedev commented on Oct 12, 2017

    @maxxedev
    Author

    Sure, that's acceptable.

    But there is a server-side error that needs to be fixed regardless. It wasn't clear how or where to report such an error.

  3. thinkingserious commented on Oct 12, 2017

    @thinkingserious
    Contributor

    Cool, I'll pass along the server side issue internally. Thanks!

  4. aravindbargurhiriyannaiah commented on May 22, 2018

    @aravindbargurhiriyannaiah

    Hello,

    We are using the SendGrid java api and are getting this exception. The API key and other details are valid. There is no attachment either

    org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 116; received: 0
    	at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:178)
    	at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)
    	at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    	at java.io.InputStreamReader.read(InputStreamReader.java:184)
    	at java.io.Reader.read(Reader.java:140)
    	at org.apache.http.util.EntityUtils.toString(EntityUtils.java:227)
    	at org.apache.http.util.EntityUtils.toString(EntityUtils.java:270)
    	at com.sendgrid.SendGridResponseHandler.handleEntity(SendGridResponseHandler.java:40)
    	at com.sendgrid.SendGridResponseHandler.handleResponse(SendGridResponseHandler.java:35)
    	at com.sendgrid.SendGridResponseHandler.handleResponse(SendGridResponseHandler.java:23)
    	at com.sendgrid.Client.getResponse(Client.java:132)
    	at com.sendgrid.Client.executeApiCall(Client.java:284)
    	at com.sendgrid.Client.post(Client.java:192)
    	at com.sendgrid.Client.api(Client.java:310)
    	at com.sendgrid.SendGrid.makeCall(SendGrid.java:151)
    	at com.sendgrid.SendGrid.api(SendGrid.java:173)
    	at com.axisrooms.gofer.manager.SendGridEmailService.sendEmail(SendGridEmailService.java:48)
    	at com.axisrooms.gofer.controller.EmailController.sendMail(EmailController.java:43)
    	at com.axisrooms.gofer.controller.EmailControllerTest.testSendMailStaging(EmailControllerTest.java:35)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    

    Can you please help us out

  5. 4 remaining items

  6. giordy commented on May 20, 2020

    @giordy

    We are experiencing the same issues in our project. The code is very straight-forward and pretty much identical to the one suggested in the README. We're using the library version 4.5.0.

    The only differences are that we're using Kotlin and that we're reusing the SendGrid object, which however is thread-safe as suggested in issue #213

    The apiKey is 100% not null.

    private fun sendEmail(accountId: Long?, toEmail: String, subject: String, htmlView: View, attachments: Attachments? = null): String? {
            val from = Email("noreply@<redacted>")
            val to = Email(toEmail)
            val content = Content("text/html", renderTemplate(htmlView))
            val mail = Mail(from, subject, to, content)
    
            if (attachments != null) {
                mail.addAttachments(attachments)
            }
    
            val request = Request()
            return try {
                request.method = Method.POST
                request.endpoint = "mail/send"
                request.body = mail.build()
                val response = sendGrid.api(request)
                logger.debug("Internal email $subject sent [${response.statusCode}]")
                logger.info("Successfully sent email \"$subject\"${accountId?.let { " to user with accountId $accountId" } ?: ""}")
                null
            } catch (ex: Throwable) {
                logger.error("Failed to send email \"$subject\"${accountId?.let { " to user with accountId $accountId" }
                        ?: ""}", ex)
                ex.message ?: "No error message available"
            }
        }
    

    Some email went through but then we started getting this same exception. One blind guess I'm having is that the SendGrid servers are communicating a certain Content-Length (76 in our logs) and then transmitting 0, hence sending the HttpClient bananas.

  7. childish-sambino commented on May 20, 2020

    @childish-sambino
    Contributor

    I'm able to repo this issue basically whenever there's an auth issue and the body is sizable.

    @giordy In the short-term, when you encounter this issue, could you try to send the same email but without the attachments? I think you will then get back a sane error response with the proper error message embedded.

  8. childish-sambino commented on May 20, 2020

    @childish-sambino
    Contributor

    Closing this as a non-library issue since it cannot/should not be remedied in client-side code. I've opened an internal ticket for tracking (reference ID: CL-2667).

  9. giordy commented on May 21, 2020

    @giordy

    @giordy In the short-term, when you encounter this issue, could you try to send the same email but without the attachments? I think you will then get back a sane error response with the proper error message embedded.

    @childish-sambino the code I pasted supports sending attachments however at the moment we never send them. The feature that uses attachments is not enabled yet.

    Currently we only send subject+body emails, yet we still see the error.

  10. childish-sambino commented on May 21, 2020

    @childish-sambino
    Contributor

    @giordy How large is the total body payload? I'm seeing the issue when it's about >4KB, but didn't narrow it down further. Can you try stripping the payload down as small as possible? In my testing this was always the result of an auth issue when the payload was large, but when the payload shrunk down the proper error was returned. In fact, the payload could be pretty much empty and the auth error would still surface.

  11. giordy commented on May 26, 2020

    @giordy

    @childish-sambino sorry for the delay. The payload was indeed rather large, around 20-25kB, being the body an HTML document. However I managed to do some tests this morning and so far the problem seems to be gone.
    I tried first to send some emails with a very light payload and always got 202.
    I re-enabled the sending of the large emails and I'm still seeing no errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions