68

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'.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Martin Rohwedder
  • 1,712
  • 4
  • 19
  • 34

8 Answers8

108

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).
Community
  • 1
  • 1
bvdb
  • 22,839
  • 10
  • 110
  • 123
  • 3
    Very good explaination. when i faced the issue i changed this: message.setContent(body, "text/html"); to this: message.setContent(body, "text/html;charset=utf-8"); – Amitk Jul 19 '20 at 14:13
  • 1
    Hello, does that mean the javax mail encodes the content (strings) in that charset before sending the mail? On the mail client, if we read the mail in a different encoding, it will not display correctly, isn't it? – Bằng Dec 02 '20 at 16:47
  • @ĐỗCôngBằng the mimetype will be sent along in the header of the e-mail. The receiving client then first extracts the mimetype from the header. That tells the client how to parse the message. But as mentioned in my answer, while the encoding can be specified in the mime-type, in some cases it will actually go through a number of more complex rules to finally determine the encoding. As soon as it knows the encoding it will then be able to parse the full message. All of which is the responsibility of your mail client. – bvdb Dec 04 '20 at 20:52
  • 1
    @bvdb I agree that mail client uses charset specified in the header. However, is the charset in header also the one used by Java mail to encode the content before sending? When I use `setContent(text, "text/html");` I have the email on OUTLOOK with its content encoded in ISO-8859-1 but its header says that text/html; charset=UTF-8. It leads OUTLOOK to use UTF-8 to decode the mail, but it was encoded with ISO-8859-1, so I have bizarre characters. In `com.sun.mail.handlers.text_plain.getCharset(String)`, us-ascii (ISO-8859-1) is used to encode the mail before sending if no charset is specified. – Bằng Dec 07 '20 at 13:29
54

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

Arsen Alexanyan
  • 3,061
  • 5
  • 25
  • 45
8

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 ' /* '.

Martin Rohwedder
  • 1,712
  • 4
  • 19
  • 34
3

It's easy, run your project with parameter -Dfile.encoding=UTF-8 ex: java -Dfile.encoding=UTF-8 -jar MyProject.jar

//Fix a typo

Lawrence Liu
  • 454
  • 3
  • 18
  • 2
    @Rohwedder, your filter may solve **your** specific problem. But it is not the answer to your initial question. Your question was about sending e-mails, not about handling web requests. – bvdb Feb 02 '15 at 12:41
  • 3
    Please fix your typo: `-Dfile.ecoding=UTF-8` -> `-Dfile.encoding=UTF-8` – Airwavezx Aug 29 '18 at 13:20
  • I had the same problem as described in the question, in a standalone Java service, and adding this parameter fix my problem. Easier than changing system config. Thanks! – MaxP Aug 04 '22 at 14:57
1

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.

Juandeyby
  • 19
  • 2
1
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

giantape
  • 21
  • 3
0

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.

D.Ogranos
  • 113
  • 7
-1

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.

Mustafa Poya
  • 2,615
  • 5
  • 22
  • 36