001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.mail2.jakarta.util; 018 019import java.net.IDN; 020import java.util.function.Function; 021 022import jakarta.mail.internet.InternetAddress; 023 024/** 025 * Converts email addresses containing International Domain Names into an ASCII representation suitable for sending an email. 026 * 027 * @see <a href="https://docs.oracle.com/javase/tutorial/i18n/network/idn.html">https://docs.oracle.com/javase/tutorial/i18n/network/idn.html</a> 028 * @see <a href="https://en.wikipedia.org/wiki/Punycode">https://en.wikipedia.org/wiki/Punycode</a> 029 * @see <a href="https://tools.ietf.org/html/rfc5891">https://tools.ietf.org/html/rfc5891</a> 030 * @see <a href="https://en.wikipedia.org/wiki/Punycode">https://en.wikipedia.org/wiki/Punycode</a> 031 * 032 * @since 1.5 033 */ 034public class IDNEmailAddressConverter { 035 036 /** 037 * Constructs a new instance. 038 */ 039 public IDNEmailAddressConverter() { 040 // empty 041 } 042 043 /** 044 * Extracts the domain part of the email address. 045 * 046 * @param email email address. 047 * @param idx index of '@' character. 048 * @return domain part of email 049 */ 050 private String getDomainPart(final String email, final int idx) { 051 return email.substring(idx + 1); 052 } 053 054 /** 055 * Extracts the local part of the email address. 056 * 057 * @param email email address. 058 * @param idx index of '@' character. 059 * @return local part of email 060 */ 061 private String getLocalPart(final String email, final int idx) { 062 return email.substring(0, idx); 063 } 064 065 /** 066 * Converts an email address to its ASCII representation using "Punycode". 067 * 068 * @param email email address. 069 * @return The ASCII representation 070 */ 071 public String toASCII(final String email) { 072 return toString(email, IDN::toASCII); 073 } 074 075 private String toString(final String email, final Function<String, String> converter) { 076 final int idx = email == null ? -1 : email.indexOf('@'); 077 if (idx < 0) { 078 return email; 079 } 080 return getLocalPart(email, idx) + '@' + converter.apply(getDomainPart(email, idx)); 081 } 082 083 /** 084 * Converts the address part of an InternetAddress to its Unicode representation. 085 * 086 * @param address email address. 087 * @return The Unicode representation 088 */ 089 String toUnicode(final InternetAddress address) { 090 return address != null ? toUnicode(address.getAddress()) : null; 091 } 092 093 /** 094 * Converts an "Punycode" email address to its Unicode representation. 095 * 096 * @param email email address. 097 * @return The Unicode representation 098 */ 099 String toUnicode(final String email) { 100 return toString(email, IDN::toUnicode); 101 } 102}