public JilterStatus eom(JilterEOMActions eomActions, Properties properties) { logger.debug("jilter eom()"); try { bos.close(); // close stream } catch (IOException io) { logger.error("jilter failed to close io stream during eom", io); } byte[] messageBytes = bos.toByteArray(); bos = new ByteArrayOutputStream(); ByteArrayInputStream bis = new ByteArrayInputStream(messageBytes); try { logger.debug("jilter store callback execute"); Config.getStopBlockFactory() .detectBlock("milter server", Thread.currentThread(), this, IDLE_TIMEOUT); callback.store(bis, host); logger.debug("jilter store callback finished"); } catch (ArchiveException e) { logger.error("failed to store the message via milter", e); if (e.getRecoveryDirective() == ArchiveException.RecoveryDirective.REJECT) { logger.debug("jilter reject"); return JilterStatus.SMFIS_REJECT; } else if (e.getRecoveryDirective() == ArchiveException.RecoveryDirective.RETRYLATER) { logger.debug("jilter temp fail"); return JilterStatus.SMFIS_TEMPFAIL; } } catch (Throwable oome) { logger.error("failed to store message:" + oome.getMessage(), oome); return JilterStatus.SMFIS_REJECT; } finally { Config.getStopBlockFactory().endDetectBlock(Thread.currentThread()); } return JilterStatus.SMFIS_CONTINUE; }
public void handleRequest(SocketChannel socket, FetchMessageCallback callback) { this.socket = socket; this.callback = callback; includeBCC = false; rcpts = new ArrayList<String>(); bos = new ByteArrayOutputStream(); InetAddress address = socket.socket().getInetAddress(); boolean isAllowed = Config.getConfig().getAgent().isAllowed(address); if (!isAllowed) { logger.debug( "attempted milter connection from disallowed address. force disconnect {address='" + address.getHostAddress() + "'}"); try { socket.close(); } catch (IOException io) { logger.error("failed to close milter socket.", io); } return; } ByteBuffer dataBuffer = ByteBuffer.allocateDirect(4096); JilterProcessor processor = new JilterProcessor(this); try { while (processor.process(socket, (ByteBuffer) dataBuffer.flip())) { dataBuffer.compact(); if (this.socket.read(dataBuffer) == -1) { logger.debug("socket reports EOF, exiting read loop"); break; } } } catch (IOException e) { logger.debug("Unexpected exception, connection will be closed", e); } finally { logger.debug("closing processor"); processor.close(); logger.debug("processor closed"); try { logger.debug("closing socket"); this.socket.close(); logger.debug("socket closed"); } catch (IOException e) { logger.debug("Unexpected exception", e); } } }
public JilterStatus body(ByteBuffer bodyp) { logger.debug("jilter body()"); long maxMessageSizeMB = Config.getConfig().getArchiver().getMaxMessageSize(); long maxMessageSizeBytes = maxMessageSizeMB * 1024 * 1024; if (bodyp.array().length > maxMessageSizeBytes) { logger.warn( "milter maximum message size exceeded { size='" + bodyp.array().length + " bytes'}"); return JilterStatus.SMFIS_REJECT; } try { bos.write("\n".getBytes()); bos.write(bodyp.array()); } catch (IOException io) { logger.error("jilter failed to write milter body data to byte buffer", io); } logger.debug("jilter body written"); return JilterStatus.SMFIS_CONTINUE; }
public JilterStatus eoh() { logger.debug("jilter eoh()"); // includeBCC is false if RCPT TO does not contain at least one field in TO, FROM and CC // this is a safety check as sometimes, RCPT TO is something differently entirely // and does not contain the actual recipients in the email MilterServerService milterService = Config.getConfig().getMilterServerService(); if (milterService.getIncludeBCC() && includeBCC) { logger.debug("including BCC addresses"); // check to see if address is flagged to ignore if (rcpts.size() > 0) { Iterator<String> i = rcpts.iterator(); while (i.hasNext()) { String rcpt = i.next(); if (shouldIgnoreBCCAddress(rcpt)) { logger.debug("ignore include bcc address {address='" + rcpt + "'}"); i.remove(); } } } if (rcpts.size() > 0) { try { for (int j = 0; j < rcpts.size(); j++) { if (j == 0) { bos.write("bcc: ".getBytes()); } else { bos.write(",".getBytes()); } bos.write(rcpts.get(j).getBytes()); } bos.write("\n".getBytes()); } catch (IOException io) { logger.error("jilter failed to write end of header data", io); } } } return JilterStatus.SMFIS_CONTINUE; }
public JilterStatus header(String headerf, String headerv) { logger.debug("jilter header {name='" + headerf + "',value='" + headerv + "'}"); StringBuffer header = new StringBuffer(); header.append(headerf); header.append(": "); header.append(headerv); header.append("\n"); try { bos.write(header.toString().getBytes()); } catch (IOException io) { logger.error("jilter failed to write header field", io); } Matcher m = headerPattern1.matcher(headerf.toLowerCase(Locale.ENGLISH).trim()); if (m.matches()) { logger.debug("jilter found to/bcc/cc header"); String[] addresses = headerv.split(","); for (int i = 0; i < addresses.length; i++) { includeBCC = includeBCC | rcpts.remove(addresses[i].toLowerCase(Locale.ENGLISH).trim()); logger.debug("jilter del recipient {recipient='" + addresses[i] + "'}"); m = headerPattern2.matcher(addresses[i].toLowerCase(Locale.ENGLISH).trim()); if (m.matches()) { String mailAddress = m.group(1); includeBCC = includeBCC | rcpts.remove(mailAddress); logger.debug("jilter del recipient {recipient='" + mailAddress + "'}"); } else { m = headerPattern3.matcher(addresses[i].toLowerCase(Locale.ENGLISH).trim()); if (m.matches()) { String mailAddress = m.group(1); includeBCC = includeBCC | rcpts.remove(mailAddress); logger.debug("jilter del recipient {recipient='" + mailAddress + "'}"); } } } } return JilterStatus.SMFIS_CONTINUE; }