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 | * <mail> and mailloger support SMTP over TLS/SSL | ||||
| Bugzilla Report 19180. | 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 | * <zipfileset> can now be defined in the main body of a project | ||||
| and referred to with refid="xyz". Bugzilla Report 17007. | and referred to with refid="xyz". Bugzilla Report 17007. | ||||
| @@ -141,6 +141,19 @@ Library Dependencies</a> for more information. | |||||
| </tr> | </tr> | ||||
| </table> | </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> | <h3>Parameters specified as nested elements</h3> | ||||
| <h4>to / cc / bcc / from/ replyto </h4> | <h4>to / cc / bcc / from/ replyto </h4> | ||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * The Apache Software License, Version 1.1 | * 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. | * reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * 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. | * Holds an email address. | ||||
| * | * | ||||
| * @author roxspring@yahoo.com Rob Oxspring | * @author roxspring@yahoo.com Rob Oxspring | ||||
| * @author Michael Davey | |||||
| * @since Ant 1.5 | * @since Ant 1.5 | ||||
| */ | */ | ||||
| public class EmailAddress { | public class EmailAddress { | ||||
| @@ -72,10 +73,109 @@ public class EmailAddress { | |||||
| /** | /** | ||||
| * Creates a new email address based on the given string | * 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 | * Sets the email address | ||||
| * | * | ||||
| * @param address the actual email address | |||||
| * @param address the actual email address (without <>) | |||||
| */ | */ | ||||
| public void setAddress(String address) { | public void setAddress(String address) { | ||||
| this.address = 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() ); | |||||
| } | |||||
| } | |||||