git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274480 13f79535-47bb-0310-9956-ffa450edef68master
@@ -100,6 +100,13 @@ Library Dependencies</a> for more information. | |||||
<code>auto</code>. The default value is <code>auto</code>.</td> | <code>auto</code>. The default value is <code>auto</code>.</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">charset</td> | |||||
<td valign="top">Character set of the email.<br> | |||||
You can also set the charset in the message nested element.<br> | |||||
These options are mutually exclusive.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">subject</td> | <td valign="top">subject</td> | ||||
<td valign="top">Email subject line.</td> | <td valign="top">Email subject line.</td> | ||||
@@ -151,6 +158,13 @@ attributes:</p> | |||||
<td valign="top">The content type to use for the message.</td> | <td valign="top">The content type to use for the message.</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">charset</td> | |||||
<td valign="top">Character set of the message<br> | |||||
You can also set the charset as attribute of the enclosing mail task.<br> | |||||
These options are mutually exclusive.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<p>If the <code>src</code> attribute is not specified, then text can be added | <p>If the <code>src</code> attribute is not specified, then text can be added | ||||
@@ -187,6 +201,21 @@ the <code><message></code> element.</p> | |||||
task will attempt to use JavaMail and fall back to UU encoding or no encoding in | task will attempt to use JavaMail and fall back to UU encoding or no encoding in | ||||
that order depending on what support classes are available. <code>${buildname}</code> | that order depending on what support classes are available. <code>${buildname}</code> | ||||
will be replaced with the <code>buildname</code> property's value.</p> | will be replaced with the <code>buildname</code> property's value.</p> | ||||
<blockquote><pre> | |||||
<property name="line2" value="some_international_message"/> | |||||
<echo message="${line2}"/> | |||||
<mail mailhost="somehost@xyz.com" mailport="25" subject="Test build" charset="utf-8"> | |||||
<from address="me@myist.com"/> | |||||
<to address="all@xyz.com" /> | |||||
<message>some international text:${line2}</message> | |||||
</mail> | |||||
</pre></blockquote> | |||||
<p>Sends an eMail from <i>me@myisp.com</i> to <i>all@xyz.com</i> with a subject of | |||||
<i>Test Build</i>, the message body being coded in UTF-8 | |||||
<hr> | <hr> | ||||
<p align="center">Copyright © 2000-2003 Apache Software Foundation. All rights | <p align="center">Copyright © 2000-2003 Apache Software Foundation. All rights | ||||
Reserved.</p> | Reserved.</p> | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
* | * | ||||
* Copyright (c) 2000-2002 The Apache Software Foundation. All rights | |||||
* Copyright (c) 2000-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 | ||||
@@ -76,6 +76,7 @@ import org.apache.tools.ant.types.FileSet; | |||||
* @author ehatcher@apache.org Erik Hatcher | * @author ehatcher@apache.org Erik Hatcher | ||||
* @author paulo.gaspar@krankikom.de Paulo Gaspar | * @author paulo.gaspar@krankikom.de Paulo Gaspar | ||||
* @author roxspring@imapmail.org Rob Oxspring | * @author roxspring@imapmail.org Rob Oxspring | ||||
* @author <a href="mailto:ishu@akm.ru">Aleksandr Ishutin</a> | |||||
* @since Ant 1.5 | * @since Ant 1.5 | ||||
* @ant.task name="mail" category="network" | * @ant.task name="mail" category="network" | ||||
*/ | */ | ||||
@@ -132,6 +133,8 @@ public class EmailTask | |||||
/** file list */ | /** file list */ | ||||
private Vector files = new Vector(); | private Vector files = new Vector(); | ||||
private Vector filesets = new Vector(); | private Vector filesets = new Vector(); | ||||
/** Character set for MimeMailer*/ | |||||
private String charset=null; | |||||
/** | /** | ||||
@@ -410,7 +413,7 @@ public class EmailTask | |||||
autoFound = true; | autoFound = true; | ||||
log("Using MIME mail", Project.MSG_VERBOSE); | log("Using MIME mail", Project.MSG_VERBOSE); | ||||
} catch (Throwable e) { | } catch (Throwable e) { | ||||
log("Failed to initialise MIME mail", Project.MSG_WARN); | |||||
log("Failed to initialise MIME mail: "+e.getMessage(),Project.MSG_WARN); | |||||
} | } | ||||
} | } | ||||
@@ -468,6 +471,15 @@ public class EmailTask | |||||
message.setMimeType(messageMimeType); | message.setMimeType(messageMimeType); | ||||
} | } | ||||
} | } | ||||
// set the character set if not done already (and required) | |||||
if (charset != null) { | |||||
if (message.getCharset()!=null) { | |||||
throw new BuildException("The charset can only be " | |||||
+ "specified in one location"); | |||||
} else { | |||||
message.setCharset(charset); | |||||
} | |||||
} | |||||
// identify which files should be attached | // identify which files should be attached | ||||
Enumeration e = filesets.elements(); | Enumeration e = filesets.elements(); | ||||
@@ -519,10 +531,34 @@ public class EmailTask | |||||
if (failOnError) { | if (failOnError) { | ||||
throw e; | throw e; | ||||
} | } | ||||
} | |||||
catch(Exception e){ | |||||
log("Failed to send email", Project.MSG_WARN); | |||||
if (failOnError) { | |||||
throw new BuildException(e); | |||||
} | |||||
} finally { | } finally { | ||||
message = savedMessage; | message = savedMessage; | ||||
files = savedFiles; | files = savedFiles; | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Sets the character set of mail message. | |||||
* Will be ignored if mimeType contains ....; Charset=... substring or | |||||
* encoding is not a <code>mime</code> | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setCharset(String charset) { | |||||
this.charset = charset; | |||||
} | |||||
/** | |||||
* Returns the character set of mail message. | |||||
* | |||||
* @return Charset of mail message. | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public String getCharset() { | |||||
return charset; | |||||
} | |||||
} | } | ||||
@@ -57,13 +57,17 @@ import java.io.BufferedReader; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.FileReader; | import java.io.FileReader; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStreamWriter; | |||||
import java.io.PrintStream; | import java.io.PrintStream; | ||||
import java.io.PrintWriter; | |||||
import org.apache.tools.ant.ProjectComponent; | import org.apache.tools.ant.ProjectComponent; | ||||
/** | /** | ||||
* Class representing an email message. | * Class representing an email message. | ||||
* | * | ||||
* @author roxspring@yahoo.com Rob Oxspring | * @author roxspring@yahoo.com Rob Oxspring | ||||
* @author <a href="mailto:ishu@akm.ru">Aleksandr Ishutin</a> | |||||
* @since Ant 1.5 | * @since Ant 1.5 | ||||
*/ | */ | ||||
public class Message extends ProjectComponent { | public class Message extends ProjectComponent { | ||||
@@ -71,7 +75,7 @@ public class Message extends ProjectComponent { | |||||
private StringBuffer buffer = new StringBuffer(); | private StringBuffer buffer = new StringBuffer(); | ||||
private String mimeType = "text/plain"; | private String mimeType = "text/plain"; | ||||
private boolean specified = false; | private boolean specified = false; | ||||
private String charset=null; | |||||
/** Creates a new empty message */ | /** Creates a new empty message */ | ||||
public Message() { | public Message() { | ||||
@@ -145,8 +149,13 @@ public class Message extends ProjectComponent { | |||||
* @param out The print stream to write to | * @param out The print stream to write to | ||||
* @throws IOException if an error occurs | * @throws IOException if an error occurs | ||||
*/ | */ | ||||
public void print(PrintStream out) | |||||
public void print(PrintStream ps) | |||||
throws IOException { | throws IOException { | ||||
// We need character encoding aware printing here. | |||||
// So, using PrintWriter over OutputStreamWriter instead of PrintStream | |||||
PrintWriter out = charset!=null? | |||||
new PrintWriter(new OutputStreamWriter(ps,charset)): | |||||
new PrintWriter(ps); | |||||
if (messageSource != null) { | if (messageSource != null) { | ||||
// Read message from a file | // Read message from a file | ||||
FileReader freader = new FileReader(messageSource); | FileReader freader = new FileReader(messageSource); | ||||
@@ -154,7 +163,6 @@ public class Message extends ProjectComponent { | |||||
try { | try { | ||||
BufferedReader in = new BufferedReader(freader); | BufferedReader in = new BufferedReader(freader); | ||||
String line = null; | String line = null; | ||||
while ((line = in.readLine()) != null) { | while ((line = in.readLine()) != null) { | ||||
out.println(getProject().replaceProperties(line)); | out.println(getProject().replaceProperties(line)); | ||||
} | } | ||||
@@ -164,6 +172,7 @@ public class Message extends ProjectComponent { | |||||
} else { | } else { | ||||
out.println(getProject().replaceProperties(buffer.substring(0))); | out.println(getProject().replaceProperties(buffer.substring(0))); | ||||
} | } | ||||
out.flush(); | |||||
} | } | ||||
@@ -175,5 +184,22 @@ public class Message extends ProjectComponent { | |||||
public boolean isMimeTypeSpecified() { | public boolean isMimeTypeSpecified() { | ||||
return specified; | return specified; | ||||
} | } | ||||
/** | |||||
* Sets the character set of mail message. | |||||
* Will be ignored if mimeType contains ....; Charset=... substring. | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setCharset(String charset) { | |||||
this.charset = charset; | |||||
} | |||||
/** | |||||
* Returns the charset of mail message. | |||||
* | |||||
* @return Charset of mail message. | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public String getCharset() { | |||||
return charset; | |||||
} | |||||
} | } | ||||
@@ -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 | ||||
@@ -53,16 +53,23 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs.email; | package org.apache.tools.ant.taskdefs.email; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | |||||
import java.io.OutputStream; | |||||
import java.io.PrintStream; | import java.io.PrintStream; | ||||
import java.io.UnsupportedEncodingException; | import java.io.UnsupportedEncodingException; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Properties; | import java.util.Properties; | ||||
import java.util.StringTokenizer; | |||||
import java.util.Vector; | import java.util.Vector; | ||||
import javax.activation.DataHandler; | import javax.activation.DataHandler; | ||||
import javax.activation.FileDataSource; | import javax.activation.FileDataSource; | ||||
import javax.mail.Message; | import javax.mail.Message; | ||||
import javax.mail.MessagingException; | import javax.mail.MessagingException; | ||||
import javax.mail.Session; | import javax.mail.Session; | ||||
@@ -72,17 +79,75 @@ import javax.mail.internet.InternetAddress; | |||||
import javax.mail.internet.MimeBodyPart; | import javax.mail.internet.MimeBodyPart; | ||||
import javax.mail.internet.MimeMessage; | import javax.mail.internet.MimeMessage; | ||||
import javax.mail.internet.MimeMultipart; | import javax.mail.internet.MimeMultipart; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
/** | /** | ||||
* Uses the JavaMail classes to send Mime format email. | * Uses the JavaMail classes to send Mime format email. | ||||
* | * | ||||
* @author roxspring@yahoo.com Rob Oxspring | * @author roxspring@yahoo.com Rob Oxspring | ||||
* @author <a href="mailto:ishu@akm.ru">Aleksandr Ishutin</a> | |||||
* @since Ant 1.5 | * @since Ant 1.5 | ||||
*/ | */ | ||||
class MimeMailer extends Mailer { | class MimeMailer extends Mailer { | ||||
/** Sends the email */ | |||||
public void send() { | |||||
// Default character set | |||||
private static final String defaultCharset = System.getProperty("file.encoding"); | |||||
// To work poperly with national charsets we have to use | |||||
// implementation of interface javax.activation.DataSource | |||||
/** | |||||
* @since Ant 1.6 | |||||
*/ | |||||
class StringDataSource implements javax.activation.DataSource { | |||||
private String data=null; | |||||
private String type=null; | |||||
private String charset = null; | |||||
private ByteArrayOutputStream out; | |||||
public InputStream getInputStream() throws IOException { | |||||
if(data == null && out == null) | |||||
throw new IOException("No data"); | |||||
else { | |||||
if(out!=null) { | |||||
data=(data!=null)?data.concat(out.toString(charset)):out.toString(charset); | |||||
out=null; | |||||
} | |||||
return new ByteArrayInputStream(data.getBytes(charset)); | |||||
} | |||||
} | |||||
public OutputStream getOutputStream() throws IOException { | |||||
if(out==null) { | |||||
out=new ByteArrayOutputStream(); | |||||
} | |||||
return out; | |||||
} | |||||
public void setContentType(String type) { | |||||
this.type=type.toLowerCase(); | |||||
} | |||||
public String getContentType() { | |||||
if(type !=null && type.indexOf("charset")>0 && type.startsWith("text/")) | |||||
return type; | |||||
// Must be like "text/plain; charset=windows-1251" | |||||
return type!=null?type.concat("; charset=".concat(charset)): | |||||
"text/plain".concat("; charset=".concat(charset)); | |||||
} | |||||
public String getName() { | |||||
return "StringDataSource"; | |||||
} | |||||
public void setCharset(String charset) { | |||||
this.charset = charset; | |||||
} | |||||
public String getCharset() { | |||||
return charset; | |||||
} | |||||
} | |||||
/** Sends the email */ | |||||
public void send() { | |||||
try { | try { | ||||
Properties props = new Properties(); | Properties props = new Properties(); | ||||
@@ -113,20 +178,38 @@ class MimeMailer extends Mailer { | |||||
msg.setRecipients(Message.RecipientType.BCC, | msg.setRecipients(Message.RecipientType.BCC, | ||||
internetAddresses(bccList)); | internetAddresses(bccList)); | ||||
if (subject != null) { | |||||
msg.setSubject(subject); | |||||
// Choosing character set of the mail message | |||||
// First: looking it from MimeType | |||||
String charset = parseCharSetFromMimeType(message.getMimeType()); | |||||
if(charset!=null) { | |||||
// Assign/reassign message charset from MimeType | |||||
message.setCharset(charset); | |||||
} | |||||
// Next: looking if charset having explict definition | |||||
else { | |||||
charset = message.getCharset(); | |||||
if(charset==null) { | |||||
// Using default | |||||
charset=defaultCharset; | |||||
message.setCharset(charset); | |||||
} | |||||
} | } | ||||
msg.addHeader("Date", getDate()); | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
PrintStream out = new PrintStream(baos); | |||||
// Using javax.activation.DataSource paradigm | |||||
StringDataSource sds = new StringDataSource(); | |||||
sds.setContentType(message.getMimeType()); | |||||
sds.setCharset(charset); | |||||
if (subject != null) | |||||
msg.setSubject(subject,charset); | |||||
msg.addHeader("Date", getDate()); | |||||
PrintStream out = new PrintStream(sds.getOutputStream()); | |||||
message.print(out); | message.print(out); | ||||
out.close(); | out.close(); | ||||
MimeBodyPart textbody = new MimeBodyPart(); | MimeBodyPart textbody = new MimeBodyPart(); | ||||
textbody.setContent(baos.toString(), message.getMimeType()); | |||||
textbody.setDataHandler(new DataHandler(sds)); | |||||
attachments.addBodyPart(textbody); | attachments.addBodyPart(textbody); | ||||
Enumeration e = files.elements(); | Enumeration e = files.elements(); | ||||
@@ -177,5 +260,15 @@ class MimeMailer extends Mailer { | |||||
return addrs; | return addrs; | ||||
} | } | ||||
private String parseCharSetFromMimeType(String type){ | |||||
int pos; | |||||
if(type==null || (pos=type.indexOf("charset"))<0) | |||||
return null; | |||||
// Assuming mime type in form "text/XXXX; charset=XXXXXX" | |||||
StringTokenizer token = new StringTokenizer(type.substring(pos),"=; "); | |||||
token.nextToken();// Skip 'charset=' | |||||
return token.nextToken(); | |||||
} | |||||
} | } | ||||