diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java new file mode 100644 index 00000000..186d71e0 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java @@ -0,0 +1,343 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +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.security.Provider; +import java.security.Security; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Locale; +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.activation.DataHandler; +import javax.activation.FileDataSource; +import javax.mail.Address; +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.SendFailedException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +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; +import org.apache.tools.ant.Project; + + +/** + * Uses the JavaMail classes to send Mime format email. + * + * @since Ant 1.5 + */ +public class MimeMailer extends Mailer { + private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + + private static final String GENERIC_ERROR = + "Problem while sending mime mail:"; + + /** Default character set */ + private static final String DEFAULT_CHARSET + = System.getProperty("file.encoding"); + + // To work properly with national charsets we have to use + // implementation of interface javax.activation.DataSource + /** + * String data source implementation. + * @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"); + } + if (out != null) { + final String encodedOut = out.toString(charset); + data = (data != null) ? data.concat(encodedOut) : encodedOut; + out = null; + } + return new ByteArrayInputStream(data.getBytes(charset)); + } + + public OutputStream getOutputStream() throws IOException { + out = (out == null) ? new ByteArrayOutputStream() : out; + return out; + } + + public void setContentType(final String type) { + this.type = type.toLowerCase(Locale.ENGLISH); + } + + public String getContentType() { + if (type != null && type.indexOf("charset") > 0 + && type.startsWith("text/")) { + return type; + } + // Must be like "text/plain; charset=windows-1251" + return new StringBuffer(type != null ? type : "text/plain").append( + "; charset=").append(charset).toString(); + } + + public String getName() { + return "StringDataSource"; + } + + public void setCharset(final String charset) { + this.charset = charset; + } + + public String getCharset() { + return charset; + } + } + + /** + * Send the email. + * + * @throws BuildException if the email can't be sent. + */ + public void send() { + try { + final Properties props = new Properties(); + + props.put("mail.smtp.host", host); + props.put("mail.smtp.port", String.valueOf(port)); + + // Aside, the JDK is clearly unaware of the Scottish + // 'session', which involves excessive quantities of + // alcohol :-) + Session sesh; + Authenticator auth = null; + if (SSL) { + try { + final Provider p = (Provider) Class.forName( + "com.sun.net.ssl.internal.ssl.Provider").newInstance(); + Security.addProvider(p); + } catch (final Exception e) { + throw new BuildException("could not instantiate ssl " + + "security provider, check that you have JSSE in " + + "your classpath"); + } + // SMTP provider + props.put("mail.smtp.socketFactory.class", SSL_FACTORY); + props.put("mail.smtp.socketFactory.fallback", "false"); + props.put("mail.smtps.host", host); + if (isPortExplicitlySpecified()) { + props.put("mail.smtps.port", String.valueOf(port)); + props.put("mail.smtp.socketFactory.port", + String.valueOf(port)); + } + } + if (user != null || password != null) { + props.put("mail.smtp.auth", "true"); + auth = new SimpleAuthenticator(user, password); + } + if (isStartTLSEnabled()) { + props.put("mail.smtp.starttls.enable", "true"); + } + sesh = Session.getInstance(props, auth); + + //create the message + final MimeMessage msg = new MimeMessage(sesh); + final MimeMultipart attachments = new MimeMultipart(); + + //set the sender + if (from.getName() == null) { + msg.setFrom(new InternetAddress(from.getAddress())); + } else { + msg.setFrom(new InternetAddress(from.getAddress(), + from.getName())); + } + // set the reply to addresses + msg.setReplyTo(internetAddresses(replyToList)); + msg.setRecipients(Message.RecipientType.TO, + internetAddresses(toList)); + msg.setRecipients(Message.RecipientType.CC, + internetAddresses(ccList)); + msg.setRecipients(Message.RecipientType.BCC, + internetAddresses(bccList)); + + // 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); + } else { + // Next: looking if charset having explicit definition + charset = message.getCharset(); + if (charset == null) { + // Using default + charset = DEFAULT_CHARSET; + message.setCharset(charset); + } + } + // Using javax.activation.DataSource paradigm + final StringDataSource sds = new StringDataSource(); + sds.setContentType(message.getMimeType()); + sds.setCharset(charset); + + if (subject != null) { + msg.setSubject(subject, charset); + } + msg.addHeader("Date", getDate()); + + if (headers != null) { + for (final Iterator iter = headers.iterator(); iter.hasNext();) { + final Header h = (Header) iter.next(); + msg.addHeader(h.getName(), h.getValue()); + } + } + final PrintStream out = new PrintStream(sds.getOutputStream()); + message.print(out); + out.close(); + + final MimeBodyPart textbody = new MimeBodyPart(); + textbody.setDataHandler(new DataHandler(sds)); + attachments.addBodyPart(textbody); + + final Enumeration e = files.elements(); + + while (e.hasMoreElements()) { + final File file = (File) e.nextElement(); + + MimeBodyPart body; + + body = new MimeBodyPart(); + if (!file.exists() || !file.canRead()) { + throw new BuildException("File \"" + file.getAbsolutePath() + + "\" does not exist or is not " + + "readable."); + } + final FileDataSource fileData = new FileDataSource(file); + final DataHandler fileDataHandler = new DataHandler(fileData); + + body.setDataHandler(fileDataHandler); + body.setFileName(file.getName()); + attachments.addBodyPart(body); + } + msg.setContent(attachments); + try { + // Send the message using SMTP, or SMTPS if the host uses SSL + final Transport transport = sesh.getTransport(SSL ? "smtps" : "smtp"); + transport.connect(host, user, password); + transport.sendMessage(msg, msg.getAllRecipients()); + } catch (final SendFailedException sfe) { + if (!shouldIgnoreInvalidRecipients()) { + throw new BuildException(GENERIC_ERROR, sfe); + } else if (sfe.getValidSentAddresses() == null + || sfe.getValidSentAddresses().length == 0) { + throw new BuildException("Couldn't reach any recipient", + sfe); + } else { + Address[] invalid = sfe.getInvalidAddresses(); + if (invalid == null) { + invalid = new Address[0]; + } + for (int i = 0; i < invalid.length; i++) { + didntReach(invalid[i], "invalid", sfe); + } + Address[] validUnsent = sfe.getValidUnsentAddresses(); + if (validUnsent == null) { + validUnsent = new Address[0]; + } + for (int i = 0; i < validUnsent.length; i++) { + didntReach(validUnsent[i], "valid", sfe); + } + } + } + } catch (final MessagingException e) { + throw new BuildException(GENERIC_ERROR, e); + } catch (final IOException e) { + throw new BuildException(GENERIC_ERROR, e); + } + } + + private static InternetAddress[] internetAddresses(final Vector list) + throws AddressException, UnsupportedEncodingException { + final int size = list.size(); + final InternetAddress[] addrs = new InternetAddress[size]; + + for (int i = 0; i < size; ++i) { + final EmailAddress addr = (EmailAddress) list.elementAt(i); + + final String name = addr.getName(); + addrs[i] = (name == null) + ? new InternetAddress(addr.getAddress()) + : new InternetAddress(addr.getAddress(), name); + } + return addrs; + } + + private String parseCharSetFromMimeType(final String type) { + if (type == null) { + return null; + } + final int pos = type.indexOf("charset"); + if (pos < 0) { + return null; + } + // Assuming mime type in form "text/XXXX; charset=XXXXXX" + final StringTokenizer token = new StringTokenizer(type.substring(pos), "=; "); + token.nextToken(); // Skip 'charset=' + return token.nextToken(); + } + + private void didntReach(final Address addr, final String category, + final MessagingException ex) { + final String msg = "Failed to send mail to " + category + " address " + + addr + " because of " + ex.getMessage(); + if (task != null) { + task.log(msg, Project.MSG_WARN); + } else { + System.err.println(msg); + } + } + + static class SimpleAuthenticator extends Authenticator { + private String user = null; + private String password = null; + public SimpleAuthenticator(final String user, final String password) { + this.user = user; + this.password = password; + } + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(user, password); + } + } +} + |