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