I write a Java 8 code that sends e-mails using SimpleJavaMail ( https://www.simplejavamail.org ) and I am using an HTML content that has embedded images e.g. <img src="cid:ji">
I add the image via currentEmailBuilder.withEmbeddedImage("ji" , new FileDataSource("smiley.png"))
After that, the e-mail is delivered but the image is not inline, instead comes as an attachment.
This is because FileDataSource does not understand the Mime Type of the png file (although it is a proper png file) and reports it by default as application/octet-stream.
Furthermore when the attached image is e.g. JPG , then the mime type is properly detected but it is attached with an unexpected CID. Instead of the one that I use in the template (e.g. ji) it comes with the file extension along (!!) i.e. ji.jpg and thus the CID does not match the template so the image again does not appear properly.
I must be doing something really wrong!
I employed a workaround by creating a class of my own named ExtendedFileDataSource that reports correct MimeType and CID but it is still very strange that I have searched a lot and nobody seems to have this or a similar problem with SimpleJavaMail.
Can you help me out so that I can get rid of the extra class?
Thank you in advance for your time!!
Panagiotis
In case you need to see the code that embeds the images is:
for (Map.Entry<String, String> entry : images.entrySet()) {
// I use a TreeMap that maps the file path to the CID (name)
final String path = entry.getKey();
final String name = entry.getValue();
// this call created the file from a custom service that I created to handle the filesyste
final File file = FilesService.api.fileFromDbNPath(account.getDatabase(), path);
if (!file.exists()) {
throw new ApiException(ApiErrorCodes.MailInexistentImage, "database", account.getDatabase(), "path", path);
}
mailBuilder.withEmbeddedImage(name, new FileDataSource(file));
}
and the resulting e-mail has these two parts (among others):
------=_Part_2_1209984735.1634128409176
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<p><b>Na =CF=84=CE=BF=CF=82 =CE=BF =CE=B1=CF=81=CF=87=CE=B7=CE=B3=CF=8C=CF=
=82:</b> =CE=9B=CE=BF=CF=8D=CE=BB=CE=B7=CF=82 =CE=A0=CE=B9=CE=BB=CE=BF=CF=
=8D=CE=BB=CE=B7=CF=82 =CE=BC=CE=B5 =CF=84o =CE=BC=CE=AD=CE=B9=CE=BB!</p><p>=
=CE=96=CE=97=CE=A4=CE=A9!!</p>
<hr>
<p><img src=3D"cid:efydpepxon"><br><img src=3D"cid:ji"><br><img src=3D"cid:=
testimage"></p>
<hr>
<h1>Fin</h1>
------=_Part_2_1209984735.1634128409176--
------=_Part_1_380493606.1634128409176
Content-Type: application/octet-stream; filename=testimage.png; name=testimage.png
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=testimage.png
Content-ID: <testimage.png>
iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAC/VBMVEUXFBAiHRYrJRxOMQMzLihV
OQIOhRhEOi1eQ...............................7IwbTAwASAIPHaQDihBgQ4fUhBRQdCOx
HPaGyXeFOSEfP0LX3UwUgE+ZfgmslckQ8LdK3ik6zMM/0KX1yGoJ++AlMbAfc4Oe7wEA2lSmadFe
khgCOHdJbIL/UGaT97paY2E/5gb/H72WgFosmUw1AAAAAElFTkSuQmCC
------=_Part_1_380493606.1634128409176
Content-Type: image/jpeg; filename=ji.jpg; name=ji.jpg
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=ji.jpg
Content-ID: <ji.jpg>
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAUEBAQEAwUEBAQGBQUGCA0ICAcHCBALDAkNExAUExIQ
EhIUFx0ZFBYcFhISGiMaHB4fISEhFBkkJyQgJh0gISD/2wBDAQUGBggHCA8ICA8gFRIVICAgICAg
ICAgICAgICAgI...........................NFFABmjNFFABmjNFFABmjNFFABmjNFFABmjN
FFABmjNFFABmjNFFABmjNFFABmjNFFABmjNFFABmjNFFABmjNFFABmjNFFABmjNFFADGVmORIy+w
x/UUUUUAf//Z
------=_Part_1_380493606.1634128409176
Your mail source code show you the id Content-ID: <testimage.png> & Content-ID: <ji.jpg>. That means the id in your html file/code img has to be the same --> <img src"cid:testimage.png"/> & <img src"cid:ji.jpg"/>.
I had exactly the same issue, and never find an answer until I do it myself, so I hope my answer will help someone.
Related
I fetched emails from gmail server using pop3 with enough_email package. Everything works as expected until I updated the flow like fetch emails which is encrypted by PGP encryption. I already achieved the decryption part of email using OpenPGP package which gives String in this form
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="000000000000da67ad05d5c5dfba"
--000000000000da67ad05d5c5dfba
Content-Type: text/plain; charset="UTF-8"
test 3
--000000000000da67ad05d5c5dfba
Content-Type: text/html; charset="UTF-8"
<div dir="ltr">test 3</div>
--000000000000da67ad05d5c5dfba--
now I am trying to create mimeMessage object from the string so I can parse it using decodeTextPlainPart function. Already tried to create mimeMessage object by using MimeMessage.parseFromText function but it's not working as expected, when ever I try to get plain text using decodeTextPlainPart function from my created mimeMessage object it returns the same thing which I provided to MimeMessage.parseFromText function.
Did I miss something or followed the wrong approach?
OpenPGP.decrypt function return string with \n as line separator but MimeMessage.parseFromText works with \r\n, when I replace all \n with \r\n in string then try to create mimeMessage object from the string I get the expected result.
I am using mimedefang filtering tool. In the configuration, I strip out all the attachments and forward it to another address. For particular sender, I can see milter changes the header Content-Type from application/pdf and multipart-mixed. In the received email on outlook, when I open the pdf using text editor (it contains content like ("This is a multi-part message in MIME format..." followed by some random numbers "------------=_1525668389-64274-8--").
Can anyone guess why this might be happening?
Multi-part messages (like those with attachments) have their parts divided by a boundary. This boundary is between 1 and 70 characters and must not appear anywhere in the anywhere within the encapsulated parts of the message (between boundaries).
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=gc0p4Jq0M2Yt08jU534c0p
This is a message with multiple parts in MIME format.
--gc0p4Jq0M2Yt08jU534c0p
Content-Type: text/html; charset=UTF-8
<html><head></head><body>This is the HTML body of the message.</body></html>
--gc0p4Jq0M2Yt08jU534c0p
Content-Type: text/plain
This is the body of the message.
--gc0p4Jq0M2Yt08jU534c0p
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg
Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==
--gc0p4Jq0M2Yt08jU534c0p--
I suspect that somewhere between mimedefang and your milter configuration, the boundaries are getting mangled or included into the attachment can causing them to be corrupted.
There are a number of good examples of adding attachments from file, but I was wondering if I could do it in a similar way to the way AlternateView.CreateAlternateViewFromString works.
I am separately using IMAP to get the body_text and body_headers of an email from one address and then wish to send it from another (via SMTP) with some changes made, but the attachment added as faithfully as possible. I am using MailMessage and SmtpClient ( System.Net & System.Net.Mail )
I have written code to extract MIME parts from BODY[TEXT] by their "Content-Type:" tag and happily add plain text the html views this way. I have the attachment in the MIME too (see example below) so it seems like I should be able to easily add the attachment directly from the string I can extract from the MIME with "Content-Type: application/octet-stream". At present, I am only interested in it working with application/octet-stream.
I have this available in parts of my code as a string containing either:
Content-Type: application/octet-stream; name="test_file.abc"
Content-Disposition: attachment; filename="test_file.abc"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_j7datrbn0
YWJjIGZpbGU=
Or
Content-Disposition: attachment; filename="test_file.abc"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_j7datrbn0
YWJjIGZpbGU=
From example:
* 53 FETCH (BODY[TEXT] {614}
--001a1140ae52fcc4690558c101ec
Content-Type: multipart/alternative; boundary="001a1140ae52fcc4630558c101ea"
--001a1140ae52fcc4630558c101ea
Content-Type: text/plain; charset="UTF-8"
Blah blah
--001a1140ae52fcc4630558c101ea
Content-Type: text/html; charset="UTF-8"
<div dir="ltr">Blah blah</div>
--001a1140ae52fcc4630558c101ea--
--001a1140ae52fcc4690558c101ec
Content-Type: application/octet-stream; name="test_file.abc"
Content-Disposition: attachment; filename="test_file.abc"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_j7datrbn0
YWJjIGZpbGU=
--001a1140ae52fcc4690558c101ec--
)
$ OK Success
All of the other aspects of my code work, but is there an easy way to directly add the attachment from the MIME data I have. I am not using MimeKit or any libraries other than standard VS ones.
Thank you for reading this long question.
Not really what I wanted to do, but I achieved what I needed as follows:
string name = find_item_by_key(attachment_content, "filename"); // looks for key="value" and returns value
string attachment_base64 = attachment_content.Substring(attachment_content.LastIndexOf("\r\n\r\n"));
attachment_base64 = attachment_base64.Trim('\r', '\n');
byte[] attachment_bytes = Convert.FromBase64String(attachment_base64);
Attachment att = new Attachment(new System.IO.MemoryStream(attachment_bytes), name);
mail.Attachments.Add(att);
Lots of pointless conversions going on, since the data is already Base64 and mail.Attachments.Add will no doubt be converting it back again.
How to extract the text content part of an email using the VMIME lib? I use the following code:
vmime::ref <vmime::body> body = Msg -> getBody();
vmime::ref <const vmime::contentHandler> cts = body -> getContents();
cts -> extract(out);
However, the content printed out is the whole body part of MIME structure of the email, including boundary and parameter settings.
--001a11c2e29cfe6d9f04e8b9a834
Content-Type: text/plain; charset=ISO-8859-1
test1
--001a11c2e29cfe6d9f04e8b9a834
Content-Type: text/html; charset=ISO-8859-1
<div dir="ltr"><br clear="all"><div>test1</div>
</div>
--001a11c2e29cfe6d9f04e8b9a834--
What I need is just the text content. However, I cannot find any API to extract just the text content.
What I need:
test1
I have been stuck for 3 days. Could anyone help???
You should use vmime::messageParser object to parse your message. This way, you will get the text contents via the vmime::textPart objects (use getTextPartList() method on messageParser).
Vincent
I trying to upload a file from an iPhone to a server. I'm trying to avoid using any libraries that aren't made by apple, and from what I can tell it looks like I'll need to go pretty low level on constructing my request. Can someone tell me what the "boundary" is in a multipart/form-data request and how to use it properly?
The boundary is an arbitrary piece of text which the client uses to delimit the fields of the form being posted. The client declares the boundary it is using as part of the Content-type header.
From the IETF Form-based File Upload in HTML RFC:
A boundary is selected that does not occur in any of the data. (This
selection is sometimes done probabilisticly.) Each field of the form
is sent, in the order in which it occurs in the form, as a part of
the multipart stream. Each part identifies the INPUT name within the
original HTML form. Each part should be labelled with an appropriate
content-type if the media type is known (e.g., inferred from the file
extension or operating system typing information) or as
application/octet-stream.
...
6. Examples
Suppose the server supplies the following HTML:
<FORM ACTION="http://server.dom/cgi/handle"
ENCTYPE="multipart/form-data"
METHOD=POST>
What is your name? <INPUT TYPE=TEXT NAME=submitter>
What files are you sending? <INPUT TYPE=FILE NAME=pics>
</FORM>
and the user types "Joe Blow" in the name field, and selects a text
file "file1.txt" for the answer to 'What files are you sending?'
The client might send back the following data:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
If the user also indicated an image file "file2.gif" for the answer
to 'What files are you sending?', the client might client might send
back the following data:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"
Content-type: multipart/mixed, boundary=BbC04y
--BbC04y
Content-disposition: attachment; filename="file1.txt"
In the first example, the boundary is the fixed string AaB03x. In the second example, the boundary is first AaB03x and then switches to BbC04y.