From f1a4a514784709dadf94d8b4f38ab2f52f1b1e1e Mon Sep 17 00:00:00 2001 From: Antoine Levy-Lambert Date: Tue, 19 Aug 2003 12:15:04 +0000 Subject: [PATCH] Changes to the constructor of EmailAddress(String address) to make it support addresses containing also the name such as name
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-ffa450edef68 --- WHATSNEW | 5 + docs/manual/CoreTasks/mail.html | 13 ++ .../ant/taskdefs/email/EmailAddress.java | 110 +++++++++++++- .../ant/taskdefs/email/EmailAddressTest.java | 141 ++++++++++++++++++ 4 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 src/testcases/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java diff --git a/WHATSNEW b/WHATSNEW index 4baa812a9..8150502a7 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -400,6 +400,11 @@ Other changes: * and mailloger support SMTP over TLS/SSL Bugzilla Report 19180. +* the attributes from, replyto ,tolist, cclist, bcclist + can now contain email addresses of the form name + or (name) address@xyz.com + Bugzilla Report 22474. + * can now be defined in the main body of a project and referred to with refid="xyz". Bugzilla Report 17007. diff --git a/docs/manual/CoreTasks/mail.html b/docs/manual/CoreTasks/mail.html index 63564a26b..05dacc12f 100644 --- a/docs/manual/CoreTasks/mail.html +++ b/docs/manual/CoreTasks/mail.html @@ -141,6 +141,19 @@ Library Dependencies for more information. +

Note regarding the attributes containing email addresses

+Since ant 1.6, the attributes from, replyto, tolist, cclist, bcclist +can contain email addresses of the form : +
    +
  • address@xyz.com
  • +
  • name <address@xyz.com>
  • +
  • <address@xyz.com> name
  • +
  • (name) address@xyz.com
  • +
  • address@xyz.com (name)
  • +
+

You need to enter the angle brackets as XML entities +&gt; and &lt;.

+

Parameters specified as nested elements

to / cc / bcc / from/ replyto

diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java index 852797b15..28bd918a1 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java @@ -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 + *
+ * name
+ *
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 "
" + 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; diff --git a/src/testcases/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java b/src/testcases/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java new file mode 100644 index 000000000..40a2a3213 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java @@ -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 + * . + */ + +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
") ); + } + + public void test4() { + expectNameAddress( new EmailAddress("
name") ); + } + + public void test5() { + expectNameAddress( new EmailAddress("
(name)") ); + } + + public void test6() { + expectNameAddress( new EmailAddress("(name)
") ); + } + + public void test7() { + expectNameAddress2( new EmailAddress("address ()") ); + } + + public void test8() { + expectNameAddress2( new EmailAddress("() address") ); + } + + public void test9() { + expectNameAddress3( new EmailAddress("address") ); + } + + public void testA() { + expectNameAddress3( new EmailAddress("
") ); + } + + public void testB() { + expectNameAddress3( new EmailAddress("
") ); + } + + 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( "", 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() ); + } +}