apache-jdkim-0.2 HeadlessParsing - how is this supposed to work?
The nature of my integration requires headers and body of the message to come from 2 separate byte streams. The headers get parsed without issue (only thing is I've stepped through the code and not come across canonicalization processing for header or body - is such supposed to be manual?) If I combine the 2 streams for header and body, the body is always empty. eg: ByteArrayInputStream headerAndBodyInputStream = new ByteArrayInputStream( headerStream.toByteArray()); headerAndBodyInputStream.read(\r\n.getBytes()); headerAndBodyInputStream.read(bodyStream.toByteArray()); headerAndBodyInputStream.read(\r\n.getBytes()); The header gets parsed and the body is not, in fact the length of the InputStream is indicates the body never exists in it at all org.apache.james.mime4j.stream.MimeTokenStream.doParse(InputStream, EntityState) I wrote a test case using the contents of the 2 streams hard coded into a string, I even used the wrong line endings to make sure this was not the issue, but EOLConvertingInputStream, correctly converted them, the header and body where both parsed without issue. Then I wrote another test case that parses the 2 streams from there separate files, combines them and prints the result to file before parsing in into the signer, once again the body is dropped. When I compare the combined stream output file to that copied into the hard coded string in a diff app, they are identical. So my conclusion was to use HeadlessParsing, I first parse the headers, then the body using cfg.setHeadlessParsing(multipart/alternative); The javadoc says little, just it must not be null, but I know from stepping through that the content-type is set from this value. The body is still empty. *Any suggestions?* I could write to file then read from file, but for performance reasons I'd rather avoid HDD operations.
apache-jdkim-0.2 2 is DKIM signing for multipart/* supposed to work?
Hi, I'm integrating an application (which uses Sendmail as MTA, and hybrid java/python mailing list manager) with apache jdkim. Other existing oss libraries (which I'd previously based the app on) seem to work fine for plain text, but multipart/alternative results in DKIM result: fail (wrong body hash) I see there are no junit tests for content type multipart DKIM only for it's predecessor DK. In org.apache.james.jdkim.impl.Message on line 79 ((SingleBody) message.getBody()).getInputStream(); However RFC 4871, say that no special processing is required for multipart, so this cast might be valid. I'm debugging and would like to affirm the premiss that pache-jdkim-0.2 for multipart/* content types is indeed considered functional? when run on a multipart produces the exception (I added a try/catch - throwable): java.lang.ClassCastException: org.apache.james.mime4j.message.MultipartImpl cannot be cast to org.apache.james.mime4j.dom.SingleBody at org.apache.james.jdkim.impl.Message.getBodyInputStream(Message.java:80) at org.apache.james.jdkim.DKIMSigner.sign(DKIMSigner.java:85) I spoke to someone on the mailing list he seems to believe it does work, hash a bug been fixed in a post-release build, or has this uncaught exception been slipping through the net? Thanks. - Justin
Re: apache-jdkim-0.2 is DKIM signing for multipart/* supposed to work?
Hi Stefano, I was very happy to discover that you where signing millions of email's initially, now I'm just confused. This is an uncaught exception, so I was thinking maybe it was unnoticed or something. I'm using apache-mime4j-0.7.2, apache-jdkim-0.2 lists this as a dependancy in the maven pom.xml. DKIMSign.pl is written in perl, if this is what you are referring to. I am not a perl developer and can barely read perl. But I'm open to any solution at this stage, I did see there is a test class called org.apache.james.jdkim.PerlDKIMTest, how does perl relate to the apache-jdkim project? I've had a look at the causes for the ClassCastException, and it is not easy to fix, due to inheritance issues. These two classes have completely different abstract parent classes, they can only be referenced by org.apache.james.mime4j.dom.Message because their concrete children implement the interface. Are you suggesting I revert to apache-mime4j-0.7 rather then apache-mime4j-0.7.2? On Wed, Sep 25, 2013 at 9:06 AM, Stefano Bagnara apa...@bago.org wrote: 2013/9/25 Justin Robinson dkim-proj...@fluidnotions.com: [...] java.lang.ClassCastException: org.apache.james.mime4j.message.MultipartImpl cannot be cast to org.apache.james.mime4j.dom.SingleBody at org.apache.james.jdkim.impl.Message.getBodyInputStream(Message.java:80) at org.apache.james.jdkim.DKIMSigner.sign(DKIMSigner.java:85) This may happen if mime4j is not correctly instantiated/invoked. mime4j has to be instructed to do raw parsing (instead of the default multipart parsing). BTW I use DKIMSign mailet to sign millions messages. DKIMSign doesn't use mime4j. Maybe there is a bug in the mime4j parsing part. Are you using mime4j-0.7 ? http://svn.apache.org/viewvc/james/jdkim/tags/apache-jdkim-project-0.2/main/src/main/java/org/apache/james/jdkim/impl/Message.java?view=markup MessageServiceFactory mbf = MessageServiceFactory.newInstance(); 70 mbf.setAttribute(MimeEntityConfig, mec); 71 mbf.setAttribute(FlatMode, true); 72 mbf.setAttribute(ContentDecoding, false); The FlatMode and ContentDecoding options are needed in order for mime4j to work. If they are not used or mime4j doesn't get it then you get a MultipartImpl object and jdkim doesn't work. Stefano - To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org
Re: apache-jdkim-0.2 is DKIM signing for multipart/* supposed to work?
Ok some progress I had extended org.apache.james.mime4j.message.DefaultMessageBuilder, to include fields and was not using org.apache.james.jdkim.impl.Message.newMessageBuilder(). I've changed this to use a decorator pattern, so the original code is now untouched. The classcastexception is no longer being thrown, but the org.apache.james.jdkim.impl.Message.getBodyInputStream() is still returning an empty InputStream, resulting in the wrong body hash. I had looked at Mailets. It seems a useful interface for integration with James server, however it complicates my integration. It is not clear to me how to integrate using Mailets, and I've not been able to find much documentation associated with such an objective. My extension application must integrate with Sendmail MTA, without using a transport socket, where Sendmail milter API is exposed else a standard install of opendkim would be fine. On Wed, Sep 25, 2013 at 9:29 AM, Justin Robinson dkim-proj...@fluidnotions.com wrote: Hi Stefano, I was very happy to discover that you where signing millions of email's initially, now I'm just confused. This is an uncaught exception, so I was thinking maybe it was unnoticed or something. I'm using apache-mime4j-0.7.2, apache-jdkim-0.2 lists this as a dependancy in the maven pom.xml. DKIMSign.pl is written in perl, if this is what you are referring to. I am not a perl developer and can barely read perl. But I'm open to any solution at this stage, I did see there is a test class called org.apache.james.jdkim.PerlDKIMTest, how does perl relate to the apache-jdkim project? I've had a look at the causes for the ClassCastException, and it is not easy to fix, due to inheritance issues. These two classes have completely different abstract parent classes, they can only be referenced by org.apache.james.mime4j.dom.Message because their concrete children implement the interface. Are you suggesting I revert to apache-mime4j-0.7 rather then apache-mime4j-0.7.2? On Wed, Sep 25, 2013 at 9:06 AM, Stefano Bagnara apa...@bago.org wrote: 2013/9/25 Justin Robinson dkim-proj...@fluidnotions.com: [...] java.lang.ClassCastException: org.apache.james.mime4j.message.MultipartImpl cannot be cast to org.apache.james.mime4j.dom.SingleBody at org.apache.james.jdkim.impl.Message.getBodyInputStream(Message.java:80) at org.apache.james.jdkim.DKIMSigner.sign(DKIMSigner.java:85) This may happen if mime4j is not correctly instantiated/invoked. mime4j has to be instructed to do raw parsing (instead of the default multipart parsing). BTW I use DKIMSign mailet to sign millions messages. DKIMSign doesn't use mime4j. Maybe there is a bug in the mime4j parsing part. Are you using mime4j-0.7 ? http://svn.apache.org/viewvc/james/jdkim/tags/apache-jdkim-project-0.2/main/src/main/java/org/apache/james/jdkim/impl/Message.java?view=markup MessageServiceFactory mbf = MessageServiceFactory.newInstance(); 70 mbf.setAttribute(MimeEntityConfig, mec); 71 mbf.setAttribute(FlatMode, true); 72 mbf.setAttribute(ContentDecoding, false); The FlatMode and ContentDecoding options are needed in order for mime4j to work. If they are not used or mime4j doesn't get it then you get a MultipartImpl object and jdkim doesn't work. Stefano - To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org
apache-jdkim-0.2 dependance apache-mime4j-0.7.2 org.apache.james.mime4j.dom.ServiceLoader.load(ClassT) does not load class instances
I've discovered the root to all my problems is that org.apache.james.mime4j.dom.ServiceLoader.load(ClassT) seems unable to load the correct instance type for the given interface eg: spiResURI: META-INF/services/org.apache.james.mime4j.dom.MessageServiceFactory resource: .../META-INF/services/org.apache.james.mime4j.dom.MessageServiceFactory [image: Inline image 1] Am not sure how this is supposed to work, the the supposed instance types seem to be null leading to strange behaviour, I'm using java jdk 6.0. On Wed, Sep 25, 2013 at 9:06 AM, Stefano Bagnara apa...@bago.org wrote: 2013/9/25 Justin Robinson dkim-proj...@fluidnotions.com: [...] java.lang.ClassCastException: org.apache.james.mime4j.message.MultipartImpl cannot be cast to org.apache.james.mime4j.dom.SingleBody at org.apache.james.jdkim.impl.Message.getBodyInputStream(Message.java:80) at org.apache.james.jdkim.DKIMSigner.sign(DKIMSigner.java:85) This may happen if mime4j is not correctly instantiated/invoked. mime4j has to be instructed to do raw parsing (instead of the default multipart parsing). BTW I use DKIMSign mailet to sign millions messages. DKIMSign doesn't use mime4j. Maybe there is a bug in the mime4j parsing part. Are you using mime4j-0.7 ? http://svn.apache.org/viewvc/james/jdkim/tags/apache-jdkim-project-0.2/main/src/main/java/org/apache/james/jdkim/impl/Message.java?view=markup MessageServiceFactory mbf = MessageServiceFactory.newInstance(); 70 mbf.setAttribute(MimeEntityConfig, mec); 71 mbf.setAttribute(FlatMode, true); 72 mbf.setAttribute(ContentDecoding, false); The FlatMode and ContentDecoding options are needed in order for mime4j to work. If they are not used or mime4j doesn't get it then you get a MultipartImpl object and jdkim doesn't work. Stefano - To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org
apache-jdkim-0.2 2 is DKIM signing for multipart/* functional?
Hi, I'm integrating an application (which uses Sendmail as MTA, and hybrid java/python mailing list manager) with apache jdkim. Other existing oss libraries (which I'd previously based the app on) seem to work fine for plain text, but multipart/alternative results in DKIM result: fail (wrong body hash) I see there are no junit tests for content type multipart DKIM only for it's predecessor DK. In org.apache.james.jdkim.impl.Message on line 79 ((SingleBody) message.getBody()).getInputStream(); However RFC 4871, say that no special processing is required for multipart, so this cast might be valid. I'm debugging and would like to affirm the premiss that pache-jdkim-0.2 for multipart/* content types is indeed considered functional? Thanks. - Justin
apache-jdkim-0.2 2 identical body hash calculated for different emails
I have what seems a strange issue, where emails with vastly different email bodies end up with an identical body hash which invariably fail with DKIM result: fail (wrong body hash) [I also get the very same body hash for all variations of the c= signature tag] Taken from app debugging output: HeaderAndBody (before canonicalisation): Return-Path: postmas...@x.com Received: by x.com for 3qcjc...@appmaildev.com; Fri, 20 Sep 2013 06:27:50 GMT Message-ID: 20130920022726-1.1.1g.a.0.lu7a7md...@x.com Date: Fri, 20 Sep 2013 06:27:50 GMT From: Postmaster postmas...@x.com To: 3qcjc...@appmaildev.com Subject: HTMLText-Sep20 X-Mailer: GroupFiO Mailer MIME-Version: 1.0 Content-Type: text/plain; This is a plain text message. HeaderAndBody (before canonicalisation): Return-Path: postmas...@x.com Received: by x.com for 3qcjc...@appmaildev.com; Fri, 20 Sep 2013 06:27:50 GMT Message-ID: 20130920022726-1.1.1g.a.0.lu7a7md...@x.com Date: Fri, 20 Sep 2013 06:27:50 GMT From: Postmaster postmas...@x.com To: 3qcjc...@appmaildev.com Subject: HTMLText-Sep20 X-Mailer: GroupFiO Mailer MIME-Version: 1.0 Content-Type: multipart/alternative; boundary=-==AGNITASOUTERx== ---==AGNITASOUTERx== Content-Type: text/plain; 1234567890 ---==AGNITASOUTERx== Content-Type: text/html; h11234567890/h1 ---==AGNITASOUTERx==-- dkimSignature: [DKIM-Signature: v=1; d=x.com; b=j1VXaZhwNySRkWj33fVcmjS0VfRZVaWV7s+NeK24HjG22Nzr7GcD/l4J9qpm4CTAYJLO8SIOoKeei2wqfgpWhOlzxN/RaMQAtQLgucZmrXBFD5A5luXcsz4s9yiEyxZ5w0b+w/lEH9rpmBIPw5BZQkVacYjY7cd/tJor08QJjLI=; s=rms; c=simple/relaxed; a=rsa-sha1; bh=uoq1oCgLlTqpdDX/iUbLy7J1Wic=; h=from:subject:date:message-id:to:mime-version:content-type;] dkimSignature: [DKIM-Signature: v=1; d=x.com; b=Qinz/pK8/yZ8MsKs84ZCk8/b2W+FlyahRCe90YZsoQvJSoU8rNFJJ1YKk1weUcOv4kVxgYwUbWNcucGhIGeMghjUiGH9mbvypsgLV06nHHjaattcotGOEsDQnSgzg1NzB7G8eqU3yfBuz/mxtBPgMm5Nfk2xSPAAylEDfjVJY1I=; s=rms; c=simple/relaxed; a=rsa-sha1; bh=uoq1oCgLlTqpdDX/iUbLy7J1Wic=; h=from:subject:date:message-id:to:mime-version:content-type;] Implementation Code: InputStream is = null; try { is = new EOLConvertingInputStream(headerAndBodyInputStream); } catch (IOException e2) { e2.printStackTrace(); return false; } String dkimSignature = null; try { dkimSignature = buildSigner(getPrivateKey()).sign(is); } catch (UnrecoverableKeyException e1) { e1.printStackTrace(); } catch (KeyStoreException e1) { e1.printStackTrace(); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (FailException e) { e.printStackTrace(); } catch (MimeException e) { e.printStackTrace(); }finally{ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println(dkimSignature: [ + dkimSignature.trim() + ]); } private DKIMSigner buildSigner(PrivateKey key) throws PermFailException, IOException, MimeException { String signatureRecordTemplate = SignatureRecordTemplateBuilder.getSignatureRecordTemplate(true); DKIMSigner signer = new DKIMSigner(signatureRecordTemplate, key); return signer; }
BUG: apache-jdkim-0.2 2 content-type: multipart/* emails cause java.lang.ClassCastException
The reason (see original email bellow) for this seems to be because the code in org.apache.james.jdkim.DKIMSigner line 85 DKIMCommon.streamCopy(message.getBodyInputStream(), bhj..getOutputStream()); when run on a multipart produces the exception (I added a try/catch - throwable): java.lang.ClassCastException: org.apache.james.mime4j.message.MultipartImpl cannot be cast to org.apache.james.mime4j.dom.SingleBody at org.apache.james.jdkim.impl.Message.getBodyInputStream(Message.java:80) at org.apache.james.jdkim.DKIMSigner.sign(DKIMSigner.java:85) leading to the message.getBodyInputStream() parameter of org.apache.james.jdkim.DKIMCommon.streamCopy(InputStream, OutputStream) being entirely empty, hence the identical body hash for every message. On Tue, Sep 24, 2013 at 6:02 PM, Justin Robinson dkim-proj...@fluidnotions.com wrote: I have what seems a strange issue, where emails with vastly different email bodies end up with an identical body hash which invariably fail with DKIM result: fail (wrong body hash) [I also get the very same body hash for all variations of the c= signature tag] Taken from app debugging output: HeaderAndBody (before canonicalisation): Return-Path: postmas...@x.com Received: by x.com for 3qcjc...@appmaildev.com; Fri, 20 Sep 2013 06:27:50 GMT Message-ID: 20130920022726-1.1.1g.a.0.lu7a7md...@x.com Date: Fri, 20 Sep 2013 06:27:50 GMT From: Postmaster postmas...@x.com To: 3qcjc...@appmaildev.com Subject: HTMLText-Sep20 X-Mailer: GroupFiO Mailer MIME-Version: 1.0 Content-Type: text/plain; This is a plain text message. HeaderAndBody (before canonicalisation): Return-Path: postmas...@x.com Received: by x.com for 3qcjc...@appmaildev.com; Fri, 20 Sep 2013 06:27:50 GMT Message-ID: 20130920022726-1.1.1g.a.0.lu7a7md...@x.com Date: Fri, 20 Sep 2013 06:27:50 GMT From: Postmaster postmas...@x.com To: 3qcjc...@appmaildev.com Subject: HTMLText-Sep20 X-Mailer: GroupFiO Mailer MIME-Version: 1.0 Content-Type: multipart/alternative; boundary=-==AGNITASOUTERx== ---==AGNITASOUTERx== Content-Type: text/plain; 1234567890 ---==AGNITASOUTERx== Content-Type: text/html; h11234567890/h1 ---==AGNITASOUTERx==-- dkimSignature: [DKIM-Signature: v=1; d=x.com; b=j1VXaZhwNySRkWj33fVcmjS0VfRZVaWV7s+NeK24HjG22Nzr7GcD/l4J9qpm4CTAYJLO8SIOoKeei2wqfgpWhOlzxN/RaMQAtQLgucZmrXBFD5A5luXcsz4s9yiEyxZ5w0b+w/lEH9rpmBIPw5BZQkVacYjY7cd/tJor08QJjLI=; s=rms; c=simple/relaxed; a=rsa-sha1; bh=uoq1oCgLlTqpdDX/iUbLy7J1Wic=; h=from:subject:date:message-id:to:mime-version:content-type;] dkimSignature: [DKIM-Signature: v=1; d=x.com; b=Qinz/pK8/yZ8MsKs84ZCk8/b2W+FlyahRCe90YZsoQvJSoU8rNFJJ1YKk1weUcOv4kVxgYwUbWNcucGhIGeMghjUiGH9mbvypsgLV06nHHjaattcotGOEsDQnSgzg1NzB7G8eqU3yfBuz/mxtBPgMm5Nfk2xSPAAylEDfjVJY1I=; s=rms; c=simple/relaxed; a=rsa-sha1; bh=uoq1oCgLlTqpdDX/iUbLy7J1Wic=; h=from:subject:date:message-id:to:mime-version:content-type;] Implementation Code: InputStream is = null; try { is = new EOLConvertingInputStream(headerAndBodyInputStream); } catch (IOException e2) { e2.printStackTrace(); return false; } String dkimSignature = null; try { dkimSignature = buildSigner(getPrivateKey()).sign(is); } catch (UnrecoverableKeyException e1) { e1.printStackTrace(); } catch (KeyStoreException e1) { e1.printStackTrace(); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (FailException e) { e.printStackTrace(); } catch (MimeException e) { e.printStackTrace(); }finally{ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println(dkimSignature: [ + dkimSignature.trim() + ]); } private DKIMSigner buildSigner(PrivateKey key) throws PermFailException, IOException, MimeException { String signatureRecordTemplate = SignatureRecordTemplateBuilder.getSignatureRecordTemplate(true); DKIMSigner signer = new DKIMSigner(signatureRecordTemplate, key); return signer; }