You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jl...@apache.org on 2020/10/07 15:58:41 UTC
svn commit: r1882306 [14/17] - in
/geronimo/javamail/trunk/geronimo-javamail_1.6: ./
geronimo-javamail_1.6_mail/ geronimo-javamail_1.6_mail/src/
geronimo-javamail_1.6_mail/src/site/ geronimo-javamail_1.6_provider/
geronimo-javamail_1.6_provider/src/ ge...
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPMessage.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPMessage.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPMessage.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPMessage.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,237 @@
+/*
+ * 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.geronimo.javamail.transport.smtp;
+
+import java.io.InputStream;
+
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+
+public class SMTPMessage extends MimeMessage {
+
+ // never notify
+ public static final int NOTIFY_NEVER = -1;
+
+ // notify of successful deliveries.
+ public static final int NOTIFY_SUCCESS = 1;
+
+ // notify of delivery failures.
+ public static final int NOTIFY_FAILURE = 2;
+
+ // notify of delivery delays
+ public static final int NOTIFY_DELAY = 4;
+
+ // return full message with status notifications
+ public static final int RETURN_FULL = 1;
+
+ // return only message headers with status notifications
+ public static final int RETURN_HDRS = 2;
+
+ // support 8BitMime encodings
+ protected boolean allow8bitMIME = false;
+
+ // a from address specified in the message envelope. Overrides other from
+ // sources.
+ protected String envelopeFrom = null;
+
+ // an option string to append to the MAIL command on sending.
+ protected String mailExtension = null;
+
+ // SMTP mail notification options if DSN is supported.
+ protected int notifyOptions = 0;
+
+ // DSN return option notification values.
+ protected int returnOption = 0;
+
+ // allow sending if some addresses give errors.
+ protected boolean sendPartial = false;
+
+ // an RFC 2554 AUTH= value.
+ protected String submitter = null;
+
+ /**
+ * Default (and normal) constructor for an SMTPMessage.
+ *
+ * @param session
+ * The hosting Javamail Session.
+ */
+ public SMTPMessage(Session session) {
+ // this is a simple one.
+ super(session);
+ }
+
+ /**
+ * Construct an SMTPMessage instance by reading and parsing the data from
+ * the provided InputStream. The InputStream will be left positioned at the
+ * end of the message data on constructor completion.
+ *
+ * @param session
+ * The hosting Javamail Session.
+ */
+ public SMTPMessage(Session session, InputStream source) throws MessagingException {
+ // this is a simple one.
+ super(session, source);
+ }
+
+ /**
+ * Construct an SMTPMimeMessage from another source MimeMessage object. The
+ * new object and the old object are independent of each other.
+ *
+ * @param source
+ * The source MimeMessage object.
+ */
+ public SMTPMessage(MimeMessage source) throws MessagingException {
+ super(source);
+ }
+
+ /**
+ * Change the allow8BitMime attribute for the message.
+ *
+ * @param a
+ * The new setting.
+ */
+ public void setAllow8bitMIME(boolean a) {
+ allow8bitMIME = a;
+ }
+
+ /**
+ * Retrieve the current 8bitMIME attribute.
+ *
+ * @return The current attribute value.
+ */
+ public boolean getAllow8bitMIME() {
+ return allow8bitMIME;
+ }
+
+ /**
+ * Change the envelopeFrom attribute for the message.
+ *
+ * @param from
+ * The new setting.
+ */
+ public void setEnvelopeFrom(String from) {
+ envelopeFrom = from;
+ }
+
+ /**
+ * Retrieve the current evelopeFrom attribute.
+ *
+ * @return The current attribute value.
+ */
+ public String getEnvelopeFrom() {
+ return envelopeFrom;
+ }
+
+ /**
+ * Change the mailExtension attribute for the message.
+ *
+ * @param e
+ * The new setting.
+ */
+ public void setMailExtension(String e) {
+ mailExtension = e;
+ }
+
+ /**
+ * Retrieve the current mailExtension attribute.
+ *
+ * @return The current attribute value.
+ */
+ public String getMailExtension() {
+ return mailExtension;
+ }
+
+ /**
+ * Change the notifyOptions attribute for the message.
+ *
+ * @param options
+ * The new setting.
+ */
+ public void setNotifyOptions(int options) {
+ notifyOptions = options;
+ }
+
+ /**
+ * Retrieve the current notifyOptions attribute.
+ *
+ * @return The current attribute value.
+ */
+ public int getNotifyOptions() {
+ return notifyOptions;
+ }
+
+ /**
+ * Change the returnOptions attribute for the message.
+ *
+ * @param option
+ * The new setting.
+ */
+ public void setReturnOption(int option) {
+ returnOption = option;
+ }
+
+ /**
+ * Retrieve the current returnOption attribute.
+ *
+ * @return The current attribute value.
+ */
+ public int getReturnOption() {
+ return returnOption;
+ }
+
+ /**
+ * Change the sendPartial attribute for the message.
+ *
+ * @param a
+ * The new setting.
+ */
+ public void setSendPartial(boolean a) {
+ sendPartial = a;
+ }
+
+ /**
+ * Retrieve the current sendPartial attribute.
+ *
+ * @return The current attribute value.
+ */
+ public boolean getSendPartial() {
+ return sendPartial;
+ }
+
+ /**
+ * Change the submitter attribute for the message.
+ *
+ * @param s
+ * The new setting.
+ */
+ public void setSubmitter(String s) {
+ submitter = s;
+ }
+
+ /**
+ * Retrieve the current submitter attribute.
+ *
+ * @return The current attribute value.
+ */
+ public String getSubmitter() {
+ return submitter;
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPReply.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPReply.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPReply.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPReply.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,208 @@
+/*
+ * 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.geronimo.javamail.transport.smtp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Util class to represent a reply from a SMTP server
+ *
+ * @version $Rev$ $Date$
+ */
+class SMTPReply {
+ // SMTP reply codes
+ public static final int SERVICE_READY = 220;
+
+ public static final int SERVICE_CLOSING = 221;
+
+ public static final int AUTHENTICATION_COMPLETE = 235;
+
+ public static final int COMMAND_ACCEPTED = 250;
+
+ public static final int ADDRESS_NOT_LOCAL = 251;
+
+ public static final int AUTHENTICATION_CHALLENGE = 334;
+
+ public static final int START_MAIL_INPUT = 354;
+
+ public static final int SERVICE_NOT_AVAILABLE = 421;
+
+ public static final int MAILBOX_BUSY = 450;
+
+ public static final int PROCESSING_ERROR = 451;
+
+ public static final int INSUFFICIENT_STORAGE = 452;
+
+ public static final int COMMAND_SYNTAX_ERROR = 500;
+
+ public static final int PARAMETER_SYNTAX_ERROR = 501;
+
+ public static final int COMMAND_NOT_IMPLEMENTED = 502;
+
+ public static final int INVALID_COMMAND_SEQUENCE = 503;
+
+ public static final int COMMAND_PARAMETER_NOT_IMPLEMENTED = 504;
+
+ public static final int MAILBOX_NOT_FOUND = 550;
+
+ public static final int USER_NOT_LOCAL = 551;
+
+ public static final int MAILBOX_FULL = 552;
+
+ public static final int INVALID_MAILBOX = 553;
+
+ public static final int TRANSACTION_FAILED = 553;
+
+ // The original reply string
+ private final String reply;
+
+ // returned message code
+ private final int code;
+
+ // the returned message text
+ private final String message;
+
+ // additional returned lines from a continued response
+ private List lines;
+
+ // indicates that this is a continuation response
+ private boolean continued;
+
+ SMTPReply(String s) throws MalformedSMTPReplyException {
+ // save the reply
+ reply = s;
+
+ // In a normal response, the first 3 must be the return code. However,
+ // the response back from a QUIT command is frequently a null string.
+ // Therefore, if the result is
+ // too short, just default the code to -1 and use the entire text for
+ // the message.
+ if (s == null || s.length() < 3) {
+ code = -1;
+ message = s;
+ return;
+ }
+
+ try {
+ continued = false;
+ code = Integer.parseInt(s.substring(0, 3));
+
+ // message should be separated by a space OR a continuation
+ // character if this is a
+ // multi-line response.
+ if (s.length() > 4) {
+ //
+ if (s.charAt(3) == '-') {
+ continued = true;
+ }
+ message = s.substring(4);
+ } else {
+ message = "";
+ }
+ } catch (NumberFormatException e) {
+ throw new MalformedSMTPReplyException("error in parsing code", e);
+ }
+ }
+
+ /**
+ * Add a line to a continued response. This will
+ * update the continued status if the end of the
+ * response is reached.
+ *
+ * @param line The line to add.
+ */
+ public void addLine(String line) {
+ if (lines == null) {
+ lines = new ArrayList();
+ lines.add(message);
+ }
+ // mark if we're still continued
+ continued = line.charAt(3) == '-';
+ // add the line to the list
+ lines.add(line.substring(4));
+ }
+
+ /**
+ * Get the list of all of the lines associated with
+ * this reply.
+ *
+ * @return A List containing all lines associated with this
+ * reply.
+ */
+ public List getLines() {
+ if (lines == null) {
+ lines = new ArrayList();
+ lines.add(message);
+ }
+ return lines;
+ }
+
+
+ /**
+ * Return the code value associated with the reply.
+ *
+ * @return The integer code associated with the reply.
+ */
+ public int getCode() {
+ return this.code;
+ }
+
+ /**
+ * Get the message text associated with the reply.
+ *
+ * @return The string value of the message from the reply.
+ */
+ public String getMessage() {
+ return this.message;
+ }
+
+ /**
+ * Retrieve the raw reply string for the reponse.
+ *
+ * @return The original reply string from the server.
+ */
+ public String getReply() {
+ return reply;
+ }
+
+ /**
+ * Indicates if reply is an error condition
+ */
+ boolean isError() {
+ // error codes are all above 400
+ return code >= 400;
+ }
+
+ /**
+ * Indicates whether this response is flagged as part of a multiple line
+ * response.
+ *
+ * @return true if the response has multiple lines, false if this is the
+ * last line of the response.
+ */
+ public boolean isContinued() {
+ return continued;
+ }
+
+ public String toString() {
+ return "CODE = " + getCode() + " : MSG = " + getMessage();
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSTransport.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSTransport.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSTransport.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSTransport.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,33 @@
+/*
+ * 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.geronimo.javamail.transport.smtp;
+
+import javax.mail.Session;
+import javax.mail.URLName;
+
+public class SMTPSTransport extends SMTPTransport {
+ /**
+ * @param session
+ * @param name
+ */
+ public SMTPSTransport(Session session, URLName name) {
+ super(session, name, "smtps", 465, true);
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSendFailedException.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSendFailedException.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSendFailedException.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPSendFailedException.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,75 @@
+/*
+ * 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.geronimo.javamail.transport.smtp;
+
+import javax.mail.Address;
+import javax.mail.SendFailedException;
+
+public class SMTPSendFailedException extends SendFailedException {
+ // the failing command
+ protected String cmd;
+
+ // the error code for the failure
+ protected int rc;
+
+ /**
+ * Constructor for an SMTPSendFaileException.
+ *
+ * @param cmd
+ * The failing command string.
+ * @param rc
+ * The error code for the failing command.
+ * @param err
+ * An error message for the exception.
+ * @param ex
+ * Any associated nested exception.
+ * @param vs
+ * An array of valid, sent addresses.
+ * @param vus
+ * An array of addresses that were valid, but were unsent.
+ * @param inv
+ * An array of addresses deemed invalid.
+ */
+ SMTPSendFailedException(
+ String cmd, int rc, String err, Exception ex, Address[] vs,
+ Address[] vus, Address[] inv) {
+ super(err, ex, vs, vus, inv);
+ this.cmd = cmd;
+ this.rc = rc;
+ }
+
+ /**
+ * Get the failing command string for the exception.
+ *
+ * @return The string value of the failing command.
+ */
+ public String getCommand() {
+ return cmd;
+ }
+
+ /**
+ * The failing command return code.
+ *
+ * @return The failure return code.
+ */
+ public int getReturnCode() {
+ return rc;
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,656 @@
+/*
+ * 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.geronimo.javamail.transport.smtp;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.Socket;
+import java.util.ArrayList;
+
+import javax.mail.Address;
+import javax.mail.AuthenticationFailedException;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.URLName;
+import javax.mail.event.TransportEvent;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimePart;
+
+import org.apache.geronimo.javamail.util.ProtocolProperties;
+import org.apache.geronimo.javamail.transport.smtp.SMTPConnection.SendStatus;
+
+/**
+ * Simple implementation of SMTP transport. Just does plain RFC821-ish delivery.
+ * <p/> Supported properties : <p/>
+ * <ul>
+ * <li> mail.host : to set the server to deliver to. Default = localhost</li>
+ * <li> mail.smtp.port : to set the port. Default = 25</li>
+ * <li> mail.smtp.locahost : name to use for HELO/EHLO - default getHostName()</li>
+ * </ul>
+ * <p/> There is no way to indicate failure for a given recipient (it's possible
+ * to have a recipient address rejected). The sun impl throws exceptions even if
+ * others successful), but maybe we do a different way... <p/> TODO : lots.
+ * ESMTP, user/pass, indicate failure, etc...
+ *
+ * @version $Rev$ $Date$
+ */
+public class SMTPTransport extends Transport {
+ /**
+ * property keys for protocol properties. The actual property name will be
+ * appended with "mail." + protocol + ".", where the protocol is either
+ * "smtp" or "smtps".
+ */
+ protected static final String MAIL_SMTP_DSN_NOTIFY = "dsn.notify";
+ protected static final String MAIL_SMTP_SENDPARTIAL = "sendpartial";
+ protected static final String MAIL_SMTP_EXTENSION = "mailextension";
+ protected static final String DEFAULT_MAIL_HOST = "localhost";
+
+ protected static final int DEFAULT_MAIL_SMTP_PORT = 25;
+ protected static final int DEFAULT_MAIL_SMTPS_PORT = 465;
+
+
+ // do we use SSL for our initial connection?
+ protected boolean sslConnection = false;
+
+ // our accessor for protocol properties and the holder of
+ // protocol-specific information
+ protected ProtocolProperties props;
+ // our active connection object
+ protected SMTPConnection connection;
+
+ // the last response line received from the server.
+ protected SMTPReply lastServerResponse = null;
+
+ /**
+ * Normal constructor for an SMTPTransport() object. This constructor is
+ * used to build a transport instance for the "smtp" protocol.
+ *
+ * @param session
+ * The attached session.
+ * @param name
+ * An optional URLName object containing target information.
+ */
+ public SMTPTransport(Session session, URLName name) {
+ this(session, name, "smtp", DEFAULT_MAIL_SMTP_PORT, false);
+ }
+
+
+ /**
+ * Common constructor used by the SMTPTransport and SMTPSTransport classes
+ * to do common initialization of defaults.
+ *
+ * @param session
+ * The host session instance.
+ * @param name
+ * The URLName of the target.
+ * @param protocol
+ * The protocol type (either "smtp" or "smtps". This helps us in
+ * retrieving protocol-specific session properties.
+ * @param defaultPort
+ * The default port used by this protocol. For "smtp", this will
+ * be 25. The default for "smtps" is 465.
+ * @param sslConnection
+ * Indicates whether an SSL connection should be used to initial
+ * contact the server. This is different from the STARTTLS
+ * support, which switches the connection to SSL after the
+ * initial startup.
+ */
+ protected SMTPTransport(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection) {
+ super(session, name);
+
+ // create the protocol property holder. This gives an abstraction over the different
+ // flavors of the protocol.
+ props = new ProtocolProperties(session, protocol, sslConnection, defaultPort);
+ // the connection manages connection for the transport
+ connection = new SMTPConnection(props);
+ }
+
+
+ /**
+ * Connect to a server using an already created socket. This connection is
+ * just like any other connection, except we will not create a new socket.
+ *
+ * @param socket
+ * The socket connection to use.
+ */
+ public void connect(Socket socket) throws MessagingException {
+ connection.connect(socket);
+ super.connect();
+ }
+
+
+ /**
+ * Do the protocol connection for an SMTP transport. This handles server
+ * authentication, if possible. Returns false if unable to connect to the
+ * server.
+ *
+ * @param host
+ * The target host name.
+ * @param port
+ * The server port number.
+ * @param user
+ * The authentication user (if any).
+ * @param password
+ * The server password. Might not be sent directly if more
+ * sophisticated authentication is used.
+ *
+ * @return true if we were able to connect to the server properly, false for
+ * any failures.
+ * @exception MessagingException
+ */
+ protected boolean protocolConnect(String host, int port, String username, String password)
+ throws MessagingException {
+ // the connection pool handles all of the details here.
+ return connection.protocolConnect(host, port, username, password);
+ }
+
+ /**
+ * Send a message to multiple addressees.
+ *
+ * @param message
+ * The message we're sending.
+ * @param addresses
+ * An array of addresses to send to.
+ *
+ * @exception MessagingException
+ */
+ public void sendMessage(Message message, Address[] addresses) throws MessagingException {
+ if (!isConnected()) {
+ throw new IllegalStateException("Not connected");
+ }
+ // don't bother me w/ null messages or no addreses
+ if (message == null) {
+ throw new MessagingException("Null message");
+ }
+
+ // SMTP only handles instances of MimeMessage, not the more general
+ // message case.
+ if (!(message instanceof MimeMessage)) {
+ throw new MessagingException("SMTP can only send MimeMessages");
+ }
+
+ // we must have a message list.
+ if (addresses == null || addresses.length == 0) {
+ throw new MessagingException("Null or empty address array");
+ }
+
+ boolean reportSuccess = getReportSuccess();
+
+ // now see how we're configured for this send operation.
+ boolean partialSends = false;
+
+ // this can be attached directly to the message.
+ if (message instanceof SMTPMessage) {
+ partialSends = ((SMTPMessage) message).getSendPartial();
+ }
+
+ // if still false on the message object, check for a property
+ // version also
+ if (!partialSends) {
+ partialSends = props.getBooleanProperty(MAIL_SMTP_SENDPARTIAL, false);
+ }
+
+ boolean haveGroup = false;
+
+ // enforce the requirement that all of the targets are InternetAddress
+ // instances.
+ for (int i = 0; i < addresses.length; i++) {
+ if (addresses[i] instanceof InternetAddress) {
+ // and while we're here, see if we have a groups in the address
+ // list. If we do, then
+ // we're going to need to expand these before sending.
+ if (((InternetAddress) addresses[i]).isGroup()) {
+ haveGroup = true;
+ }
+ } else {
+ throw new MessagingException("Illegal InternetAddress " + addresses[i]);
+ }
+ }
+
+ // did we find a group? Time to expand this into our full target list.
+ if (haveGroup) {
+ addresses = expandGroups(addresses);
+ }
+
+ SendStatus[] stats = new SendStatus[addresses.length];
+
+ // create our lists for notification and exception reporting.
+ Address[] sent = null;
+ Address[] unsent = null;
+ Address[] invalid = null;
+
+ try {
+ // send sender first. If this failed, send a failure notice of the
+ // event, using the full list of
+ // addresses as the unsent, and nothing for the rest.
+ if (!connection.sendMailFrom(message)) {
+ unsent = addresses;
+ sent = new Address[0];
+ invalid = new Address[0];
+ // notify of the error.
+ notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent, invalid, message);
+
+ // include the reponse information here.
+ SMTPReply last = connection.getLastServerResponse();
+ // now send an "uber-exception" to indicate the failure.
+ throw new SMTPSendFailedException("MAIL FROM", last.getCode(), last.getMessage(), null, sent, unsent,
+ invalid);
+ }
+
+ // get the additional notification status, if available
+ String dsn = getDeliveryStatusNotification(message);
+
+ // we need to know about any failures once we've gone through the
+ // complete list, so keep a
+ // failure flag.
+ boolean sendFailure = false;
+
+ // event notifcation requires we send lists of successes and
+ // failures broken down by category.
+ // The categories are:
+ //
+ // 1) addresses successfully processed.
+ // 2) addresses deemed valid, but had a processing failure that
+ // prevented sending.
+ // 3) addressed deemed invalid (basically all other processing
+ // failures).
+ ArrayList sentAddresses = new ArrayList();
+ ArrayList unsentAddresses = new ArrayList();
+ ArrayList invalidAddresses = new ArrayList();
+
+ // Now we add a MAIL TO record for each recipient. At this point, we
+ // just collect
+ for (int i = 0; i < addresses.length; i++) {
+ InternetAddress target = (InternetAddress) addresses[i];
+
+ // write out the record now.
+ SendStatus status = connection.sendRcptTo(target, dsn);
+ stats[i] = status;
+
+ switch (status.getStatus()) {
+ // successfully sent
+ case SendStatus.SUCCESS:
+ sentAddresses.add(target);
+ break;
+
+ // we have an invalid address of some sort, or a general sending
+ // error (which we'll
+ // interpret as due to an invalid address.
+ case SendStatus.INVALID_ADDRESS:
+ case SendStatus.GENERAL_ERROR:
+ sendFailure = true;
+ invalidAddresses.add(target);
+ break;
+
+ // good address, but this was a send failure.
+ case SendStatus.SEND_FAILURE:
+ sendFailure = true;
+ unsentAddresses.add(target);
+ break;
+ }
+ }
+
+ // if we had a send failure, then we need to check if we allow
+ // partial sends. If not allowed,
+ // we abort the send operation now.
+ if (sendFailure) {
+ // if we're not allowing partial successes or we've failed on
+ // all of the addresses, it's
+ // time to abort.
+ if (!partialSends || sentAddresses.isEmpty()) {
+ // we send along the valid and invalid address lists on the
+ // notifications and
+ // exceptions.
+ // however, since we're aborting the entire send, the
+ // successes need to become
+ // members of the failure list.
+ unsentAddresses.addAll(sentAddresses);
+
+ // this one is empty.
+ sent = new Address[0];
+ unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
+ invalid = (Address[]) invalidAddresses.toArray(new Address[0]);
+
+ // go reset our connection so we can process additional
+ // sends.
+ connection.resetConnection();
+
+ // get a list of chained exceptions for all of the failures.
+ MessagingException failures = generateExceptionChain(stats, false);
+
+ // now send an "uber-exception" to indicate the failure.
+ throw new SMTPSendFailedException("MAIL TO", 0, "Invalid Address", failures, sent, unsent, invalid);
+ }
+ }
+
+ try {
+ // try to send the data
+ connection.sendData((MimeMessage)message);
+ } catch (MessagingException e) {
+ // If there's an error at this point, this is a complete
+ // delivery failure.
+ // we send along the valid and invalid address lists on the
+ // notifications and
+ // exceptions.
+ // however, since we're aborting the entire send, the successes
+ // need to become
+ // members of the failure list.
+ unsentAddresses.addAll(sentAddresses);
+
+ // this one is empty.
+ sent = new Address[0];
+ unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
+ invalid = (Address[]) invalidAddresses.toArray(new Address[0]);
+ // notify of the error.
+ notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent, invalid, message);
+ // send a send failure exception.
+ throw new SMTPSendFailedException("DATA", 0, "Send failure", e, sent, unsent, invalid);
+ }
+
+ // create our lists for notification and exception reporting from
+ // this point on.
+ sent = (Address[]) sentAddresses.toArray(new Address[0]);
+ unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
+ invalid = (Address[]) invalidAddresses.toArray(new Address[0]);
+
+ // if sendFailure is true, we had an error during the address phase,
+ // but we had permission to
+ // process this as a partial send operation. Now that the data has
+ // been sent ok, it's time to
+ // report the partial failure.
+ if (sendFailure) {
+ // notify our listeners of the partial delivery.
+ notifyTransportListeners(TransportEvent.MESSAGE_PARTIALLY_DELIVERED, sent, unsent, invalid, message);
+
+ // get a list of chained exceptions for all of the failures (and
+ // the successes, if reportSuccess has been
+ // turned on).
+ MessagingException failures = generateExceptionChain(stats, reportSuccess);
+
+ // now send an "uber-exception" to indicate the failure.
+ throw new SMTPSendFailedException("MAIL TO", 0, "Invalid Address", failures, sent, unsent, invalid);
+ }
+
+ // notify our listeners of successful delivery.
+ notifyTransportListeners(TransportEvent.MESSAGE_DELIVERED, sent, unsent, invalid, message);
+
+ // we've not had any failures, but we've been asked to report
+ // success as an exception. Do
+ // this now.
+ if (reportSuccess) {
+ // generate the chain of success exceptions (we already know
+ // there are no failure ones to report).
+ MessagingException successes = generateExceptionChain(stats, reportSuccess);
+ if (successes != null) {
+ throw successes;
+ }
+ }
+ } catch (SMTPSendFailedException e) {
+ // if this is a send failure, we've already handled
+ // notifications....just rethrow it.
+ throw e;
+ } catch (MessagingException e) {
+ // notify of the error.
+ notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent, invalid, message);
+ throw e;
+ }
+ }
+
+
+ /**
+ * Determine what delivery status notification should
+ * be added to the RCPT TO: command.
+ *
+ * @param message The message we're sending.
+ *
+ * @return The string NOTIFY= value to add to the command.
+ */
+ protected String getDeliveryStatusNotification(Message message) {
+ String dsn = null;
+
+ // there's an optional notification argument that can be added to
+ // MAIL TO. See if we've been
+ // provided with one.
+
+ // an SMTPMessage object is the first source
+ if (message instanceof SMTPMessage) {
+ // get the notification options
+ int options = ((SMTPMessage) message).getNotifyOptions();
+
+ switch (options) {
+ // a zero value indicates nothing is set.
+ case 0:
+ break;
+
+ case SMTPMessage.NOTIFY_NEVER:
+ dsn = "NEVER";
+ break;
+
+ case SMTPMessage.NOTIFY_SUCCESS:
+ dsn = "SUCCESS";
+ break;
+
+ case SMTPMessage.NOTIFY_FAILURE:
+ dsn = "FAILURE";
+ break;
+
+ case SMTPMessage.NOTIFY_DELAY:
+ dsn = "DELAY";
+ break;
+
+ // now for combinations...there are few enough combinations here
+ // that we can just handle this in the switch statement rather
+ // than have to
+ // concatentate everything together.
+ case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_FAILURE):
+ dsn = "SUCCESS,FAILURE";
+ break;
+
+ case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_DELAY):
+ dsn = "SUCCESS,DELAY";
+ break;
+
+ case (SMTPMessage.NOTIFY_FAILURE + SMTPMessage.NOTIFY_DELAY):
+ dsn = "FAILURE,DELAY";
+ break;
+
+ case (SMTPMessage.NOTIFY_SUCCESS + SMTPMessage.NOTIFY_FAILURE + SMTPMessage.NOTIFY_DELAY):
+ dsn = "SUCCESS,FAILURE,DELAY";
+ break;
+ }
+ }
+
+ // if still null, grab a property value (yada, yada, yada...)
+ if (dsn == null) {
+ dsn = props.getProperty(MAIL_SMTP_DSN_NOTIFY);
+ }
+ return dsn;
+ }
+
+
+
+ /**
+ * Close the connection. On completion, we'll be disconnected from the
+ * server and unable to send more data.
+ *
+ * @exception MessagingException
+ */
+ public void close() throws MessagingException {
+ // This is done to ensure proper event notification.
+ super.close();
+ // NB: We reuse the connection if asked to reconnect
+ connection.close();
+ }
+
+
+ /**
+ * Turn a series of send status items into a chain of exceptions indicating
+ * the state of each send operation.
+ *
+ * @param stats
+ * The list of SendStatus items.
+ * @param reportSuccess
+ * Indicates whether we should include the report success items.
+ *
+ * @return The head of a chained list of MessagingExceptions.
+ */
+ protected MessagingException generateExceptionChain(SendStatus[] stats, boolean reportSuccess) {
+ MessagingException current = null;
+
+ for (int i = 0; i < stats.length; i++) {
+ SendStatus status = stats[i];
+
+ if (status != null) {
+ MessagingException nextException = stats[i].getException(reportSuccess);
+ // if there's an exception associated with this status, chain it
+ // up with the rest.
+ if (nextException != null) {
+ if (current == null) {
+ current = nextException;
+ } else {
+ current.setNextException(nextException);
+ current = nextException;
+ }
+ }
+ }
+ }
+ return current;
+ }
+
+ /**
+ * Expand the address list by converting any group addresses into single
+ * address targets.
+ *
+ * @param addresses
+ * The input array of addresses.
+ *
+ * @return The expanded array of addresses.
+ * @exception MessagingException
+ */
+ protected Address[] expandGroups(Address[] addresses) throws MessagingException {
+ ArrayList expandedAddresses = new ArrayList();
+
+ // run the list looking for group addresses, and add the full group list
+ // to our targets.
+ for (int i = 0; i < addresses.length; i++) {
+ InternetAddress address = (InternetAddress) addresses[i];
+ // not a group? Just copy over to the other list.
+ if (!address.isGroup()) {
+ expandedAddresses.add(address);
+ } else {
+ // get the group address and copy each member of the group into
+ // the expanded list.
+ InternetAddress[] groupAddresses = address.getGroup(true);
+ for (int j = 1; j < groupAddresses.length; j++) {
+ expandedAddresses.add(groupAddresses[j]);
+ }
+ }
+ }
+
+ // convert back into an array.
+ return (Address[]) expandedAddresses.toArray(new Address[0]);
+ }
+
+
+ /**
+ * Retrieve the local client host name.
+ *
+ * @return The string version of the local host name.
+ * @exception SMTPTransportException
+ */
+ public String getLocalHost() throws MessagingException {
+ return connection.getLocalHost();
+ }
+
+
+ /**
+ * Explicitly set the local host information.
+ *
+ * @param localHost
+ * The new localHost name.
+ */
+ public void setLocalHost(String localHost) {
+ connection.setLocalHost(localHost);
+ }
+
+
+ /**
+ * Return the current reportSuccess property.
+ *
+ * @return The current reportSuccess property.
+ */
+ public boolean getReportSuccess() {
+ return connection.getReportSuccess();
+ }
+
+ /**
+ * Set a new value for the reportSuccess property.
+ *
+ * @param report
+ * The new setting.
+ */
+ public void setReportSuccess(boolean report) {
+ connection.setReportSuccess(report);
+ }
+
+ /**
+ * Return the current startTLS property.
+ *
+ * @return The current startTLS property.
+ */
+ public boolean getStartTLS() {
+ return connection.getStartTLS();
+ }
+
+ /**
+ * Set a new value for the startTLS property.
+ *
+ * @param start
+ * The new setting.
+ */
+ public void setStartTLS(boolean start) {
+ connection.setStartTLS(start);
+ }
+
+ /**
+ * Retrieve the SASL realm used for DIGEST-MD5 authentication. This will
+ * either be explicitly set, or retrieved using the mail.smtp.sasl.realm
+ * session property.
+ *
+ * @return The current realm information (which can be null).
+ */
+ public String getSASLRealm() {
+ return connection.getSASLRealm();
+ }
+
+ /**
+ * Explicitly set the SASL realm used for DIGEST-MD5 authenticaiton.
+ *
+ * @param name
+ * The new realm name.
+ */
+ public void setSASLRealm(String name) {
+ connection.setSASLRealm(name);
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransportException.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransportException.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransportException.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransportException.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,44 @@
+/*
+ * 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.geronimo.javamail.transport.smtp;
+
+/**
+ * General purpose Exception
+ *
+ * @version $Id$
+ */
+class SMTPTransportException extends Exception {
+
+ SMTPTransportException() {
+ super();
+ }
+
+ SMTPTransportException(String s) {
+ super(s);
+ }
+
+ SMTPTransportException(String s, Exception t) {
+ super(s, t);
+ }
+
+ SMTPTransportException(Exception t) {
+ super("SMTP Transport error", t);
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CommandFailedException.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CommandFailedException.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CommandFailedException.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CommandFailedException.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,35 @@
+/**
+ * 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.geronimo.javamail.util;
+
+import javax.mail.MessagingException;
+
+public class CommandFailedException extends MessagingException {
+ public CommandFailedException() {
+ super();
+ }
+
+ public CommandFailedException(String message) {
+ super(message);
+ }
+
+ public CommandFailedException(String message, Exception cause) {
+ super(message, cause);
+ }
+}
+
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ConnectionException.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ConnectionException.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ConnectionException.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/ConnectionException.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,35 @@
+/**
+ * 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.geronimo.javamail.util;
+
+import javax.mail.MessagingException;
+
+public class ConnectionException extends MessagingException {
+ public ConnectionException() {
+ super();
+ }
+
+ public ConnectionException(String message) {
+ super(message);
+ }
+
+ public ConnectionException(String message, Exception cause) {
+ super(message, cause);
+ }
+}
+
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CountingOutputStream.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CountingOutputStream.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CountingOutputStream.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/CountingOutputStream.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,60 @@
+/*
+ * 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.geronimo.javamail.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An implementation of an OutputStream just counts
+ * the number of bytes written to the stream.
+ * @version $Rev$ $Date$
+ */
+public class CountingOutputStream extends OutputStream {
+ // the counting accumulator
+ int count = 0;
+
+ // in order for this to work, we only need override the single character
+ // form, as the others
+ // funnel through this one by default.
+ public void write(int ch) throws IOException {
+ // just increment the count
+ count++;
+ }
+
+
+ /**
+ * Get the current accumulator total for this stream.
+ *
+ * @return The current count.
+ */
+ public int getCount() {
+ return count;
+ }
+
+
+ /**
+ * Reset the counter to zero.
+ */
+ public void reset() {
+ count = 0;
+ }
+}
+
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/InvalidCommandException.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/InvalidCommandException.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/InvalidCommandException.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/InvalidCommandException.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,35 @@
+/**
+ * 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.geronimo.javamail.util;
+
+import javax.mail.MessagingException;
+
+public class InvalidCommandException extends MessagingException {
+ public InvalidCommandException() {
+ super();
+ }
+
+ public InvalidCommandException(String message) {
+ super(message);
+ }
+
+ public InvalidCommandException(String message, Exception cause) {
+ super(message, cause);
+ }
+}
+
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,140 @@
+/*
+ * 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.geronimo.javamail.util;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * An implementation of an OutputStream that performs MIME linebreak
+ * canonicalization and "byte-stuff" so that data content does not get mistaken
+ * for a message data-end marker (CRLF.CRLF)l
+ *
+ * @version $Rev$ $Date$
+ */
+public class MIMEInputReader extends Reader {
+
+ // the wrappered output stream.
+ protected Reader source;
+
+ // a flag to indicate we've just processed a line break. This is used for
+ // byte stuffing purposes. This
+ // is initially true, because if the first character of the content is a
+ // period, we need to byte-stuff
+ // immediately.
+ protected boolean atLineBreak = true;
+ // we've hit the terminating marker on the data
+ protected boolean endOfData = false;
+
+
+ /**
+ * Create an input reader that reads from the source input reader
+ *
+ * @param out
+ * The wrapped Reader
+ */
+ public MIMEInputReader(Reader source) {
+ this.source = source;
+ }
+
+ /**
+ * Concrete implementation of the Reader read()
+ * abstract method. This appears to be the only
+ * abstract method, so all of the other reads must
+ * funnel through this method.
+ *
+ * @param buffer The buffer to fill.
+ * @param off The offset to start adding characters.
+ * @param len The number of requested characters.
+ *
+ * @return The actual count of characters read. Returns -1
+ * if we hit an EOF without reading any characters.
+ * @exception IOException
+ */
+ public int read(char buffer[], int off, int len) throws IOException {
+ // we've been asked for nothing, we'll return nothing.
+ if (len == 0) {
+ return 0;
+ }
+
+ // have we hit the end of data? Return a -1 indicator
+ if (endOfData) {
+ return -1;
+ }
+
+ // number of bytes read
+ int bytesRead = 0;
+
+ int lastRead;
+
+ while (bytesRead < len && (lastRead = source.read()) >= 0) {
+ // We are checking for the end of a multiline response
+ // the format is .CRLF
+
+ // we also have to check for byte-stuffing situation
+ // where we remove a leading period.
+ if (atLineBreak && lastRead == '.') {
+ // step to the next character
+ lastRead = source.read();
+ // we have ".CR"...this is our end of stream
+ // marker. Consume the LF from the reader and return
+ if (lastRead == '\r') {
+ source.read();
+ // no more reads from this point.
+ endOfData = true;
+ break;
+ }
+ // the next character SHOULD be a ".". We swallow the first
+ // dot and just write the next character to the buffer
+ atLineBreak = false;
+ }
+ else if (lastRead == '\n') {
+ // hit an end-of-line marker?
+ // remember we just had a line break
+ atLineBreak = true;
+ }
+ else
+ {
+ // something other than a line break character
+ atLineBreak = false;
+ }
+ // add the character to the buffer
+ buffer[off++] = (char)lastRead;
+ bytesRead++;
+ }
+
+ // we must have had an EOF condition of some sort
+ if (bytesRead == 0) {
+ return -1;
+ }
+ // return the actual length read in
+ return bytesRead;
+ }
+
+ /**
+ * Close the stream. This is a NOP for this stream.
+ *
+ * @exception IOException
+ */
+ public void close() throws IOException {
+ // does nothing
+ }
+}
+
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEOutputStream.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEOutputStream.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEOutputStream.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEOutputStream.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,132 @@
+/*
+ * 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.geronimo.javamail.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An implementation of an OutputStream that performs MIME linebreak
+ * canonicalization and "byte-stuff" so that data content does not get mistaken
+ * for a message data-end marker (CRLF.CRLF)l
+ *
+ * @version $Rev$ $Date$
+ */
+public class MIMEOutputStream extends OutputStream {
+
+ // the wrappered output stream.
+ protected OutputStream out;
+
+ // last character we handled...used to recongnize line breaks.
+ protected int lastWrite = -1;
+
+ // a flag to indicate we've just processed a line break. This is used for
+ // byte stuffing purposes. This
+ // is initially true, because if the first character of the content is a
+ // period, we need to byte-stuff
+ // immediately.
+ protected boolean atLineBreak = true;
+
+ /**
+ * Create an output stream that writes to the target output stream.
+ *
+ * @param out
+ * The wrapped output stream.
+ */
+ public MIMEOutputStream(OutputStream out) {
+ this.out = out;
+ }
+
+ // in order for this to work, we only need override the single character
+ // form, as the others
+ // funnel through this one by default.
+ public void write(int ch) throws IOException {
+ // if this is a CR character, always write out a full sequence, and
+ // remember that we just did this.
+ if (ch == '\r') {
+ out.write((byte) '\r');
+ out.write((byte) '\n');
+ // we've just taken a break;
+ atLineBreak = true;
+ }
+ // if this is a new line, then we need to determine if this is a loner
+ // or part of a CRLF sequence.
+ else if (ch == '\n') {
+ // is this a lone ranger?
+ if (lastWrite != '\r') {
+ // write the full CRLF sequence.
+ out.write((byte) '\r');
+ out.write((byte) '\n');
+ }
+ // regardless of whether we wrote something or not, we're still at a
+ // line break.
+ atLineBreak = true;
+ }
+ // potential byte-stuffing situation?
+ else if (ch == '.') {
+ // ok, this is a potential stuff situation. Did we just have a line
+ // break? Double up the character.
+ if (atLineBreak) {
+ out.write('.');
+ }
+ out.write('.');
+ atLineBreak = false;
+ } else {
+ // just write this out and flip the linebreak flag.
+ out.write(ch);
+ atLineBreak = false;
+ }
+ // remember this last one for CRLF tracking purposes.
+ lastWrite = ch;
+ }
+
+
+ /**
+ * Force the stream to be terminated at a line break.
+ * This is generally in preparation for the transport to
+ * write out an end-of-data marker, which generally
+ * needs to be preceded by a CRLF sequence.
+ *
+ * @exception IOException
+ */
+ public void forceTerminatingLineBreak() throws IOException {
+ if (!atLineBreak) {
+ out.write((byte) '\r');
+ out.write((byte) '\n');
+ // we've just taken a break;
+ atLineBreak = true;
+ }
+ }
+
+
+ /**
+ * Write out the SMTP terminator to the output stream.
+ * This ensures that we don't write out an extra
+ * CRLF if the data terminates with that value.
+ *
+ * @exception IOException
+ */
+ public void writeSMTPTerminator() throws IOException {
+ forceTerminatingLineBreak();
+ out.write('.');
+ out.write('\r');
+ out.write('\n');
+ }
+}