📄 remotedelivery.java
字号:
if (sfe.getValidUnsentAddresses() != null) { Address[] address = sfe.getValidUnsentAddresses(); if (address.length > 0) { recipients.clear(); for (int i = 0; i < address.length; i++) { try { recipients.add(new MailAddress(address[i].toString())); } catch (ParseException pe) { // this should never happen ... we should have // caught malformed addresses long before we // got to this code. log("Can't parse unsent address: " + pe.getMessage()); } } if (isDebug) log("Unsent recipients: " + recipients); deleteMessage = failMessage(mail, sfe, false); } } return deleteMessage; } catch (MessagingException ex) { // We should do a better job checking this... if the failure is a general // connect exception, this is less descriptive than more specific SMTP command // failure... have to lookup and see what are the various Exception // possibilities // Unable to deliver message after numerous tries... fail accordingly // We check whether this is a 5xx error message, which // indicates a permanent failure (like account doesn't exist // or mailbox is full or domain is setup wrong). // We fail permanently if this was a 5xx error return failMessage(mail, ex, ('5' == ex.getMessage().charAt(0))); } /* If we get here, we've exhausted the loop of servers without * sending the message or throwing an exception. One case * where this might happen is if we get a MessagingException on * each transport.connect(), e.g., if there is only one server * and we get a connect exception. */ return failMessage(mail, new MessagingException("No mail server(s) available at this time."), false); } /** * Insert the method's description here. * Creation date: (2/25/00 1:14:18 AM) * @param mail org.apache.james.core.MailImpl * @param exception javax.mail.MessagingException * @param boolean permanent * @return boolean Whether the message failed fully and can be deleted */ private boolean failMessage(MailImpl mail, MessagingException ex, boolean permanent) { StringWriter sout = new StringWriter(); PrintWriter out = new PrintWriter(sout, true); if (permanent) { out.print("Permanent"); } else { out.print("Temporary"); } StringBuffer logBuffer = new StringBuffer(64) .append(" exception delivering mail (") .append(mail.getName()) .append(": "); out.print(logBuffer.toString()); ex.printStackTrace(out); log(sout.toString()); if (!permanent) { if (!mail.getState().equals(Mail.ERROR)) { mail.setState(Mail.ERROR); mail.setErrorMessage("0"); mail.setLastUpdated(new Date()); } int retries = Integer.parseInt(mail.getErrorMessage()); if (retries < maxRetries) { logBuffer = new StringBuffer(128) .append("Storing message ") .append(mail.getName()) .append(" into outgoing after ") .append(retries) .append(" retries"); log(logBuffer.toString()); ++retries; mail.setErrorMessage(retries + ""); mail.setLastUpdated(new Date()); return false; } else { logBuffer = new StringBuffer(128) .append("Bouncing message ") .append(mail.getName()) .append(" after ") .append(retries) .append(" retries"); log(logBuffer.toString()); } } if (bounceProcessor != null) { // do the new DSN bounce // setting attributes for DSN mailet mail.setAttribute("delivery-error", ex); mail.setState(bounceProcessor); // re-insert the mail into the spool for getting it passed to the dsn-processor MailetContext mc = getMailetContext(); try { mc.sendMail(mail); } catch (MessagingException e) { // we shouldn't get an exception, because the mail was already processed log("Exception re-inserting failed mail: ", e); } } else { // do an old style bounce bounce(mail, ex); } return true; } private void bounce(MailImpl mail, MessagingException ex) { StringWriter sout = new StringWriter(); PrintWriter out = new PrintWriter(sout, true); String machine = "[unknown]"; try { InetAddress me = InetAddress.getLocalHost(); machine = me.getHostName(); } catch(Exception e){ machine = "[address unknown]"; } StringBuffer bounceBuffer = new StringBuffer(128) .append("Hi. This is the James mail server at ") .append(machine) .append("."); out.println(bounceBuffer.toString()); out.println("I'm afraid I wasn't able to deliver your message to the following addresses."); out.println("This is a permanent error; I've given up. Sorry it didn't work out. Below"); out.println("I include the list of recipients and the reason why I was unable to deliver"); out.println("your message."); out.println(); for (Iterator i = mail.getRecipients().iterator(); i.hasNext(); ) { out.println(i.next()); } if (ex.getNextException() == null) { out.println(ex.getMessage().trim()); } else { Exception ex1 = ex.getNextException(); if (ex1 instanceof SendFailedException) { out.println("Remote mail server told me: " + ex1.getMessage().trim()); } else if (ex1 instanceof UnknownHostException) { out.println("Unknown host: " + ex1.getMessage().trim()); out.println("This could be a DNS server error, a typo, or a problem with the recipient's mail server."); } else if (ex1 instanceof ConnectException) { //Already formatted as "Connection timed out: connect" out.println(ex1.getMessage().trim()); } else if (ex1 instanceof SocketException) { out.println("Socket exception: " + ex1.getMessage().trim()); } else { out.println(ex1.getMessage().trim()); } } out.println(); out.println("The original message is attached."); log("Sending failure message " + mail.getName()); try { getMailetContext().bounce(mail, sout.toString()); } catch (MessagingException me) { log("Encountered unexpected messaging exception while bouncing message: " + me.getMessage()); } catch (Exception e) { log("Encountered unexpected exception while bouncing message: " + e.getMessage()); } } public String getMailetInfo() { return "RemoteDelivery Mailet"; } /** * For this message, we take the list of recipients, organize these into distinct * servers, and duplicate the message for each of these servers, and then call * the deliver (messagecontainer) method for each server-specific * messagecontainer ... that will handle storing it in the outgoing queue if needed. * * @param mail org.apache.mailet.Mail */ public void service(Mail genericmail) throws MessagingException{ MailImpl mail = (MailImpl)genericmail; // Do I want to give the internal key, or the message's Message ID if (isDebug) { log("Remotely delivering mail " + mail.getName()); } Collection recipients = mail.getRecipients(); if (gatewayServer == null) { // Must first organize the recipients into distinct servers (name made case insensitive) Hashtable targets = new Hashtable(); for (Iterator i = recipients.iterator(); i.hasNext();) { MailAddress target = (MailAddress)i.next(); String targetServer = target.getHost().toLowerCase(Locale.US); Collection temp = (Collection)targets.get(targetServer); if (temp == null) { temp = new ArrayList(); targets.put(targetServer, temp); } temp.add(target); } //We have the recipients organized into distinct servers... put them into the //delivery store organized like this... this is ultra inefficient I think... // Store the new message containers, organized by server, in the outgoing mail repository String name = mail.getName(); for (Iterator i = targets.keySet().iterator(); i.hasNext(); ) { String host = (String) i.next(); Collection rec = (Collection) targets.get(host); if (isDebug) { StringBuffer logMessageBuffer = new StringBuffer(128) .append("Sending mail to ") .append(rec) .append(" on host ") .append(host); log(logMessageBuffer.toString()); } mail.setRecipients(rec); StringBuffer nameBuffer = new StringBuffer(128) .append(name) .append("-to-") .append(host); mail.setName(nameBuffer.toString()); outgoing.store(mail); //Set it to try to deliver (in a separate thread) immediately (triggered by storage) } } else { // Store the mail unaltered for processing by the gateway server(s) if (isDebug) { StringBuffer logMessageBuffer = new StringBuffer(128) .append("Sending mail to ") .append(mail.getRecipients()) .append(" via ") .append(gatewayServer); log(logMessageBuffer.toString()); } //Set it to try to deliver (in a separate thread) immediately (triggered by storage) outgoing.store(mail); } mail.setState(Mail.GHOST); } // Need to synchronize to get object monitor for notifyAll() public synchronized void destroy() { //Mark flag so threads from this mailet stop themselves destroyed = true; //Wake up all threads from waiting for an accept for (Iterator i = deliveryThreads.iterator(); i.hasNext(); ) { Thread t = (Thread)i.next(); t.interrupt(); } notifyAll(); } /** * Handles checking the outgoing spool for new mail and delivering them if * there are any */ public void run() { /* TODO: CHANGE ME!!! The problem is that we need to wait for James to * finish initializing. We expect the HELLO_NAME to be put into * the MailetContext, but in the current configuration we get * started before the SMTP Server, which establishes the value. * Since there is no contractual guarantee that there will be a * HELLO_NAME value, we can't just wait for it. As a temporary * measure, I'm inserting this philosophically unsatisfactory * fix. */ long stop = System.currentTimeMillis() + 60000; while ((getMailetContext().getAttribute(Constants.HELLO_NAME) == null) && stop > System.currentTimeMillis()) { try { Thread.sleep(1000);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -