How to send html email to outlook from Java - java

I'm trying to send an email in html format using JavaMail but it always seems to only display as a text email in Outlook.
Here is my code:
try
{
Properties props = System.getProperties();
props.put("mail.smtp.host", mailserver);
props.put("mail.smtp.from", fromEmail);
props.put("mail.smtp.auth", authentication);
props.put("mail.smtp.port", port);
Session session = Session.getDefaultInstance(props, null);
// -- Create a new message --
MimeMessage message = new MimeMessage(session);
// -- Set the FROM and TO fields --
message.setFrom(new InternetAddress(fromEmail, displayName));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false));
MimeMultipart content = new MimeMultipart();
MimeBodyPart text = new MimeBodyPart();
MimeBodyPart html = new MimeBodyPart();
text.setText(textBody);
text.setHeader("MIME-Version" , "1.0" );
text.setHeader("Content-Type" , text.getContentType() );
html.setContent(htmlBody, "text/html");
html.setHeader("MIME-Version" , "1.0" );
html.setHeader("Content-Type" , html.getContentType() );
content.addBodyPart(text);
content.addBodyPart(html);
message.setContent( content );
message.setHeader("MIME-Version" , "1.0" );
message.setHeader("Content-Type" , content.getContentType() );
message.setHeader("X-Mailer", "My own custom mailer");
// -- Set the subject --
message.setSubject(subject);
// -- Set some other header information --
message.setSentDate(new Date());
// INFO: only SMTP protocol is supported for now...
Transport transport = session.getTransport("smtp");
transport.connect(mailserver, username, password);
message.saveChanges();
// -- Send the message --
transport.sendMessage(message, message.getAllRecipients());
transport.close();
return true;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw e;
}
Any ideas why the html version of the email won't display in Outlook?

After a lot of investigation, I've been able to make some significant progress.
Firstly, instead of using JavaMail directly, I recommend using the Jakarta Commons Email library. This really simplifies the issue a lot!
The code is now:
HtmlEmail email = new HtmlEmail();
email.setHostName(mailserver);
email.setAuthentication(username, password);
email.setSmtpPort(port);
email.setFrom(fromEmail);
email.addTo(to);
email.setSubject(subject);
email.setTextMsg(textBody);
email.setHtmlMsg(htmlBody);
email.setDebug(true);
email.send();
Talk about simple.
However, there is still an issue. The html version of the email works great in Gmail, Hotmail, etc. But it still won't correctly display in Outlook. It always wants to display the text version and I'm not sure why. I suspect it's a setting in Outlook, but I can't find it...

In addition to removing the html.setHeader("Content-Type", html.getContentType())
call as suggest already, I'd replace the line:
MimeMultipart content = new MimeMultipart();
…with:
MimeMultipart content = new MimeMultiPart("alternative");
…and removing the line:
message.setHeader("Content-Type" , content.getContentType() );
The default MimeMultiPart constructor could be causing problems with a "multipart/mixed" content-type.
When using multipart/alternative, the alternatives are ordered by how faithful they are to the original, with the best rendition last. However, clients usually give users an option to display plain text, even when HTML is present. Are you sure that this option is not enabled in Outlook? How do other user agents, like Thunderbird, or GMail, treat your messages?
Also, ensure that the HTML is well-formed. I'd validate the HTML content with the W3 validation service, and possibly save it into a file and view it with different versions of IE too. Maybe there's a flaw there causing Outlook to fall back to plain text.

html.setContent(htmlBody, "text/html");
html.setHeader("MIME-Version" , "1.0" );
html.setHeader("Content-Type" , html.getContentType() );
setContent and setHeader("Content-Type", String) do the same thing - is it possible that html.getContentType() is returning something other than text/html?
Expanding based on comment and #PhilLho & #erickson's answer (geez, I must type slowly), use:
MimeMultipart content = new MimeMultipart("alternative")

Change this To:
message.setContent(new String(sBuffer.toString().getBytes(), "iso-8859-1"), "text/html; charset=\"iso-8859-1\"");
The content char set need to be set, I don't see why the content itself.
Should rather be:
message.setContent(sBuffer.toString(), "text/html;charset=iso-8859-1");

I used the following code:
mimeBodyPart1.setDataHandler(new DataHandler(new ByteArrayDataSource(messageBody, "text/html; charset=utf-8")));
multiPart.addBodyPart(mimeBodyPart1);
message.setContent(multiPart, "text/html; charset=utf-8");
Now, Outlook displays in html format.

You should look at the source of the received message: is the Content-Type of the message multipart/alternative?

