Closed alan-vos closed 3 months ago
Yes, not all types are recognized by default in Jakarta Activation. For example when applying S/MIME, I have to add a bunch of types as well, same for text/calendar when parsing MimeMessage files.
In your case, the x-gzip is missing. Luckily, it's easy to add:
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("application/x-gzip;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
CommandMap.setDefaultCommandMap(mc);
Let me know if this helped you. In the meantime, I'll think about adding it in Simple Java Mail as well.
I should note that x-gzip seems to be an odd occurrence from what I read (ranging from experimental to obsolete). Are you using an older archiving program?
Thank you for the quick reply. I like the implementation (using fluent API) and really wanted to use your library.
I believe attaching compressed archives (zip, gzip, tar, etc ..) is a fairly common use case among the use cases you've already implemented.
I will try out this code now and report back.
Ok, unfortunately -- no joy.
I'm using the gzip that has worked with all Unix platforms for years. It's nothing special -- pretty vanilla.
final MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("application/x-gzip; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
CommandMap.setDefaultCommandMap(mc);
final byte[] bytes = readBytesFromFile("log.tar.gz");
final Email email = EmailBuilder.startingBlank()
.from(...)
.to(...)
.withSubject("Test email gzip attachment")
.withPlainText("See attached gzip")
.withAttachment("log", bytes, "application/x-gzip")
.buildEmail();
with same error:
jakarta.mail.MessagingException: IOException while sending message; nested exception is: jakarta.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; boundary="----=_Part_0_852445367.1718255155787"
Oh, I believe, I've made a big mistake!
Ok, now that I've corrected my goof-up ...
final MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
//mc.addMailcap("application/x-gzip; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("application/x-xz; charset=binary; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
CommandMap.setDefaultCommandMap(mc);
final byte[] bytes = readBytesFromFile("log.tar.xz");
final Email email = EmailBuilder.startingBlank()
.from(...)
.to(...)
.withSubject("Test Email")
.withPlainText("log.tar.xz")
.withAttachment("log.tar.xz", bytes, "application/x-xz; charset=binary")
.buildEmail();
However, the error is still the same ...
jakarta.mail.MessagingException: IOException while sending message; nested exception is: jakarta.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; boundary="----=_Part_0_852445367.1718256585518"
So, just in case ... The following code is currently working using the log.tar.xz file.
final MimeBodyPart attachmentBodyPart = new MimeBodyPart();
attachmentBodyPart.attachFile(new File("logs.tar.xz"));
multipart.addBodyPart(attachmentBodyPart);
message.setContent(multipart);
Transport.send(message);
Can you give this a go?
final MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("application/x-xz;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
It uses a more generic data handler that can handle binary data. If still no luck, please provide a test archive so I can reproduce the issue.
Still same error
final MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("application/x-xz;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
final byte[] bytes = readBytesFromFile("log.tar.xz");
final Email email = EmailBuilder.startingBlank()
.from(...)
.to(...)
.withSubject("Test Email from Gmail")
.withPlainText("Helloworld")
.withAttachment("log", bytes, "application/x-xz")
.buildEmail();
jakarta.mail.MessagingException: IOException while sending message; nested exception is: jakarta.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; boundary="----=_Part_0_1935122449.1718281067735
So can you provide a test case for me? That would help me a lot.
I believe I understand the problem a bit more. I'm using maven with the shade jar plugin. I suspect it might be causing the headaches. In the use-case, I purposefully used an all inclusive maven-assembly-plugin with jar-with-dependencies. Which includes every project dependency.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${entrypoint.class}</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
So, this worked! However, how do I force the maven shaded plugin to include the jakarta activation framework? This currently is puzzling me. Any ideas how to do that?
After some further investigation and I hope it helps someone, the following dependencies are required. In my case, jarkarta along with the contents in META-INF/ that pertain to jakarta mail/activation.
So, the following code worked as long as the assembly plugin was used with jar-with dependencies.
public final class EntryPoint {
public static void main(String[] args) throws IOException {
final String filename = "log";
final String directory = "tmp-test";
final Path outputFilenamePath = Paths.get(filename + ".tar.xz");
final String user = "";
final String passwd = "";
// Generate dummy archive
generateTestArchive(filename, directory);
// Simple Java Mail code
final MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("application/x-xz;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
// Read bytes from archive file tar.xz
final byte[] bytes = Files.readAllBytes(outputFilenamePath);
// The email content
final Email email = EmailBuilder.startingBlank()
// Might be a good idea to get real email addresses, othewise gmail complains.
.from("From Test User", "testuser@gmail.com")
.to("To Test User", "testuser@gmail.com")
.withSubject("Test Email from Gmail")
.withPlainText("Test attachment")
.withAttachment("log", bytes, "application/x-xz")
.buildEmail();
// Send mail configuration
try (final Mailer mailer = MailerBuilder
.withSMTPServer("smtp.gmail.com", 587, user, passwd)
.withTransportStrategy(TransportStrategy.SMTP_TLS)
.buildMailer()) {
mailer.sendMail(email);
} catch (Exception e) {
Logger.error(e);
} finally {
FileUtils.delete(outputFilenamePath.toFile());
}
}
}
Just in case someone uses the maven-shade-plugin -- this worked for me (cleanly). Keep in mind, I'm using the latest JDK8 to date.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven.shade.version}</version>
<executions>
<execution>
<id>second-shade</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<outputFile>${project.build.directory}/${executable.name}.jar</outputFile>
<filters>
<filter>
<artifact>org.eclipse.angus:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>jakarta.mail:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>jakarta.activation:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>org.simplejavamail:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>org.tinylog:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/LICENSE*</exclude>
<exclude>META-INF/license/**</exclude>
<exclude>META-INF/maven/**</exclude>
<exclude>LICENSE*</exclude>
<exclude>RELEASE*</exclude>
<exclude>NOTICE*</exclude>
<exclude>/*.txt</exclude>
<exclude>build.properties</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
<addHeader>true</addHeader>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>${entrypoint.class}</Main-Class>
<Build-Number>${project.version}</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Everything is working as designed as per my issue.
I'm unable to attach a x-gzip attachment. You'd think a zip file, gzip file, essentially a compressed file attachment is a relatively common use-case.
I've looked at TestEmail and have tried my combinations. Here are a couple of examples that do not work.
I've verified that log.gz does in fact exist in the current directory and is in fact a gzip.
The error I get back is:
Reading pass issues, this generally means a missing (or unable) to read a mailcap. However, the mailcap exists. Now, I do not see a mailcap for x-gzip MIME.
Can anyone provide a "simple" working example, please?