addresses containing also the name such as name <address> or (name) address. This allows these syntaxes to be used in the attributes from, tolist, cclist, replyto of the email task. PR: 22474 Submitted by: Michael Davey ( michael dot davey at coderage dot org) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275114 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -400,6 +400,11 @@ Other changes: | |||
| * <mail> and mailloger support SMTP over TLS/SSL | |||
| Bugzilla Report 19180. | |||
| * <mail> the attributes from, replyto ,tolist, cclist, bcclist | |||
| can now contain email addresses of the form name <address@xyz.com> | |||
| or (name) address@xyz.com | |||
| Bugzilla Report 22474. | |||
| * <zipfileset> can now be defined in the main body of a project | |||
| and referred to with refid="xyz". Bugzilla Report 17007. | |||
| @@ -141,6 +141,19 @@ Library Dependencies</a> for more information. | |||
| </tr> | |||
| </table> | |||
| <h3>Note regarding the attributes containing email addresses</h3> | |||
| Since ant 1.6, the attributes from, replyto, tolist, cclist, bcclist | |||
| can contain email addresses of the form : | |||
| <ul> | |||
| <li>address@xyz.com</li> | |||
| <li>name <address@xyz.com></li> | |||
| <li><address@xyz.com> name</li> | |||
| <li>(name) address@xyz.com</li> | |||
| <li>address@xyz.com (name)</li> | |||
| </ul> | |||
| <p>You need to enter the angle brackets as XML entities | |||
| <code>&gt;</code> and <code>&lt;</code>.</p> | |||
| <h3>Parameters specified as nested elements</h3> | |||
| <h4>to / cc / bcc / from/ replyto </h4> | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2002 The Apache Software Foundation. All rights | |||
| * Copyright (c) 2002-2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -57,6 +57,7 @@ package org.apache.tools.ant.taskdefs.email; | |||
| * Holds an email address. | |||
| * | |||
| * @author roxspring@yahoo.com Rob Oxspring | |||
| * @author Michael Davey | |||
| * @since Ant 1.5 | |||
| */ | |||
| public class EmailAddress { | |||
| @@ -72,10 +73,109 @@ public class EmailAddress { | |||
| /** | |||
| * Creates a new email address based on the given string | |||
| * | |||
| * @param address the email address | |||
| * @param email the email address (with or without <>) | |||
| * Acceptable forms include: | |||
| * address | |||
| * <address> | |||
| * name <address> | |||
| * <address> name | |||
| * (name) address | |||
| * address (name) | |||
| */ | |||
| public EmailAddress(String address) { | |||
| this.address = address; | |||
| // Make a limited attempt to extract a sanitized name and email address | |||
| // Algorithm based on the one found in Ant's MailMessage.java | |||
| public EmailAddress(String email) { | |||
| final int minLen = 9; | |||
| int len = email.length(); | |||
| // shortcut for "<address>" | |||
| if (len > minLen) { | |||
| if ((email.charAt(0) == '<' || email.charAt(1) == '<') | |||
| && (email.charAt(len - 1) == '>' || email.charAt(len - 2) == '>')) { | |||
| this.address = trim(email, true); | |||
| return; | |||
| } | |||
| } | |||
| int paramDepth = 0; | |||
| int start = 0; | |||
| int end = 0; | |||
| int nStart = 0; | |||
| int nEnd = 0; | |||
| for (int i = 0; i < len; i++) { | |||
| char c = email.charAt(i); | |||
| if (c == '(') { | |||
| paramDepth++; | |||
| if (start == 0) { | |||
| end = i; // support "address (name)" | |||
| nStart = i + 1; | |||
| } | |||
| } else if (c == ')') { | |||
| paramDepth--; | |||
| if (end == 0) { | |||
| start = i + 1; // support "(name) address" | |||
| nEnd = i; | |||
| } | |||
| } else if (paramDepth == 0 && c == '<') { | |||
| if (start == 0) { | |||
| nEnd = i; | |||
| } | |||
| start = i + 1; | |||
| } else if (paramDepth == 0 && c == '>') { | |||
| end = i; | |||
| if (end != len - 1) { | |||
| nStart = i + 1; | |||
| } | |||
| } | |||
| } | |||
| // DEBUG: System.out.println( email ); | |||
| if (end == 0) { | |||
| end = len; | |||
| } | |||
| // DEBUG: System.out.println( "address: " + start + " " + end ); | |||
| if (nEnd == 0) { | |||
| nEnd = len; | |||
| } | |||
| // DEBUG: System.out.println( "name: " + nStart + " " + nEnd ); | |||
| this.address = trim(email.substring(start, end), true); | |||
| this.name = trim(email.substring(nStart, nEnd), false); | |||
| // if the two substrings are longer than the original, then name | |||
| // contains address - so reset the name to null | |||
| if (this.name.length() + this.address.length() > len) { | |||
| this.name = null; | |||
| } | |||
| } | |||
| /** | |||
| * A specialised trim() that trims whitespace, | |||
| * '(', ')', '"', '<', '>' from the start and end of strings | |||
| */ | |||
| private String trim(String t, boolean trimAngleBrackets) { | |||
| int start = 0; | |||
| int end = t.length(); | |||
| boolean trim = false; | |||
| do { | |||
| trim = false; | |||
| if (t.charAt(end - 1) == ')' | |||
| || (t.charAt(end - 1) == '>' && trimAngleBrackets) | |||
| || (t.charAt(end - 1) == '"' && t.charAt(end - 2) != '\\') | |||
| || t.charAt(end - 1) <= '\u0020') { | |||
| trim = true; | |||
| end--; | |||
| } | |||
| if (t.charAt(start) == '(' | |||
| || (t.charAt(start) == '<' && trimAngleBrackets) | |||
| || t.charAt(start) == '"' | |||
| || t.charAt(start) <= '\u0020') { | |||
| trim = true; | |||
| start++; | |||
| } | |||
| } while (trim); | |||
| return t.substring(start, end); | |||
| } | |||
| @@ -92,7 +192,7 @@ public class EmailAddress { | |||
| /** | |||
| * Sets the email address | |||
| * | |||
| * @param address the actual email address | |||
| * @param address the actual email address (without <>) | |||
| */ | |||
| public void setAddress(String address) { | |||
| this.address = address; | |||
| @@ -0,0 +1,141 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "Ant" and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.email; | |||
| import junit.framework.TestCase; | |||
| /** | |||
| * @author Michael Davey | |||
| * @since Ant 1.6 | |||
| */ | |||
| public class EmailAddressTest extends TestCase { | |||
| public EmailAddressTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| } | |||
| public void test1() { | |||
| expectNameAddress( new EmailAddress("address (name)") ); | |||
| } | |||
| public void test2() { | |||
| expectNameAddress( new EmailAddress("(name) address") ); | |||
| } | |||
| public void test3() { | |||
| expectNameAddress( new EmailAddress("name <address>") ); | |||
| } | |||
| public void test4() { | |||
| expectNameAddress( new EmailAddress("<address> name") ); | |||
| } | |||
| public void test5() { | |||
| expectNameAddress( new EmailAddress("<address> (name)") ); | |||
| } | |||
| public void test6() { | |||
| expectNameAddress( new EmailAddress("(name) <address>") ); | |||
| } | |||
| public void test7() { | |||
| expectNameAddress2( new EmailAddress("address (<name>)") ); | |||
| } | |||
| public void test8() { | |||
| expectNameAddress2( new EmailAddress("(<name>) address") ); | |||
| } | |||
| public void test9() { | |||
| expectNameAddress3( new EmailAddress("address") ); | |||
| } | |||
| public void testA() { | |||
| expectNameAddress3( new EmailAddress("<address>") ); | |||
| } | |||
| public void testB() { | |||
| expectNameAddress3( new EmailAddress(" <address> ") ); | |||
| } | |||
| public void testC() { | |||
| expectNameAddress3( new EmailAddress("< address >") ); | |||
| } | |||
| public void testD() { | |||
| expectNameAddress3( new EmailAddress(" < address > ") ); | |||
| } | |||
| private void expectNameAddress(EmailAddress e) { | |||
| assertEquals( "name", e.getName() ); | |||
| assertEquals( "address", e.getAddress() ); | |||
| } | |||
| // where the name contains <> | |||
| private void expectNameAddress2(EmailAddress e) { | |||
| assertEquals( "<name>", e.getName() ); | |||
| assertEquals( "address", e.getAddress() ); | |||
| } | |||
| // where only an address is supplied | |||
| private void expectNameAddress3(EmailAddress e) { | |||
| assertTrue( "Expected null, found <" + e.getName() + ">", | |||
| e.getName() == null ); | |||
| assertEquals( "address", e.getAddress() ); | |||
| } | |||
| } | |||