message.setContent(new String(sBuffer.toString().getBytes(), "iso-8859-1"), "text/html; charset=iso-8859-1");
Should solve your problem (removed \" characters).

workaroung solution solved outlook 2003: This message uses a character set that is not supported by the Internet Service. doesn't display correctly.
It could be due to the encoding. Most html pages use iso-8859-1 not cp-1252 try changing
For example, your code is:
message.setContent(sBuffer.toString(), "text/html");
Change this to:
message.setContent(new String(sBuffer.toString().getBytes(), "iso-8859-1"), "text/html; charset=\"iso-8859-1\"");
This throws a new checked exception : java.io.UnsupportedEncodingException so you need to declare it to be thrown or catch it.
iso-8859-1 is supported so, the exception will never be thrown unless something gets corrupted with your rt.jar.
Regards,
Javeed
javeed.mca#gmail.com

Related

java email attachment being sent as plain text in body

I'm having an issue with sending attachments via email in java using the java mail (1.4.6). It seems that when I attach a document of any sort and send it, the recipient gets the file in plain text format in the body. Rather than, you guessed it, sending the whole file like you would expect and the body not interfered with.
Code
try
{
// Create a message
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(Compose.to));
message.setSubject(Compose.subject);
//message.setText(Compose.body);
//If there are no CC's then skip it. This if seemed to decrease send time.
if(Compose.cc != null)
{
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(Compose.cc));
message.saveChanges();
}
else
message.saveChanges();
/*
* For adding the attached file to the email. This time the if
* statement is used to stop the email attachment process if there
* is none. Other wise due to the way I've set it up it'll try to
* send file path and file name as null, and we fail an otherwise valid email.
*/
if(Compose.filename != null)
{
String file = Compose.filepath;
String fileName = Compose.filename;
Multipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(fileName);
multipart.addBodyPart(messageBodyPart);
BodyPart messageBodyPart2 = new MimeBodyPart();
messageBodyPart2.setText(Compose.body);
multipart.addBodyPart(messageBodyPart2);
message.setContent(multipart);
}
else
{
message.setText(Compose.body);
message.saveChanges();
}
//Send the message by javax.mail.Transport .
Transport tr = session.getTransport("smtp"); // Get Transport object from session
tr.connect(smtphost, username, password); // We need to connect
tr.sendMessage(message, message.getAllRecipients()); // Send message
//Notify the user everything functioned fine.
JOptionPane.showMessageDialog(null, "Your mail has been sent.");
}
Thinking over this I remembered how FileDataSource() is an overloaded statement taking a string or a file type as a parameter, trying both I got the same result but I will experiment more with the the file type now.
EDIT: After more testing I noticed that sometimes the file will not appear along with whatever was in the body at the time of sending.
For each part you have to set disposition to Part.INLINE for the body and Part.ATTACHMENT for the attachment. The attachFile methods will do that for you. Avoid JavaMail 1.4.6 in favor of the latest release or at least use JavaMail 1.4.7 which contains fixes for known issues with JavaMail 1.4.6.
You're setting the attachment as the first body part. It needs to be the second body part.
Also, consider upgrading to JavaMail 1.5.4 and using the MimeBodyPart.attachFile method to attach the file.

Java Mail API - Encoding problems

