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() ); | |||||
} | |||||
} |