Closed dadouam closed 2 years ago
Thank you for your thorough research, I'll have a closer look soon. This resource naming algorithm keeps giving me headaches, though. It's not as straightforward as you might think.
Since this is one of the trickier parts of the library, it would be of great help if you could provide an example email along with a bare example of your code using it to create a new email. Either here, or if it cannot be published I could treat it discretely only on my own laptop...
Hi, thank you for your reply! Here is a basic .eml sample that allows me to reproduce the issue. sample.eml.zip
Here is the associated test case, assuming sample.eml
is on the test resources classpath. I believe the modifiedEmail
step is not needed here but it's here to show what kind of things I'd do with the originalEmail
.
@Test
void testExtension() throws IOException {
String eml = IOUtils.toString(getClass().getResourceAsStream("/sample.eml"), StandardCharsets.UTF_8);
assertThat(eml)
.contains("Content-Id: <DB294AA3-160F-4825-923A-B16C8B674543@home>")
.contains("filename=filename.png");
Email originalEmail = EmailConverter.emlToEmail(eml);
AttachmentResource originalResource = originalEmail.getEmbeddedImages().get(0);
assertThat(originalResource.getName()).isEqualTo("DB294AA3-160F-4825-923A-B16C8B674543@home");
assertThat(originalResource.getDataSource().getName()).isEqualTo("filename.png");
Email modifiedEmail = EmailBuilder.copying(originalEmail)
.clearRecipients()
.to("other@company.com")
.buildEmail();
AttachmentResource resource = modifiedEmail.getEmbeddedImages().get(0);
assertThat(resource.getName()).isEqualTo("DB294AA3-160F-4825-923A-B16C8B674543@home");
assertThat(resource.getDataSource().getName()).isEqualTo("filename.png");
String modifiedEml = EmailConverter.emailToEML(modifiedEmail);
assertThat(modifiedEml)
.contains("cid:DB294AA3-160F-4825-923A-B16C8B674543@home\"")
.contains("Content-ID: <DB294AA3-160F-4825-923A-B16C8B674543@home.png>")
.contains("filename=\"DB294AA3-160F-4825-923A-B16C8B674543@home.png\"");
}
Btw, I did manage to workaround this issue using EmailPopulatingBuilder withEmbeddedImage(@NotNull String name, @NotNull byte[] data, @NotNull String mimetype);
with byte[] data
created from the original resource - so that the filename
extension doesn't interfere with the name
used as CID.
Hello,
First of all I must thank you for this great work!!
I also have the same issue (along with not recognizing mime type for PNG files) and I worked around it by "replacing" the FileDataSource
.
I digged a little bit to the issue and saw that the FileDataSource
class returns as name
the file name and this name is used as a CID instead of the name given in the withEmbeddedImage
call.
So I replaced the FileDataSource
class with the following class that keeps the name separately and returns this one. So when I create an instance of this class I take case to pass the name that I give to withEmbeddedImage
call and it works so far:
package some.package;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.activation.FileDataSource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class ExtendedFileDataSource extends FileDataSource {
private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
private final File file;
private final String name;
public ExtendedFileDataSource(File file, String name) {
super(file);
this.file = file;
if (name == null) {
this.name = file.getName();
} else {
this.name = name;
}
}
public ExtendedFileDataSource(String name) {
this(new File(name), name);
}
@Override
public String getContentType() {
final String superContentType = super.getContentType();
if (superContentType.equals(DEFAULT_MIME_TYPE)) {
try {
return Files.probeContentType(file.toPath());
} catch (IOException e) {
return DEFAULT_MIME_TYPE;
}
} else {
return superContentType;
}
}
@Override
public String getName() {
return name;
}
}
This is a combination of regression bugs from #219, #249, #310. This was solved in #351 and released in 6.7.0. Give it a try!
Hello, I'm trying to use the library to achieve a rather simple workflow:
Email
entity from the MimeMessage (usingEmailBuilder.copying()
)MimeMessage
in order to send the email to a specific recipient. I want the rest of the e-mail to be left untouched, or at least the HTML, text, attachments... should stay the same as much as possible.The lib is working pretty well for that purpose and provides a much better experience than the JavaMail API. However, I'm facing an issue with some embedded images with e-mails sent from the Apple Mail App (don't know if it happens specifically with this client).
The original email has its Content-ID set like this:
There is no
.png
at the end of Content-ID and thesrc:cid
img property is properly set.Once I receive such an email and try to send it back, no matter if
EmailBuilder
and keep the original list fromcopying()
withEmbeddedImage(embeddedResource.getName(), embeddedResource.getDataSource()
(I was hoping setting the name directly like this would force thecid
to be exactlyembeddedResource.getName()
The end result is a
cid
value ofE977B3EA-BC23-486B-A803-C23C9A849C51@home.png
and it breaks the embedded image because there is a mismatch between thiscid
and thesrc:cid
.I looked at the code and I'm pretty sure this behavior comes from
MimeMessageHelper.determineResourceName()
, perhaps as a side-effect of https://github.com/bbottema/simple-java-mail/issues/307 ?Here is the original resource, from
copying()
: the "name" property is the correct CID, anddataSource.getName()
returns the original file name (which is the one Gmail, Apple Mail... uses as display name for the embedded image "attachment" rather than the cid).Here is the resource before entering into
determineResourceName
:Here is the end result:
.png
was unexpectedly appended toresourceName
, and while I don't think it's as big a problem, thefileName
ignores the value ofdateSource.getName()
and is always equal toresourceName
, which I'm not sure why as having a different cid name/file name could be important in some cases?I'll look for some workaround around the
fileName
because I think it's what triggers this addition of the extension at the end.But I think it would be nice to allow some customization of how
AttachmentResource
is transformed into a body part, or at least provide a way to takename
anddataSource.getName()
"as is" and trust the developer that the values are already correct?Thanks!