I'm using Java Mail API and I'm trying to send an email through Gmail's SMTP.
How my program works:
java.util.Scanner class is used to get user input - I'm asking user for various parameters to be used in mail sending class; which does the following:
Message mailMessage = new MimeMessage(session);
mailMessage.setFrom(new InternetAddress("example#example.com"));
mailMessage.setRecipients(Message.RecipientType.TO,InternetAddress.parse(mail.getTo()));
mailMessage.setSubject(mail.getSubject());
mailMessage.setText(mail.getMessage());
Transport.send(mailMessage);
Everything works as long as I use ASCII symbols/ chars. But whenever I want to use "country-specific" characters - like [õäöü] - I get bunch of weird-looking symbols...
Techniques I've used so far(which don't work for me):
setHeader("Content-Type", "text/plain; charset=UTF-8");
setHeader("Content-Encoding","ISO-8859-9");
setContent(message, "text/plain; charset=iso-8859-2");
Note: everything is displayed correctly inside an IDE when System.out.println() is performed to display the message to be sent.
EDIT: e.x. when sent message body is [õäöü]
It's displayed [ä„”?] in Gmail.
EDIT: When mailMessage.setText(MimeUtility.encodeText(mail.getMessage(), "UTF-8", "Q")); is used, then the output in Gmail is following:
"=?UTF-8?Q?=C3=A4=E2=80=9E=E2=80=9D=EF=BF=BD;=0D=0A?="
ANOTHER EDIT: Interestingly, when I do: mailMessage.setText(strVar + "õäöü", "ISO-8859-1");
It actually appends "õäöü" nicely in my email (but the first part[strVar] of the string is still full of ?'s and []'s).
MimeMessage message = new MimeMessage(session);
message.setSubject(subject, "UTF-8");
message.setText(body, "UTF-8");
So one has to set the character encoding for both, body and subject.
Addendum because of comment of #bartac
For the corresponding MimeBodyPart do a setHeader("Content-Type", "text/plain; charset=UTF-8").
You should use setText(String text, String charset) or setText(String text, String charset, String subtype) to set the text body with a specific encoding.
MimeUtility.encodeText() is not meant for body text, but only for encoded text in headers (and then only for headers set with setHeader or addHeader).
Basically, my code works just fine, as its supposed to. It was the cmd, that could not handle non-ascii letters. I used a bat file to access a jar. I think I'm just going to make a little GUI then... Thanks everyone for answering.
The following worked for me:
MimeMessage message = ...
message.setSubject(subject, "UTF-8");
message.setContent(body, "text/plain; charset=UTF-8");
Where subject and body are regular String objects with no special treatment (code and user interface use UTF-8).
1- Consider you want to send an email with this string in the body:
"Olá João!"
2 - As the code is running in the GAE server, this string is interpreted with the default ASCII encoding. To send this email with the correct accented characters, define the String as:
String body = "Ol\u00e1 Jo\u00e3o!";
The special characters are manually defined with its UTF-8 codes. Search the codes you need in the table http://www.utf8-chartable.de/
3- Convert the string encoding to UTF-8. All the codes manually typed will be now correctly interpreted:
Session session = Session.getDefaultInstance(props);
MimeMessage message = new MimeMessage(session);
String encodedSubject = new String (subject.getBytes("UTF-8"),"UTF-8");
String encodedBody = new String (body.getBytes("UTF-8"),"UTF-8");
message.setSubject(encodedSubject, "UTF-8");
message.setText(encodedBody, "UTF-8");
JavaMailSenderImpl emailSender = new JavaMailSenderImpl();
mailSender.setHost("...");
MimeMessage message = emailSender.createMimeMessage();
message.setSubject("...", "UTF-8");
message.setText("...", "UTF-8");
MimeMessageHelper helper = new MimeMessageHelper(message, "UTF-8");
helper.setFrom(from);
helper.setTo(to);
emailSender.send(message);
In case if you use HTML messages, try this:
Message message = new MimeMessage(session);
message.setContent(htmlText, "text/html; charset=UTF-8");
the following charset working to me: charset=ISO-8859-1, example:
mail.setContent(testMail.getTexto(), "text/plain; charset=ISO-8859-1");

Sending string as an attachment using javamail

I have been trying to get a solution but I am not able to. Here is the whole thing. I wrote the following code
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
message.setSentDate(new Date());
MimeBodyPart messagePart = new MimeBodyPart();
messagePart.setContent(messageContent, "text/html");
Multipart multipart = new MimeMultipart("mixed");
multipart.addBodyPart(messagePart);
MimeBodyPart attachmentPart = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(attachment.getBytes(), "text/plain");
attachmentPart.setDataHandler(new DataHandler(source));
attachmentPart.setFileName(attachmentFileName);
multipart.addBodyPart(attachmentPart);
message.setContent(multipart);
try {
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
The code is pretty much self explanatory. messagePart is the mail and attachmentPart is the attachment. But messagePart here is not plain text. It is HTML. So the problem is if I run this code mail is sent successfully but the attachment does not come attached to the mail. So my question boils down to this. Is it possible to send html content and attach something to a mail at the same time. I am stuck here. Could anyone help please.
I don't see anything obviously wrong with your code.
How are you determining that the message has no attachment?
You can see exactly what JavaMail would send by adding "message.writeTo(System.out);" just before you call Transport.send.
What version of JavaMail are you using? What mail server are you using? Some mail servers (I'm looking at you, Exchange) will reformat the message to what they think it should be, even if it's different than what you intended.
If you are running on Google App Engine and you add a dummy text part it works great. I have no idea why the dummy text part makes it work, but I was having the exact same problem and adding a dummy text part worked for me too.
You want to add
attachmentPart.setDisposition(Part.ATTACHMENT);
Part.ATTACHMENT means the part should be showed as an attachment.
Part.INLINE means you want to show the attachment as part of the message.

Sending an html email with an image in GAE

When I send an e-mail currently from within GAE I receive the email with a Content-Transfer-Encoding of quoted-printable. I am looking to set this to base64. The quoted-printable would be find except the image is not displayed when I receive the email. As it is right now my html which looks like this:
String base64StringImg = Base64.encode(my byte array);
StringBuilder htmlBody = new StringBuilder();
htmlBody.append("<html>");
htmlBody.append("<body>");
htmlBody.append("<img src='data:image/png;base64,");
htmlBody.append(base64StringImg);
htmlBody.append("'/>");
htmlBody.append("<br/><br/>");
htmlBody.append("Hello " + name);
htmlBody.append("</body>");
htmlBody.append("</html>");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromUser));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
message.setSubject(subject);
Multipart mp = new MimeMultipart();
BodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(htmlBody.toString(), "text/html; charset=UTF-8");
mp.addBodyPart(htmlPart);
message.setContent(mp);
Transport.send(message);
How can I send an html e-mail with an image in GAE? I have read the following two bug/feature requests which make it clear there are limitations.
http://code.google.com/p/googleappengine/issues/detail?id=198
http://code.google.com/p/googleappengine/issues/detail?id=965
HTML embedded images seem to be poorly supported in email clients: http://www.campaignmonitor.com/blog/post/1761/embedding-images-in-email/
What is supported are images HTML images attached to email: http://www.campaignmonitor.com/blog/post/1759/embedding-images-revisited/
However, as you noted with the link to the issue, the second option is poorly supported in GAE. What you could try is create by hand the mail content shown in second link.

