1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.mail.util; 18 19 import javax.mail.internet.InternetAddress; 20 import java.net.IDN; 21 22 /** 23 * Converts email addresses containing International Domain Names into an ASCII 24 * representation suitable for sending an email. 25 * 26 * @see <a href="https://docs.oracle.com/javase/tutorial/i18n/network/idn.html">https://docs.oracle.com/javase/tutorial/i18n/network/idn.html</a> 27 * @see <a href="https://en.wikipedia.org/wiki/Punycode">https://en.wikipedia.org/wiki/Punycode</a> 28 * @see <a href="https://tools.ietf.org/html/rfc5891">https://tools.ietf.org/html/rfc5891</a> 29 * @see <a href="https://en.wikipedia.org/wiki/Punycode">https://en.wikipedia.org/wiki/Punycode</a> 30 * 31 * @since 1.5 32 */ 33 public class IDNEmailAddressConverter 34 { 35 /** 36 * Convert an email address to its ASCII representation using "Punycode". 37 * 38 * @param email email address. 39 * @return The ASCII representation 40 */ 41 public String toASCII(final String email) 42 { 43 final int idx = findAtSymbolIndex(email); 44 45 if (idx < 0) 46 { 47 return email; 48 } 49 50 return getLocalPart(email, idx) + '@' + IDN.toASCII(getDomainPart(email, idx)); 51 } 52 53 /** 54 * Convert the address part of an InternetAddress to its Unicode representation. 55 * 56 * @param address email address. 57 * @return The Unicode representation 58 */ 59 String toUnicode(final InternetAddress address) 60 { 61 return address != null ? toUnicode(address.getAddress()) : null; 62 } 63 64 /** 65 * Convert an "Punycode" email address to its Unicode representation. 66 * 67 * @param email email address. 68 * @return The Unicode representation 69 */ 70 String toUnicode(final String email) 71 { 72 final int idx = findAtSymbolIndex(email); 73 74 if (idx < 0) 75 { 76 return email; 77 } 78 79 return getLocalPart(email, idx) + '@' + IDN.toUnicode(getDomainPart(email, idx)); 80 } 81 82 /** 83 * Extracts the local part of the email address. 84 * 85 * @param email email address. 86 * @param idx index of '@' character. 87 * @return local part of email 88 */ 89 private String getLocalPart(final String email, final int idx) 90 { 91 return email.substring(0, idx); 92 } 93 94 /** 95 * Extracts the domain part of the email address. 96 * 97 * @param email email address. 98 * @param idx index of '@' character. 99 * @return domain part of email 100 */ 101 private String getDomainPart(final String email, final int idx) 102 { 103 return email.substring(idx + 1); 104 } 105 106 /** 107 * Null-safe wrapper for {@link String#indexOf} to find the '@' character. 108 * 109 * @param value String value. 110 * @return index of first '@' character or {@code -1} 111 */ 112 private int findAtSymbolIndex(final String value) 113 { 114 if (value == null) 115 { 116 return -1; 117 } 118 119 return value.indexOf('@'); 120 } 121 }