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> | |||
| <td align="center" valign="top">No</td> | |||
| </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> | |||
| <td valign="top">subject</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 align="center" valign="top">No</td> | |||
| </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> | |||
| <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 | |||
| that order depending on what support classes are available. <code>${buildname}</code> | |||
| 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> | |||
| <p align="center">Copyright © 2000-2003 Apache Software Foundation. All rights | |||
| Reserved.</p> | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * 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. | |||
| * | |||
| * 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 paulo.gaspar@krankikom.de Paulo Gaspar | |||
| * @author roxspring@imapmail.org Rob Oxspring | |||
| * @author <a href="mailto:ishu@akm.ru">Aleksandr Ishutin</a> | |||
| * @since Ant 1.5 | |||
| * @ant.task name="mail" category="network" | |||
| */ | |||
| @@ -132,6 +133,8 @@ public class EmailTask | |||
| /** file list */ | |||
| private Vector files = new Vector(); | |||
| private Vector filesets = new Vector(); | |||
| /** Character set for MimeMailer*/ | |||
| private String charset=null; | |||
| /** | |||
| @@ -410,7 +413,7 @@ public class EmailTask | |||
| autoFound = true; | |||
| log("Using MIME mail", Project.MSG_VERBOSE); | |||
| } 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); | |||
| } | |||
| } | |||
| // 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 | |||
| Enumeration e = filesets.elements(); | |||
| @@ -519,10 +531,34 @@ public class EmailTask | |||
| if (failOnError) { | |||
| throw e; | |||
| } | |||
| } | |||
| catch(Exception e){ | |||
| log("Failed to send email", Project.MSG_WARN); | |||
| if (failOnError) { | |||
| throw new BuildException(e); | |||
| } | |||
| } finally { | |||
| message = savedMessage; | |||
| 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.FileReader; | |||
| import java.io.IOException; | |||
| import java.io.OutputStreamWriter; | |||
| import java.io.PrintStream; | |||
| import java.io.PrintWriter; | |||
| import org.apache.tools.ant.ProjectComponent; | |||
| /** | |||
| * Class representing an email message. | |||
| * | |||
| * @author roxspring@yahoo.com Rob Oxspring | |||
| * @author <a href="mailto:ishu@akm.ru">Aleksandr Ishutin</a> | |||
| * @since Ant 1.5 | |||
| */ | |||
| public class Message extends ProjectComponent { | |||
| @@ -71,7 +75,7 @@ public class Message extends ProjectComponent { | |||
| private StringBuffer buffer = new StringBuffer(); | |||
| private String mimeType = "text/plain"; | |||
| private boolean specified = false; | |||
| private String charset=null; | |||
| /** Creates a new empty message */ | |||
| public Message() { | |||
| @@ -145,8 +149,13 @@ public class Message extends ProjectComponent { | |||
| * @param out The print stream to write to | |||
| * @throws IOException if an error occurs | |||
| */ | |||
| public void print(PrintStream out) | |||
| public void print(PrintStream ps) | |||
| 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) { | |||
| // Read message from a file | |||
| FileReader freader = new FileReader(messageSource); | |||
| @@ -154,7 +163,6 @@ public class Message extends ProjectComponent { | |||
| try { | |||
| BufferedReader in = new BufferedReader(freader); | |||
| String line = null; | |||
| while ((line = in.readLine()) != null) { | |||
| out.println(getProject().replaceProperties(line)); | |||
| } | |||
| @@ -164,6 +172,7 @@ public class Message extends ProjectComponent { | |||
| } else { | |||
| out.println(getProject().replaceProperties(buffer.substring(0))); | |||
| } | |||
| out.flush(); | |||
| } | |||
| @@ -175,5 +184,22 @@ public class Message extends ProjectComponent { | |||
| public boolean isMimeTypeSpecified() { | |||
| 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 | |||
| * | |||
| * 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 | |||
| @@ -53,16 +53,23 @@ | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.email; | |||
| import java.io.ByteArrayInputStream; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.io.PrintStream; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.util.Enumeration; | |||
| import java.util.Properties; | |||
| import java.util.StringTokenizer; | |||
| import java.util.Vector; | |||
| import javax.activation.DataHandler; | |||
| import javax.activation.FileDataSource; | |||
| import javax.mail.Message; | |||
| import javax.mail.MessagingException; | |||
| import javax.mail.Session; | |||
| @@ -72,17 +79,75 @@ import javax.mail.internet.InternetAddress; | |||
| import javax.mail.internet.MimeBodyPart; | |||
| import javax.mail.internet.MimeMessage; | |||
| import javax.mail.internet.MimeMultipart; | |||
| import org.apache.tools.ant.BuildException; | |||
| /** | |||
| * Uses the JavaMail classes to send Mime format email. | |||
| * | |||
| * @author roxspring@yahoo.com Rob Oxspring | |||
| * @author <a href="mailto:ishu@akm.ru">Aleksandr Ishutin</a> | |||
| * @since Ant 1.5 | |||
| */ | |||
| 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 { | |||
| Properties props = new Properties(); | |||
| @@ -113,20 +178,38 @@ class MimeMailer extends Mailer { | |||
| msg.setRecipients(Message.RecipientType.BCC, | |||
| 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); | |||
| out.close(); | |||
| MimeBodyPart textbody = new MimeBodyPart(); | |||
| textbody.setContent(baos.toString(), message.getMimeType()); | |||
| textbody.setDataHandler(new DataHandler(sds)); | |||
| attachments.addBodyPart(textbody); | |||
| Enumeration e = files.elements(); | |||
| @@ -177,5 +260,15 @@ class MimeMailer extends Mailer { | |||
| 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(); | |||
| } | |||
| } | |||