UTF-8 charset doesn't work with javax.mail - java
I have used Java Mail API, for sending emails. I am using a contact formular to send the input, which has to be send to a specific email.
The email is send without problems, though I am a danish guy, and I am therefore in need of three danish characters which is 'æ', 'ø' and 'å', in the subject and the email text.
I have therefore seen that I can use UTF-8 character encoding, to provide these characters, but when my mail is send I only see some strange letters - 'ã¦', 'ã¸' and 'ã¥' - instead of the danish letters - 'æ', 'ø' and 'å'.
My method to send the email is looking like this:
public void sendEmail(String name, String fromEmail, String subject, String message) throws AddressException, MessagingException, UnsupportedEncodingException, SendFailedException
{
//Set Mail properties
Properties props = System.getProperties();
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.host", "smtp.gmail.com");
props.setProperty("mail.smtp.socketFactory.port", "465");
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("my_username", "my_password");
}
});
//Create the email with variable input
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setHeader("Content-Type", "text/plain; charset=UTF-8");
mimeMessage.setFrom(new InternetAddress(fromEmail, name));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("my_email"));
mimeMessage.setSubject(subject, "utf-8");
mimeMessage.setContent(message, "text/plain");
//Send the email
Transport.send(mimeMessage);
}
Please help me find out how I can correct this 'error'.
For all e-mails
There are a couple of system properties related to mailing, that can probably simplify your code. I am talking about this specific property actually: "mail.mime.charset".
The mail.mime.charset System property can be used to specify the default MIME charset to use for encoded words and text parts that don't otherwise specify a charset. Normally, the default MIME charset is derived from the default Java charset, as specified in the file.encoding System property. Most applications will have no need to explicitly set the default MIME charset. In cases where the default MIME charset to be used for mail messages is different than the charset used for files stored on the system, this property should be set.
As you can read above, by default there is no value for the mail.mime.charset and the file encoding (file.encoding property) is used.
For a specific e-mail
However, if you want to specify a specific encoding for a specific e-mail, then you should probably use the 2 parameter setSubject(subject,charset) and setText(text,charset) methods.
If that doesn't work, then probably your input is already corrupted before it reached this point. In other words, you probably used the wrong encoding to collect your data.
Mime types are complicated
The setContent(content, "UTF-8") (as other sources claim) will just not work. Just look at the signature of this method: setContent(Object content, String mimetype). Mime type and charset are 2 totally different things. Imho, you should really be using one of the setText(...) methods with a charset parameter.
But if you persist in using a mimetype to set the charset setContent(content,mimetype), then use the correct format. (not just "UTF-8", but something like "text/plain; charset=UTF-8"). But more importantly, be aware that every mime-type has its own way of handling charsets.
As specified in RFC-2046 the default charset for text/plain is US-ASCII, but can be overruled with an additional charset parameter.
However, in RFC-6657 makes clear that the text/xml type determines the charset using the content of the message. The charset parameter will just be ignored here.
And in RFC-2854 is stated that text/html should really always specify a charset. But if you don't, then it will use ISO-8859-1 (=Latin-1).
Maybe You should provide also UTF-8 here
mimeMessage.setContent(message, "text/plain; charset=UTF-8");
You have to look at http://www.coderanch.com/t/274480/java/java/JavaMail-set-content-utf
After spending a lot of time on debugging, and searching the internet for a clue, I have found a solution to my problem.
It seems that whenever I sended data through a web request, my application didn't encode the characters with UTF-8 encoding. This meant that the data which was send from my contact form, which contained æ, ø and å characters, couldn't be handled correct by the character encoding.
The solution seemed to setup a Character Encoding Filter, in my Deployment Descriptor, which would encode all incoming request from the web to be with the character encoding UTF-8.
private void registerCharacterEncodingFilter(ServletContext servletContext) {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", encodingFilter);
characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
}
This filter sets the encoding to be UTF-8 and force the encoding to all requests comming at the url ' /* '.
It's easy,
run your project with parameter -Dfile.encoding=UTF-8
ex:
java -Dfile.encoding=UTF-8 -jar MyProject.jar
//Fix a typo
Before sending your String to the send method, you must convert the String into UTF-8
If you are receiving a "request" parameter, you can use "setCharacterEncoding":
request.setCharacterEncoding("utf-8");
String subject = request.getParameter("subject");
String content = request.getParameter("content");
...
MimeMessage mineMessage = new MimeMessage(session);
mineMessage.setFrom(new InternetAddress(myAccountEmail));
mineMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recepient));
mineMessage.setSubject(subject, "UTF-8");
mineMessage.setContent(content, "text/plain;charset=UTF-8");
Otherwise, convert your String into UTF-8 format with the following method:
String subject = new String(subject.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));
String content = new String(content.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));
...
MimeMessage mineMessage = new MimeMessage(session);
mineMessage.setFrom(new InternetAddress(myAccountEmail));
mineMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recepient));
mineMessage.setSubject(subject, "UTF-8");
mineMessage.setContent(content, "plain/plain;charset=UTF-8");
This is the result in Spanish.
mimeMessage.setContent(mail.getBody(), "text/html; charset=UTF-8");
maybe iam wrong, but this work for me. :) any ööö, äää, üüü character will shown correctly in my outlook.
outlook screenshot
I know I'm late to this question, but I had a similar problem just now.
It may be worth it to check your source encodings too! I was using a test class, with hardcoded subject/text containing some special characters, which kept coming garbled when sending the email. Even though I had set the charset UTF-8 wherever applicable (mimeMessage.setSubject(subject, charset), mimeMessage.setContent(content, "text/plain; charset=UTF-8")).
Then I noted that the source encoding of this class was windows-1252. From my understanding, when a java file is compiled, any source texts are converted to UTF-8. But in this case, in the maven pom.xml for this project, the project.build.sourceEncoding property was missing - so I'm actually not sure which encoding maven was using during compilation (by default) since none was specified.
Changing the source encoding was not possible here, but as soon as I changed the special characters to Unicode code literals (e.g. "ü" to "\u00fc"), the whole thing worked fine.
Maybe is too later, but there is a very simple method to fix this problem.
Just call this constructor to create a MimeMessageHelper that encode UTF-8 as we escpect:
MimeMessage **mimeMessage** = mailSender.createMimeMessage();
MimeMessageHelper **helper** = new MimeMessageHelper(mimeMessage, false(or true if you want include Multipart), "UTF-8");
No more actions are needed, continue the mail sending flow as you wish.
Related
How to resolve UTF-8 enconding in JSP on tomcat server? [duplicate]
I have used Java Mail API, for sending emails. I am using a contact formular to send the input, which has to be send to a specific email. The email is send without problems, though I am a danish guy, and I am therefore in need of three danish characters which is 'æ', 'ø' and 'å', in the subject and the email text. I have therefore seen that I can use UTF-8 character encoding, to provide these characters, but when my mail is send I only see some strange letters - 'ã¦', 'ã¸' and 'ã¥' - instead of the danish letters - 'æ', 'ø' and 'å'. My method to send the email is looking like this: public void sendEmail(String name, String fromEmail, String subject, String message) throws AddressException, MessagingException, UnsupportedEncodingException, SendFailedException { //Set Mail properties Properties props = System.getProperties(); props.setProperty("mail.smtp.starttls.enable", "true"); props.setProperty("mail.smtp.host", "smtp.gmail.com"); props.setProperty("mail.smtp.socketFactory.port", "465"); props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.setProperty("mail.smtp.auth", "true"); props.setProperty("mail.smtp.port", "465"); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { #Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("my_username", "my_password"); } }); //Create the email with variable input MimeMessage mimeMessage = new MimeMessage(session); mimeMessage.setHeader("Content-Type", "text/plain; charset=UTF-8"); mimeMessage.setFrom(new InternetAddress(fromEmail, name)); mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("my_email")); mimeMessage.setSubject(subject, "utf-8"); mimeMessage.setContent(message, "text/plain"); //Send the email Transport.send(mimeMessage); } Please help me find out how I can correct this 'error'.
For all e-mails There are a couple of system properties related to mailing, that can probably simplify your code. I am talking about this specific property actually: "mail.mime.charset". The mail.mime.charset System property can be used to specify the default MIME charset to use for encoded words and text parts that don't otherwise specify a charset. Normally, the default MIME charset is derived from the default Java charset, as specified in the file.encoding System property. Most applications will have no need to explicitly set the default MIME charset. In cases where the default MIME charset to be used for mail messages is different than the charset used for files stored on the system, this property should be set. As you can read above, by default there is no value for the mail.mime.charset and the file encoding (file.encoding property) is used. For a specific e-mail However, if you want to specify a specific encoding for a specific e-mail, then you should probably use the 2 parameter setSubject(subject,charset) and setText(text,charset) methods. If that doesn't work, then probably your input is already corrupted before it reached this point. In other words, you probably used the wrong encoding to collect your data. Mime types are complicated The setContent(content, "UTF-8") (as other sources claim) will just not work. Just look at the signature of this method: setContent(Object content, String mimetype). Mime type and charset are 2 totally different things. Imho, you should really be using one of the setText(...) methods with a charset parameter. But if you persist in using a mimetype to set the charset setContent(content,mimetype), then use the correct format. (not just "UTF-8", but something like "text/plain; charset=UTF-8"). But more importantly, be aware that every mime-type has its own way of handling charsets. As specified in RFC-2046 the default charset for text/plain is US-ASCII, but can be overruled with an additional charset parameter. However, in RFC-6657 makes clear that the text/xml type determines the charset using the content of the message. The charset parameter will just be ignored here. And in RFC-2854 is stated that text/html should really always specify a charset. But if you don't, then it will use ISO-8859-1 (=Latin-1).
Maybe You should provide also UTF-8 here mimeMessage.setContent(message, "text/plain; charset=UTF-8"); You have to look at http://www.coderanch.com/t/274480/java/java/JavaMail-set-content-utf
After spending a lot of time on debugging, and searching the internet for a clue, I have found a solution to my problem. It seems that whenever I sended data through a web request, my application didn't encode the characters with UTF-8 encoding. This meant that the data which was send from my contact form, which contained æ, ø and å characters, couldn't be handled correct by the character encoding. The solution seemed to setup a Character Encoding Filter, in my Deployment Descriptor, which would encode all incoming request from the web to be with the character encoding UTF-8. private void registerCharacterEncodingFilter(ServletContext servletContext) { CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter(); encodingFilter.setEncoding("UTF-8"); encodingFilter.setForceEncoding(true); FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", encodingFilter); characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*"); } This filter sets the encoding to be UTF-8 and force the encoding to all requests comming at the url ' /* '.
It's easy, run your project with parameter -Dfile.encoding=UTF-8 ex: java -Dfile.encoding=UTF-8 -jar MyProject.jar //Fix a typo
Before sending your String to the send method, you must convert the String into UTF-8 If you are receiving a "request" parameter, you can use "setCharacterEncoding": request.setCharacterEncoding("utf-8"); String subject = request.getParameter("subject"); String content = request.getParameter("content"); ... MimeMessage mineMessage = new MimeMessage(session); mineMessage.setFrom(new InternetAddress(myAccountEmail)); mineMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recepient)); mineMessage.setSubject(subject, "UTF-8"); mineMessage.setContent(content, "text/plain;charset=UTF-8"); Otherwise, convert your String into UTF-8 format with the following method: String subject = new String(subject.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8")); String content = new String(content.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8")); ... MimeMessage mineMessage = new MimeMessage(session); mineMessage.setFrom(new InternetAddress(myAccountEmail)); mineMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recepient)); mineMessage.setSubject(subject, "UTF-8"); mineMessage.setContent(content, "plain/plain;charset=UTF-8"); This is the result in Spanish.
mimeMessage.setContent(mail.getBody(), "text/html; charset=UTF-8"); maybe iam wrong, but this work for me. :) any ööö, äää, üüü character will shown correctly in my outlook. outlook screenshot
I know I'm late to this question, but I had a similar problem just now. It may be worth it to check your source encodings too! I was using a test class, with hardcoded subject/text containing some special characters, which kept coming garbled when sending the email. Even though I had set the charset UTF-8 wherever applicable (mimeMessage.setSubject(subject, charset), mimeMessage.setContent(content, "text/plain; charset=UTF-8")). Then I noted that the source encoding of this class was windows-1252. From my understanding, when a java file is compiled, any source texts are converted to UTF-8. But in this case, in the maven pom.xml for this project, the project.build.sourceEncoding property was missing - so I'm actually not sure which encoding maven was using during compilation (by default) since none was specified. Changing the source encoding was not possible here, but as soon as I changed the special characters to Unicode code literals (e.g. "ü" to "\u00fc"), the whole thing worked fine.
Maybe is too later, but there is a very simple method to fix this problem. Just call this constructor to create a MimeMessageHelper that encode UTF-8 as we escpect: MimeMessage **mimeMessage** = mailSender.createMimeMessage(); MimeMessageHelper **helper** = new MimeMessageHelper(mimeMessage, false(or true if you want include Multipart), "UTF-8"); No more actions are needed, continue the mail sending flow as you wish.
sending an Arabic text in email
I have a problem sending an Arabic text in email with java language. this is my message in properties file: mail.send=تجربة I use this syntax in jave : ResourceBundle dq_resource = ResourceBundle.getBundle("nls.myfile_ar"); String text= dq_resource.getString("mail.send") but when I received email U have this text : اÙ?Ù?Ù?ضÙ?ع I try also in java with this code : String text= new String(dq_resource.getString("mail.send").getBytes(),Charset.forName("UTF-8")); but I have this text in mail : ا�?�?�?ض�?ع
You need to set a header for the mail, something like message.setHeader("Content-Type", "text/plain; charset=UTF-8"); setHeader is a method of the Message class that allows you to set a header.
The easiest solution could be using strings normally ( without getBytes method ) changing the default encoding in your workspace for example eclipse. Windows-->Preferences-->General-->workspace-->Text file encoding Also you can try to convert UTF-8 to UTF-16 .
Encoding Problems
Having an issue with a java string used for emails in a java source file. The string contains "Protégé". Our server environment from what I have been able to determine uses UTF-8. So I converted it to "Protégé" for UTF-8. It works great on our server, but when I run it locally it doesn't translate it properly. So I changed eclipse to use UTF-8 under preferences but it doesn't translate it locally. Still shows "Protégé". Any ideas? From the comments: I ran this locally and on our server: OutputStreamWriter out = new OutputStreamWriter(new ByteArrayOutputStream()); System.out.println(out.getEncoding()); And it displays Cp1252 locally and UTF-8 on our JBoss server. We originally had the string with "Protégé" but on JBoss it only shows "Prot". When I use "Prot\u00e9g\u00e9" it works fine locally but when ran on our server it shows "Protg".
If the string contains "Prot\u00e9g\u00e9", this precludes a compiler encoding problem (like alluded by SyntaxT3rr0r), since it is now right in the Java String (unless there is a compiler bug, which I would not assume). Thus we have an problem between output, transfer and display. How do you look at the output from your server? It could be that there somewhere is some recoding which destroys your strings. Or that somewhere some output is mis-declared. If you are using a Terminal/command window to look at the output, consider setting it to UTF-8 before connecting to the server. And yes, Java uses internally UTF-16 for the strings, but some system dependent encoding as both compiler default and default encoding of OutputStreamWriter/InputStreamReader and several other APIs which convert between strings and bytes. Looks like this is UTF-8 on the server and Windows-1252 on your client system. This should not really matter here.
Try this: MimeMessage msg = new MimeMessage(session); MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setDataHandler(new DataHandler(new ByteArrayDataSource(message.toString, "text/html"))); mbp1.setContent(new String(message.getBytes("UTF-8"),"ISO-8859-1"), "text/html"); Multipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); msg.setContent(mp, "text/html"); put your language char set instead of "ISO-8859-1"
response.sendredirect with url with foreign chars - how to encode?
I have a jsf app that has international users so form inputs can have non-western strings like kanjii and chinese - if I hit my url with ..?q=東日本大 the output on the page is correct and I see the q input in my form gets populated fine. But if I enter that same string into my form and submit, my app does a redirect back to itself after constructing the url with the populated parameters in the url (seems redundant but this is due to 3rd party integration) but the redirect is not encoding the string properly. I have url = new String(url.getBytes("ISO-8859-1"), "UTF-8"); response.sendRedirect(url); But url redirect ends up being q=???? I've played around with various encoding strings (switched around ISO and UTF-8 and just got a bunch of gibberish in the url) in the String constructor but none seem to work to where I get q=東日本大 Any ideas as to what I need to do to get the q=東日本大 populated in the redirect properly? Thanks.
How are you making your url? URIs can't directly have non-ASCII characters in; they have to be turned into bytes (using a particular encoding) and then %-encoded. URLEncoder.encode should be given an encoding argument, to ensure this is the right encoding. Otherwise you get the default encoding, which is probably wrong and always to be avoided. String q= "\u6771\u65e5\u672c\u5927"; // 東日本大 String url= "http://example.com/query?q="+URLEncoder.encode(q, "utf-8"); // http://example.com/query?q=%E6%9D%B1%E6%97%A5%E6%9C%AC%E5%A4%A7 response.sendRedirect(url); This URI will display as the IRI ‘http://example.com/query?q=東日本大’ in the browser address bar. Make sure you're serving your pages as UTF-8 (using Content-Type header/meta) and interpreting query string input as UTF-8 (server-specific; see this faq for Tomcat.)
Try response.setContentType("text/html; charset=UTF-16"); response.setCharacterEncoding("utf-16");
Java mail charset ISO-8859-2 not working
I am having problem with Java Mail API. I can successfully send mail, but some special characters (from ISO-8859-2 languages like czech, slovak) are not shown in mail. They are damaged even in IDE output. What am I doing wrong? Message msg = new MimeMessage(session); msg.setContent(message, "text/plain; charset=iso-8859-2")
msg.setContent(message, "text/plain; charset=UTF-8"); instead of the charset you've given?
I found solution, using multipart. here is code : MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(from)); MimeMultipart multipart = new MimeMultipart(); msg.setRecipient(Message.RecipientType.TO, new InternetAddress(recipient)); MimeBodyPart tmpBp = new MimeBodyPart(); tmpBp.setContent(message,"text/plain; charset=utf-8"); multipart.addBodyPart(tmpBp); msg.setContent(multipart); Transport.send(msg);
Rather use UTF-8 as charset and configure your IDE console to use the very same charset as well. I don't know which IDE you're using as you didn't tell about it, but if it were Eclipse, then you can change it by Window > Preferences > General > Workspace > Text file encoding > Other > UTF-8. If that doesn't fix the problem, then the problem lies somewhere else. Maybe you're reading the message from a file using the wrong encoding. For that you need to use InputStreamReader which takes the charset as 2nd constructor argument.
You should use the setText method from the class MimeMessage instead of setContent /** * Convenience method that sets the given String as this part's * content, with a MIME type of "text/plain" and the specified * charset. The given Unicode string will be charset-encoded * using the specified charset. The charset is also used to set * the "charset" parameter. * * #param text the text content to set * #param charset the charset to use for the text * #exception MessagingException if an error occurs */ public void setText(String text, String charset) throws MessagingException {