Email attachments not included within Glassfish

I have a MailMessage class I've written to manage sending email from my application. It works fine for plain text messages, and the attachment logic works when I compile and run it manually on the command line, but it fails to include my attachments when I'm running it within Glassfish 3.1. I'm assuming there must be some subtle class loading problem that I'm clobbering on the command line by having my CLASSPATH environment set, but I haven't been able to figure out what application server setting I need to change. Here's the code I use to create and send my mail message when running on the command line:
public static void main(String[] args) throws Exception {
String[] toAddr = new String[] {"steve.ferguson#epsilon.com"};
String subject = "This is a test";
String data = "This is a message body";
MailMessage mailMessage = new MailMessage(toAddr, subject, data);
mailMessage.addAttachment(new File("/etc/hosts"), "text/plain");
mailMessage.send();
}
If I change this function to a method called by my servlet, with debugging enabled, the resulting mail message looks like this:
[#|2011-11-17T11:21:37.710-0500|INFO|glassfish3.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-1;|Date: Thu, 17 Nov 2011 11:21:37 -0500 (EST)
From: sender#mydomain.com
To: steve.ferguson#mydomain.com
Message-ID: <9116840.7.1321546897580.JavaMail...>
Subject: This is a test
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_6_16232037.1321546897569"
.
|#]
By comparison, when I run the same code on the command line, it shows all of the attachments, each with the separate message boundary. This is the function I'm using to add the attachments to the underlying MimeMessage:
private Multipart buildMultipartMessage(String messageBody)
throws MessagingException {
MimeBodyPart messagePart = new MimeBodyPart();
messagePart.setText(messageBody.toString());
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messagePart);
// Attach each of our files
for (File part : attachment.keySet()) {
BodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setDataHandler(new DataHandler(new FileDataSource(part)));
attachmentPart.setFileName(part.getName() + ".txt");
attachmentPart.setHeader("Content-Type", attachment.get(part));
attachmentPart.setHeader("Content-ID", part.getName());
attachmentPart.setDisposition(Part.ATTACHMENT);
multipart.addBodyPart(attachmentPart);
}
return multipart;
}
Which is called and used like this by my MailMessage class:
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("sender#mydomain.com"));
InternetAddress[] addresses = new InternetAddress[mailTo.length];
for (int i = 0; i < mailTo.length; i++)
addresses[i] = new InternetAddress(mailTo[i]);
message.setRecipients(Message.RecipientType.TO, addresses);
message.setSubject(subject);
message.setSentDate(new Date());
Multipart multipart = buildMultipartMessage(messageBody.toString());
message.setContent(multipart);
Again, all of this code, exactly as is, compiles, runs, and produces a valid email with attachments when run on the command line. It's only when I do the same thing within Glassfish that I get an empty message.
Any suggestions on how to diagnose this would be most appreciated.
Steve
UPDATE:
If I add this code after the call to buildMultipartMessage(), but before message.setContent(multipart), I can see that the content is correct:
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("/var/tmp/stf"));
multipart.writeTo(bos);
bos.close();
} catch (Exception ex) { }
The /var/tmp/stf file contains the full message body with attachments and separators. I'm still confused as to why this works from the command line, but not within Glassfish, but the information may be useful in resolving the problem.
It turned out that my solution to this problem caused the current problem. Having javax.mail.jar in my boot classpath and activation.jar in my endorsed directory was the only way I could get email handling working with the logger, but then they didn't work for normal usage. I have no idea why this is, but I found that eliminating the -Xbootclasspath option and removing activation.jar from my endorsed directory fixed the problem. If anyone has any speculation as to why, I'd be glad to do some more testing and report back. For now, I guess I have to live without email logging, because the attachments are a requirement for my application.
Perhaps if I switch to log4j instead of using the native Java EE 6 logging, I can have the best of both worlds.

Categories