📄 smtptransport.java
字号:
try { closeConnection(); } catch (MessagingException mex) { } // ignore it } ///////////////////// smtp stuff /////////////////////// private BufferedInputStream serverInput; private LineInputStream lineInputStream; private OutputStream serverOutput; private Socket serverSocket; /////// smtp protocol ////// /** * Issue the <code>HELO</code> command. * * @param domain our domain * * @since JavaMail 1.4.1 */ protected void helo(String domain) throws MessagingException { if (domain != null) issueCommand("HELO " + domain, 250); else issueCommand("HELO", 250); } /** * Issue the <code>EHLO</code> command. * Collect the returned list of service extensions. * * @param domain our domain * @return true if command succeeds * * @since JavaMail 1.4.1 */ protected boolean ehlo(String domain) throws MessagingException { String cmd; if (domain != null) cmd = "EHLO " + domain; else cmd = "EHLO"; sendCommand(cmd); int resp = readServerResponse(); if (resp == 250) { // extract the supported service extensions BufferedReader rd = new BufferedReader(new StringReader(lastServerResponse)); String line; extMap = new Hashtable(); try { boolean first = true; while ((line = rd.readLine()) != null) { if (first) { // skip first line which is the greeting first = false; continue; } if (line.length() < 5) continue; // shouldn't happen line = line.substring(4); // skip response code int i = line.indexOf(' '); String arg = ""; if (i > 0) { arg = line.substring(i + 1); line = line.substring(0, i); } if (debug) out.println("DEBUG SMTP: Found extension \"" + line + "\", arg \"" + arg + "\""); extMap.put(line.toUpperCase(Locale.ENGLISH), arg); } } catch (IOException ex) { } // can't happen } return resp == 250; } /** * Issue the <code>MAIL FROM:</code> command to start sending a message. <p> * * Gets the sender's address in the following order: * <ol> * <li>SMTPMessage.getEnvelopeFrom()</li> * <li>mail.smtp.from property</li> * <li>From: header in the message</li> * <li>System username using the * InternetAddress.getLocalAddress() method</li> * </ol> * * @since JavaMail 1.4.1 */ protected void mailFrom() throws MessagingException { String from = null; if (message instanceof SMTPMessage) from = ((SMTPMessage)message).getEnvelopeFrom(); if (from == null || from.length() <= 0) from = session.getProperty("mail." + name + ".from"); if (from == null || from.length() <= 0) { Address[] fa; Address me; if (message != null && (fa = message.getFrom()) != null && fa.length > 0) me = fa[0]; else me = InternetAddress.getLocalAddress(session); if (me != null) from = ((InternetAddress)me).getAddress(); else throw new MessagingException( "can't determine local email address"); } String cmd = "MAIL FROM:" + normalizeAddress(from); // request delivery status notification? if (supportsExtension("DSN")) { String ret = null; if (message instanceof SMTPMessage) ret = ((SMTPMessage)message).getDSNRet(); if (ret == null) ret = session.getProperty("mail." + name + ".dsn.ret"); // XXX - check for legal syntax? if (ret != null) cmd += " RET=" + ret; } /* * If an RFC 2554 submitter has been specified, and the server * supports the AUTH extension, include the AUTH= element on * the MAIL FROM command. */ if (supportsExtension("AUTH")) { String submitter = null; if (message instanceof SMTPMessage) submitter = ((SMTPMessage)message).getSubmitter(); if (submitter == null) submitter = session.getProperty("mail." + name + ".submitter"); // XXX - check for legal syntax? if (submitter != null) { try { String s = xtext(submitter); cmd += " AUTH=" + s; } catch (IllegalArgumentException ex) { if (debug) out.println("DEBUG SMTP: ignoring invalid submitter: " + submitter + ", Exception: " + ex); } } } /* * Have any extensions to the MAIL command been specified? */ String ext = null; if (message instanceof SMTPMessage) ext = ((SMTPMessage)message).getMailExtension(); if (ext == null) ext = session.getProperty("mail." + name + ".mailextension"); if (ext != null && ext.length() > 0) cmd += " " + ext; issueSendCommand(cmd, 250); } /** * Sends each address to the SMTP host using the <code>RCPT TO:</code> * command and copies the address either into * the validSentAddr or invalidAddr arrays. * Sets the <code>sendFailed</code> * flag to true if any addresses failed. * * @since JavaMail 1.4.1 */ /* * success/failure/error possibilities from the RCPT command * from rfc821, section 4.3 * S: 250, 251 * F: 550, 551, 552, 553, 450, 451, 452 * E: 500, 501, 503, 421 * * and how we map the above error/failure conditions to valid/invalid * address vectors that are reported in the thrown exception: * invalid addr: 550, 501, 503, 551, 553 * valid addr: 552 (quota), 450, 451, 452 (quota), 421 (srvr abort) */ protected void rcptTo() throws MessagingException { Vector valid = new Vector(); Vector validUnsent = new Vector(); Vector invalid = new Vector(); int retCode = -1; MessagingException mex = null; boolean sendFailed = false; MessagingException sfex = null; validSentAddr = validUnsentAddr = invalidAddr = null; boolean sendPartial = false; if (message instanceof SMTPMessage) sendPartial = ((SMTPMessage)message).getSendPartial(); if (!sendPartial) { String sp = session.getProperty("mail." + name + ".sendpartial"); sendPartial = sp != null && sp.equalsIgnoreCase("true"); } if (debug && sendPartial) out.println("DEBUG SMTP: sendPartial set"); boolean dsn = false; String notify = null; if (supportsExtension("DSN")) { if (message instanceof SMTPMessage) notify = ((SMTPMessage)message).getDSNNotify(); if (notify == null) notify = session.getProperty("mail." + name + ".dsn.notify"); // XXX - check for legal syntax? if (notify != null) dsn = true; } // try the addresses one at a time for (int i = 0; i < addresses.length; i++) { sfex = null; InternetAddress ia = (InternetAddress)addresses[i]; String cmd = "RCPT TO:" + normalizeAddress(ia.getAddress()); if (dsn) cmd += " NOTIFY=" + notify; // send the addresses to the SMTP server sendCommand(cmd); // check the server's response for address validity retCode = readServerResponse(); switch (retCode) { case 250: case 251: valid.addElement(ia); if (!reportSuccess) break; // user wants exception even when successful, including // details of the return code // create and chain the exception sfex = new SMTPAddressSucceededException(ia, cmd, retCode, lastServerResponse); if (mex == null) mex = sfex; else mex.setNextException(sfex); break; case 550: case 553: case 503: case 551: case 501: // given address is invalid if (!sendPartial) sendFailed = true; invalid.addElement(ia); // create and chain the exception sfex = new SMTPAddressFailedException(ia, cmd, retCode, lastServerResponse); if (mex == null) mex = sfex; else mex.setNextException(sfex); break; case 552: case 450: case 451: case 452: // given address is valid if (!sendPartial) sendFailed = true; validUnsent.addElement(ia); // create and chain the exception sfex = new SMTPAddressFailedException(ia, cmd, retCode, lastServerResponse); if (mex == null) mex = sfex; else mex.setNextException(sfex); break; default: // handle remaining 4xy & 5xy codes if (retCode >= 400 && retCode <= 499) { // assume address is valid, although we don't really know validUnsent.addElement(ia); } else if (retCode >= 500 && retCode <= 599) { // assume address is invalid, although we don't really know invalid.addElement(ia); } else { // completely unexpected response, just give up if (debug) out.println("DEBUG SMTP: got response code " + retCode + ", with response: " + lastServerResponse); String _lsr = lastServerResponse; // else rset will nuke it int _lrc = lastReturnCode; if (serverSocket != null) // hasn't already been closed issueCommand("RSET", 250); lastServerResponse = _lsr; // restore, for get lastReturnCode = _lrc; throw new SMTPAddressFailedException(ia, cmd, retCode, _lsr); } if (!sendPartial) sendFailed = true; // create and chain the exception sfex = new SMTPAddressFailedException(ia, cmd, retCode, lastServerResponse); if (mex == null) mex = sfex; else mex.setNextException(sfex); break; } } // if we're willing to send to a partial list, and we found no // valid addresses, that's complete failure if (sendPartial && valid.size() == 0) sendFailed = true; // copy the vectors into appropriate arrays if (sendFailed) { // copy invalid addrs invalidAddr = new Address[invalid.size()]; invalid.copyInto(invalidAddr); // copy all valid addresses to validUnsent, since something failed validUnsentAddr = new Address[valid.size() + validUnsent.size()]; int i = 0; for (int j = 0; j < valid.size(); j++) validUnsentAddr[i++] = (Address)valid.elementAt(j); for (int j = 0; j < validUnsent.size(); j++) validUnsentAddr[i++] = (Address)validUnsent.elementAt(j); } else if (reportSuccess || (sendPartial && (invalid.size() > 0 || validUnsent.size() > 0))) { // we'll go on to send the message, but after sending we'll // throw an exception with this exception nested sendPartiallyFailed = true; exception = mex; // copy invalid addrs invalidAddr = new Address[invalid.size()]; invalid.copyInto(invalidAddr); // copy valid unsent addresses to validUnsent validUnsentAddr = new Address[validUnsent.size()]; validUnsent.copyInto(validUnsentAddr); // copy valid addresses to validSent validSentAddr = new Address[valid.size()]; valid.copyInto(validSentAddr); } else { // all addresses pass validSentAddr = addresses; } // print out the debug info if (debug) { if (validSentAddr != null && validSentAddr.length > 0) { out.println("DEBUG SMTP: Verified Addresses"); for (int l = 0; l < validSentAddr.length; l++) { out.println("DEBUG SMTP: " + validSentAddr[l]); } } if (validUnsentAddr != null && validUnsentAddr.length > 0) { out.println("DEBUG SMTP: Valid Unsent Addresses"); for (int j = 0; j < validUnsentAddr.length; j++) { out.println("DEBUG SMTP: " + validUnsentAddr[j]); } } if (invalidAddr != null && invalidAddr.length > 0) { out.println("DEBUG SMTP: Invalid Addresses"); for (int k = 0; k < invalidAddr.length; k++) { out.println("DEBUG SMTP: " + invalidAddr[k]); } } } // throw the exception, fire TransportEvent.MESSAGE_NOT_DELIVERED event if (sendFailed) { if (debug) out.println("DEBUG SMTP: Sending failed " + "because of invalid destination addresses"); notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, validSentAddr, validUnsentAddr, invalidAddr, this.message); // reset the connection so more sends are allowed String lsr = lastServerResponse; // save, for get int lrc = lastReturnCode; try { if (serverSocket != null) issueCommand("RSET", 250); } catch (MessagingException ex) { // if can't reset, best to close the connection try { close(); } catch (MessagingException ex2) { // thrown by close()--ignore, will close() later anyway if (debug) ex2.printStackTrace(out); } } finally { lastServerResponse = lsr; // restore lastReturnCode = lrc; } throw new SendFailedException("Invalid Addresses", mex, validSentAddr, validUnsentAddr, invalidAddr); } } /** * Send the <code>DATA</code> command to the SMTP host and return * an OutputStream to which the data is to be written. * * @since JavaMail 1.4.1 */ protected OutputStream data() throws MessagingException { assert Thread.holdsLock(this); issueSendCommand("DATA", 354); dataStream = new SMTPOutputStream(serverOutput); return dataStream; } /** * Terminate the sent data. * * @since JavaMail 1.4.1 */ protected void finishData() throws IOException, MessagingException { assert Thread.holdsLock(this); dataStream.ensureAtBOL(); issueSendCommand(".", 250); } /** * Issue the <code>STARTTLS</code> command and switch the socket to * TLS mode if it succeeds. * * @since JavaMail 1.4.1 */ protected void startTLS() throws MessagingException { issueCommand("STARTTLS", 220); // it worked, now switch the socket into TLS mode try { serverSocket = SocketFetcher.startTLS(serverSocket, session.getProperties(), "mail." + name); initStreams(); } catch (IOException ioex) { closeConnection();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -