I am using below code to send mail to multiple users across different domains.
String emailBody = "<html>Some html text goes here</html>"
String from = "from#domain1.com"
String bcc = "bcc#domain2.com"
String subject = "Some subject..."
List attachments = "Some image attachments ..."
MimeMessage message = new MimeMessage(session);
message.setHeader("Content-Type", "text/html; charset=UTF-16")
message.setHeader("Accept-Language", "en-US")
message.setHeader("Content-Language", "en-US")
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.BCC,InternetAddress.parse(bcc));
message.setSubject(subject);
// creates message part
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(emailBody, "text/html; charset=UTF-16");
// creates multi-part
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
addAttachmentsToMultiPart(multipart,attachments)
message.setContent(multipart);
Transport.send(message);
The email body is entirely is in English. But users of few domains are recieving it in Chinese characters. When I viewed the html source of the body, I found it is partially garbled. Some orginal html text is intact and some junk characters in between text with no particular order. This mail travels this path "Tomcat application -> company mail server -> outlook.office365.com server -> target mail server -> End user outlook client".
After some research, I found this issue could be due to Character encoding. For testing it, I tried sending this mail to gamil.com. The mail body appears correctly in gmail, but I notice following headers are found in headers part and entire body part is base64 encoded.
Content-Type: text/html; charset="UTF-16"
Content-Transfer-Encoding: base64
I am not sure how "Content-Transfer-Encoding" is being set on headers and where is mail body getting encoded. But I don't see similar headers in End User mail properties. I tried explicitly setting "Content-Transfer-Encoding" to "base64", "quoted-printable" ( and other types), but it is always ignored and gmail always recieves it as base64. And this setting has no impact end user mails. They always recieves same garbage.
Can anyone help me understand what could be issue and how to resolve it
We have code that is very similar to what you have written, the only differences which you could try:
We don't set any headers in the message
We use a slightly different body content type - text/html; charset=utf-8
As an aside, we use com.google.common.net.MediaType to pass the media type into the e-mail sending class, so then you can use MediaType.toString() to get the content type.
I resolved after lot of research and experiment. There were basically two issues
Character-set should not be set at MimeMessage level but at individual MimeBodyPart level.
Changed the UTF-16 to UTF-8. Some email client/server cannot handle UTF-16 properly or they are not configured to handle UTF-16.
Related
I need to develop an application to send events to Gmail / Outlook calendars. Java mail 1.5.5 is used. I did some tests with version 1.6.2, without more success
The chosen solution is to generate ics files, and send them by email to the target calendars adresses.
On Gmail, the email is well recognized as an event email (the email contains the description of the event, the possibility to change the answer, and the event is automatically added to the calendar)
On Outlook, the attachment is not recognized as an event (the email just contains the ics file as an attachment, no description or response request, and the event is not automatically added to the calendar) . You must then click on the attachment, then on "Add to calendar" so that the event is created in the calendar
I found many similar topics on the net, but nothing that helped me solve the problem
The problem could come from the ics file or the headers of the mail. The ics file looks good to me: If on gmail, I create a new message, I add my ics as an attachment, and I send it to my Outlook address, the email is well recognized as an event
Here is the content of the ics file
BEGIN:VCALENDAR
PRODID:<MYPRODID>
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP:20220629T121224Z
SUMMARY:Test Event
DTSTART:20220630T110000Z
DTEND:20220630T130000Z
UID:<MYUID>
SEQUENCE:1656460800
DESCRIPTION:Event body
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=FALSE;CN=<MYCN>:mailto:<MYEMAIL>
ORGANIZER;CN=<MYORGNAME>:mailto:<MYORGEMAIL>
END:VEVENT
END:VCALENDAR
I have some doubt on the headers / mail structure. I find a lot of different things on the internet, but everything I try leads to the same result (the need to open my email in Outlook, to manually import the attachment)
Here is my java code during the last tests:
Properties prop = new Properties();
prop.put("mail.mime.charset", "UTF-8");
prop.put("mail.smtp.host", "<MYHOST>");
prop.put("mail.smtp.port", "<MYPORT>");
prop.put("mail.smtp.auth", Boolean.TRUE.toString());
prop.put("mail.smtp.user", "<MYUSER>");
prop.put("password", "<MYPASS>");
String from = "<MYORGEMAIL>";
String to = "<MYEMAIL>";
Session session = Session.getInstance(prop, new SMTPAuthenticator(prop));
// Define message
MimeMessage message = new MimeMessage(session);
message.addHeader("method", "REQUEST");
message.addHeader("charset", "UTF-8");
message.addHeader("component", "VEVENT");
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("Outlook Meeting Request Using JavaMail");
File invitation = new File("<MYFILEPATH>\\vCalendar_5067936453064913847.ics");
MimeMultipart mixed = new MimeMultipart("mixed");
// Create the message part
MimeMultipart alternative = new MimeMultipart("alternative");
MimeBodyPart alternativePart = new MimeBodyPart();
alternativePart.setContent(alternative);
mixed.addBodyPart(alternativePart);
MimeBodyPart plain = new MimeBodyPart();
plain.setText("body", "UTF-8", "plain");
MimeBodyPart html = new MimeBodyPart();
html.setText("<div dir=\"ltr\">body</div>", "UTF-8", "html");
alternative.addBodyPart(plain);
alternative.addBodyPart(html);
// Create the attachment part
BodyPart icsBodyPart = new MimeBodyPart();
icsBodyPart.addHeader("method", "REQUEST");
icsBodyPart.addHeader("Content-Class", "urn:content-classes:calendarmessage");
icsBodyPart.addHeader("Content-ID", "calendar_message");
icsBodyPart.addHeader("component", "VEVENT");
FileInputStream inputStream = new FileInputStream(invitation.getAbsolutePath());
final DataSource source =
new ByteArrayDataSource(inputStream,
"text/calendar; charset=\"UTF-8\"; name=\"vCalendar_5067936453064913847.ics\"");
icsBodyPart.setDataHandler(new DataHandler(source));
icsBodyPart.setFileName(invitation.getName());
mixed.addBodyPart(icsBodyPart);
// Put parts in message
message.setContent(mixed);
// send message
Transport.send(message);
To know how to structure my mime parts, I look to my message structure in my gmail sendbox (the one that is reconized by Outlook) :
MIME-Version: 1.0
Date: Tue, 12 Jul 2022 14:44:10 +0200
Message-ID: <XXXXXXXXXXX#mail.gmail.com>
Subject: Mail title test
From: XXXXXXXXXXX <XXXXXXXXXXX#gmail.com>
To: XXXXXXXXXXX <XXXXXXXXXXX#XXXXXXXXXXX.com>
Content-Type: multipart/mixed; boundary="00000000000072927505e39b0616"
--00000000000072927505e39b0616
Content-Type: multipart/alternative; boundary="00000000000072927005e39b0614"
--00000000000072927005e39b0614
Content-Type: text/plain; charset="UTF-8"
Mail content test
--00000000000072927005e39b0614
Content-Type: text/html; charset="UTF-8"
<div dir="ltr">Mail content test<br></div>
--00000000000072927005e39b0614--
--00000000000072927505e39b0616
Content-Type: text/calendar; charset="UTF-8"; name="vCalendar_5067936453064913847.ics"
Content-Disposition: attachment; filename="vCalendar_5067936453064913847.ics"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_l4i5zybk0
Content-ID: <f_l4i5zybk0>
QkVHSU46VkNBTEVOREFSClBST0RJRDpTeWxvYiBudWxsClZFUlNJT046Mi4wCkNBTFNDQUxFOkdS
RUdPUklBTgpXXXXXXXXXXXVRVUVTVApCRUdJTjpWRVZFTlQKRFRTVEFNUDoyMDIyMDYyOVQxMjEy
MjRaClNVTU1BUlk6NSAtIMOJdsOpbmVtZW50IGR1IDI4MDYgw6AgU3lsb2IgZGUgZMOpbW8gCkRU
U1RBUlQ6MjAyMjA2MzBUMTEwMDAwWgpEVEVORDoyMDIyMDYzMFQxMzAwMDBaClVJRDp0ZXN0VWlk
MTY1OTc1QHN5bG9iLmNvbQpTRVFVRU5DRToxNjU2NDYwODAwCkRFU0NSSVBUSU9OOlRlc3QgZGUg
Y29ycCBkZSB0ZXh0ZVxuc3VyIHBsdXNpZXVycyBsaWduZXNcLCBhY2NlbnRzIMOgIHRlc3RlcgpB
VFRFTkRFRTtST0xFPVJFUSXXXXXXXXXXXXXOVDtQQVJUU1RBVD1BQ0NFUFRFRDtSU1ZQPUZBTFNF
O0NOPUFsZXhhbmRyZSBORURORUQ6bWFpbHRvOmFsZXgubmVkamFyaUBnbWFpbC5jb20KT1JHQU5J
WkVSO0NOPSJPcmfDom5pc2F0ZXVyIjptYWlsdG86ZGF0YUBzeWxvYi5jb20KRU5EOlZFVkVOVApF
TkQ6VkNBTEVOREFSCgo=
--00000000000072927505e39b0616--
If I knew how to see the same informations on outlook, I could compare the mail received from gmail and the one received from java, but I'm not sure it's possible (I found the "display / message details" option, but this option only show informations about the top level mime part, not the complete mime structure)
Does anyone have an idea how to fix this problem?
Thanks,
I had a similar problem and found a solution in rewriting a Content-Type header. I've added method=REQUEST to this header and after that outlook started recognize my emails as events.
Content-Type: text/calendar; charset="utf-8"; method=REQUEST
Example of code on python:
msg = MIMEMultipart()
msg['Subject'] = 'Your event'
msg['From'] = 'test#test.com'
msg['To'] = 'test#test.com'
with open('example.ics') as f:
event = MIMEText(f.read(), _subtype='calendar', _charset='utf-8')
event.replace_header('Content-Type', 'text/calendar; charset="utf-8"; method=REQUEST')
msg.attach(event)
s.send_message(msg)
s.quit()
I've set up my GAE/Java project to receiving emails and it works pretty fine excepting it can not preserve the incoming mail's format(e.g. bold, italic, font size, text color, bulleted list...), and the content type of incoming mails are always "text/plain", as a result from the end user's view the mail content huddled and unreadable.
For example I send a formatted mail from Gmail, when I receiving the mail in GAE all formats is tripped off and leaves a bulk of plain text.
Is there any way I can get incoming mail type as HTML so the format would be preserved?
While sending the mail through server. Set the body content type text/html.
.
.
.
htmlPart = new MimeBodyPart();
htmlPart.setContent("<b>html content</b>", "text/html");
This should work for you..
Looks like a duplicate of this question and answer
Moreover, I am copying a few excerpts from Google App Engine Documentation here which says:
The message contains a subject, a plaintext body, and an optional HTML body.
It can also contain file attachments, as well as a limited set of headers.
And I am guessing the content type should be text/html
I have one confusion about content type of mime message. Say I have a mime message. It is a multipart message and the body parts are like this
Mime body part containing plain text, html text(like some letters in
bold in body)
Second mime body part containing an attachment,
Third mime body part containing one inline image (which is being referred from body with cid)
When I am creating the body part, should I explicitly set the content type for top mime message and then each body part?
If yes, what should they be in the above example?
multipart/alternative is suggested for html, multipart/mixed is suggested for attachments, multipart/related is suggested for inline. I am using all of them, so what should be content-Type for complete message and different body parts?
Just for information I tried to replicate above scenario where I did not set the content type neither for the overall MimeMessage nor for body parts.
But still I get the expected stuff like plain text, Bold letters in body, attachment, inline image on james at right place
How come James is interpreting the mime message and body parts without setting the content type, and how come it is displaying them in right fashion?
Code For Reference
MimeMessage msg = new MimeMessage(mailSession);
MimeMultipart mpart = new MimeMultipart();
MimeBodyPart bp = new MimeBodyPart();
bp.setText("plain text and html text like<b>Test</>", CHARSET_UTF_8, MESSAGE_HTML_CONTENT_TYPE);
// add message body
mpart.addBodyPart(bp);
// adding attachment
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setFileName("WordFile1");
file = new File("word file");
DataSource source = new FileDataSource(file);
bodyPart.setDataHandler(new DataHandler(source));
mpart.addBodyPart(bodyPart);
// adding image inline
MimeBodyPart bodyPart2 = new MimeBodyPart();
bodyPart2.setFileName("inline image");
file2 = new File("image1");
DataSource source2 = new FileDataSource(file);
bodyPart2.setDataHandler(new DataHandler(source));
bodyPart2.setDisposition(MimeBodyPart.INLINE);
bodyPart2.setHeader("Content-ID", "Unique-CntentId");
bodyPart2.setHeader("Content-Type", "image/jpeg");
mpart.addBodyPart(bodyPart2);
// At last setting multipart In MimeMessage
msg.setContent(mpart);
With the above code, I get the correct html text, plain text, inline image and attachments at right place in ThunderBird integrated with James.
So I don't understand when and where to set multipart/mixed, multipart/alternative, multipart/related as Content-Type or does the mail server internally set it?
If I understand what you're trying to do, you want a message with this structure:
multipart/mixed
multipart/alternative
text/plain - a plain text version of the main message body
multipart/related
text/html - the html version of the main message body
image/jpeg - an image referenced by the main body
application/octet-stream (or whatever) - the attachment
That means three nested multipart pieces. You'll need to specify the subtype for each multipart piece other than the default "mixed".
The multipart/mixed and multipart/alternative pieces are relatively straightforward. The multipart/related piece is more complicated and you might want to read RFC 2387 and/or find some other tutorials to help you with that.
You can simplify the structure by getting rid of the multipart/related and just having the html text reference an image somewhere on the internet.
You should also test that a message with this structure is going to be displayed properly by all the mail readers you care about. Some mail readers will do a better job than others with a complicated structure such as this.
When using javax.mail.*, I'm trying to send a message with the content encoded in both text/plain and text/html. How can I add both encodings to the MimeMessage?
Does setText override the previous text set? ie: if I do setText("", "text/plain") then setText("", "text/html"), will the secord call override the message text previously set or will they both be present in the message?
Q: How do I send mail with both plain text as well as HTML text so that each mail reader can choose the format appropriate for it?
A: You'll want to send a MIME multipart/alternative message. You construct such a message essentially the same way you construct a multipart/mixed message, using a MimeMultipart object constructed using new MimeMultipart("alternative"). You then insert the text/plain body part as the first part in the multpart and insert the text/html body part as the second part in the multipart. You'll need to construct the plain and html parts yourself to have appropriate content. See RFC2046 for details of the structure of such a message.
http://www.oracle.com/technetwork/java/faq-135477.html#sendmpa
Anybody knows how to do this? I got all the information of the email (body, subject, from , to, cc, bcc) and need to generate an .eml file out of it.
You can create eml files with the following code. It works fine with thunderbird and probably with other email clients:
public static void createMessage(String to, String from, String subject, String body, List<File> attachments) {
try {
Message message = new MimeMessage(Session.getInstance(System.getProperties()));
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject(subject);
// create the message part
MimeBodyPart content = new MimeBodyPart();
// fill message
content.setText(body);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(content);
// add attachments
for(File file : attachments) {
MimeBodyPart attachment = new MimeBodyPart();
DataSource source = new FileDataSource(file);
attachment.setDataHandler(new DataHandler(source));
attachment.setFileName(file.getName());
multipart.addBodyPart(attachment);
}
// integration
message.setContent(multipart);
// store file
message.writeTo(new FileOutputStream(new File("c:/mail.eml")));
} catch (MessagingException ex) {
Logger.getLogger(Mailkit.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Mailkit.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can construct javax.mail.Message object (or have it already constructed from the mail server) and then you can use writeTo() method to save it to file.
See JavaMail API for more information.
EML files are just plain text files. The headers are separated from the body by a blank line. Headers look like this:
From: "DR CLEMENT OKON" <drclement#nigerianspam.com>
To: "You" <you#yourdomain.com>
Subject: REQUEST FOR URGENT BUSINESS RELATIONSHIP
Date: Tue, 30 Sep 2008 09:42:47 -0400
For more info, the official spec is RFC 2822. It's actually not as hard to read as some RFCs.
Edit: When I said "plain text" I should have thought for a second. I really meant plain ASCII - and not the 8-bit "extended ASCII" either - just up to character 127. If you want more than seven bits, you need some kind of encoding and things get complicated.
Looking at a typical EML file it looks like a raw dump of the text communication that went to the server. So it is a text file containing the mail headers and body. To get your attachments, different views, etc in the correct format inside the EML file you need to MIME-encode the body and its parts.
If you want to add HTML Stuff you have to add
content.setHeader("Content-Type", "text/html");
(as Marco Sulla said) but also change
message.setContent(multipart);
to
message.setContent(multipart,"text/html");